Serenity Operating System
at master 144 lines 4.7 kB view raw
1/* 2 * Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibWebSocket/ConnectionInfo.h> 8#include <LibWebSocket/Message.h> 9#include <WebSocket/ConnectionFromClient.h> 10#include <WebSocket/WebSocketClientEndpoint.h> 11 12namespace WebSocket { 13 14static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; 15 16ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) 17 : IPC::ConnectionFromClient<WebSocketClientEndpoint, WebSocketServerEndpoint>(*this, move(socket), 1) 18{ 19 s_connections.set(1, *this); 20} 21 22void ConnectionFromClient::die() 23{ 24 s_connections.remove(client_id()); 25 if (s_connections.is_empty()) 26 Core::EventLoop::current().quit(0); 27} 28 29Messages::WebSocketServer::ConnectResponse ConnectionFromClient::connect(URL const& url, DeprecatedString const& origin, 30 Vector<DeprecatedString> const& protocols, Vector<DeprecatedString> const& extensions, IPC::Dictionary const& additional_request_headers) 31{ 32 if (!url.is_valid()) { 33 dbgln("WebSocket::Connect: Invalid URL requested: '{}'", url); 34 return -1; 35 } 36 37 ConnectionInfo connection_info(url); 38 connection_info.set_origin(origin); 39 connection_info.set_protocols(protocols); 40 connection_info.set_extensions(extensions); 41 42 Vector<ConnectionInfo::Header> headers; 43 for (auto const& header : additional_request_headers.entries()) { 44 headers.append({ header.key, header.value }); 45 } 46 connection_info.set_headers(headers); 47 48 VERIFY(m_connection_ids < NumericLimits<i32>::max()); 49 auto id = ++m_connection_ids; 50 auto connection = WebSocket::create(move(connection_info)); 51 connection->on_open = [this, id]() { 52 did_connect(id); 53 }; 54 connection->on_message = [this, id](auto message) { 55 did_receive_message(id, move(message)); 56 }; 57 connection->on_error = [this, id](auto message) { 58 did_error(id, (i32)message); 59 }; 60 connection->on_close = [this, id](u16 code, DeprecatedString reason, bool was_clean) { 61 did_close(id, code, move(reason), was_clean); 62 }; 63 64 connection->start(); 65 m_connections.set(id, move(connection)); 66 return id; 67} 68 69Messages::WebSocketServer::ReadyStateResponse ConnectionFromClient::ready_state(i32 connection_id) 70{ 71 RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({}); 72 if (connection) { 73 return (u32)connection->ready_state(); 74 } 75 return (u32)ReadyState::Closed; 76} 77 78Messages::WebSocketServer::SubprotocolInUseResponse ConnectionFromClient::subprotocol_in_use(i32 connection_id) 79{ 80 RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({}); 81 if (connection) { 82 return connection->subprotocol_in_use(); 83 } 84 return DeprecatedString::empty(); 85} 86 87void ConnectionFromClient::send(i32 connection_id, bool is_text, ByteBuffer const& data) 88{ 89 RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({}); 90 if (connection && connection->ready_state() == ReadyState::Open) { 91 Message websocket_message(data, is_text); 92 connection->send(websocket_message); 93 } 94} 95 96void ConnectionFromClient::close(i32 connection_id, u16 code, DeprecatedString const& reason) 97{ 98 RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({}); 99 if (connection && connection->ready_state() == ReadyState::Open) 100 connection->close(code, reason); 101} 102 103Messages::WebSocketServer::SetCertificateResponse ConnectionFromClient::set_certificate(i32 connection_id, 104 [[maybe_unused]] DeprecatedString const& certificate, [[maybe_unused]] DeprecatedString const& key) 105{ 106 RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({}); 107 bool success = false; 108 if (connection) { 109 // NO OP here 110 // connection->set_certificate(certificate, key); 111 success = true; 112 } 113 return success; 114} 115 116void ConnectionFromClient::did_connect(i32 connection_id) 117{ 118 async_connected(connection_id); 119} 120 121void ConnectionFromClient::did_receive_message(i32 connection_id, Message message) 122{ 123 async_received(connection_id, message.is_text(), message.data()); 124} 125 126void ConnectionFromClient::did_error(i32 connection_id, i32 message) 127{ 128 async_errored(connection_id, message); 129} 130 131void ConnectionFromClient::did_close(i32 connection_id, u16 code, DeprecatedString reason, bool was_clean) 132{ 133 async_closed(connection_id, code, reason, was_clean); 134 deferred_invoke([this, connection_id] { 135 m_connections.remove(connection_id); 136 }); 137} 138 139void ConnectionFromClient::did_request_certificates(i32 connection_id) 140{ 141 async_certificate_requested(connection_id); 142} 143 144}