1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 21:45:08 +00:00
serenity/Userland/Services/WebSocket/ConnectionFromClient.cpp
Linus Groh 6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00

135 lines
4.3 KiB
C++

/*
* Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWebSocket/ConnectionInfo.h>
#include <LibWebSocket/Message.h>
#include <WebSocket/ConnectionFromClient.h>
#include <WebSocket/WebSocketClientEndpoint.h>
namespace WebSocket {
static HashMap<int, RefPtr<ConnectionFromClient>> s_connections;
ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket)
: IPC::ConnectionFromClient<WebSocketClientEndpoint, WebSocketServerEndpoint>(*this, move(socket), 1)
{
s_connections.set(1, *this);
}
void ConnectionFromClient::die()
{
s_connections.remove(client_id());
if (s_connections.is_empty())
Core::EventLoop::current().quit(0);
}
Messages::WebSocketServer::ConnectResponse ConnectionFromClient::connect(URL const& url, DeprecatedString const& origin,
Vector<DeprecatedString> const& protocols, Vector<DeprecatedString> const& extensions, IPC::Dictionary const& additional_request_headers)
{
if (!url.is_valid()) {
dbgln("WebSocket::Connect: Invalid URL requested: '{}'", url);
return -1;
}
ConnectionInfo connection_info(url);
connection_info.set_origin(origin);
connection_info.set_protocols(protocols);
connection_info.set_extensions(extensions);
Vector<ConnectionInfo::Header> headers;
for (auto const& header : additional_request_headers.entries()) {
headers.append({ header.key, header.value });
}
connection_info.set_headers(headers);
VERIFY(m_connection_ids < NumericLimits<i32>::max());
auto id = ++m_connection_ids;
auto connection = WebSocket::create(move(connection_info));
connection->on_open = [this, id]() {
did_connect(id);
};
connection->on_message = [this, id](auto message) {
did_receive_message(id, move(message));
};
connection->on_error = [this, id](auto message) {
did_error(id, (i32)message);
};
connection->on_close = [this, id](u16 code, DeprecatedString reason, bool was_clean) {
did_close(id, code, move(reason), was_clean);
};
connection->start();
m_connections.set(id, move(connection));
return id;
}
Messages::WebSocketServer::ReadyStateResponse ConnectionFromClient::ready_state(i32 connection_id)
{
RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
if (connection) {
return (u32)connection->ready_state();
}
return (u32)ReadyState::Closed;
}
void ConnectionFromClient::send(i32 connection_id, bool is_text, ByteBuffer const& data)
{
RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
if (connection && connection->ready_state() == ReadyState::Open) {
Message websocket_message(data, is_text);
connection->send(websocket_message);
}
}
void ConnectionFromClient::close(i32 connection_id, u16 code, DeprecatedString const& reason)
{
RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
if (connection && connection->ready_state() == ReadyState::Open)
connection->close(code, reason);
}
Messages::WebSocketServer::SetCertificateResponse ConnectionFromClient::set_certificate(i32 connection_id,
[[maybe_unused]] DeprecatedString const& certificate, [[maybe_unused]] DeprecatedString const& key)
{
RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
bool success = false;
if (connection) {
// NO OP here
// connection->set_certificate(certificate, key);
success = true;
}
return success;
}
void ConnectionFromClient::did_connect(i32 connection_id)
{
async_connected(connection_id);
}
void ConnectionFromClient::did_receive_message(i32 connection_id, Message message)
{
async_received(connection_id, message.is_text(), message.data());
}
void ConnectionFromClient::did_error(i32 connection_id, i32 message)
{
async_errored(connection_id, message);
}
void ConnectionFromClient::did_close(i32 connection_id, u16 code, DeprecatedString reason, bool was_clean)
{
async_closed(connection_id, code, reason, was_clean);
deferred_invoke([this, connection_id] {
m_connections.remove(connection_id);
});
}
void ConnectionFromClient::did_request_certificates(i32 connection_id)
{
async_certificate_requested(connection_id);
}
}