ClientConnection.cpp 4.6 KB

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