ClientConnection.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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::ConnectResponse ClientConnection::connect(URL const& url, String const& origin,
  28. Vector<String> const& protocols, Vector<String> const& extensions, IPC::Dictionary const& additional_request_headers)
  29. {
  30. if (!url.is_valid()) {
  31. dbgln("WebSocket::Connect: Invalid URL requested: '{}'", url);
  32. return -1;
  33. }
  34. ConnectionInfo connection_info(url);
  35. connection_info.set_origin(origin);
  36. connection_info.set_protocols(protocols);
  37. connection_info.set_extensions(extensions);
  38. Vector<ConnectionInfo::Header> headers;
  39. for (auto const& header : additional_request_headers.entries()) {
  40. headers.append({ header.key, header.value });
  41. }
  42. connection_info.set_headers(headers);
  43. VERIFY(m_connection_ids < NumericLimits<i32>::max());
  44. auto id = ++m_connection_ids;
  45. auto connection = WebSocket::create(move(connection_info));
  46. connection->on_open = [this, id]() {
  47. did_connect(id);
  48. };
  49. connection->on_message = [this, id](auto message) {
  50. did_receive_message(id, move(message));
  51. };
  52. connection->on_error = [this, id](auto message) {
  53. did_error(id, (i32)message);
  54. };
  55. connection->on_close = [this, id](u16 code, String reason, bool was_clean) {
  56. did_close(id, code, move(reason), was_clean);
  57. };
  58. connection->start();
  59. m_connections.set(id, move(connection));
  60. return id;
  61. }
  62. Messages::WebSocketServer::ReadyStateResponse ClientConnection::ready_state(i32 connection_id)
  63. {
  64. RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
  65. if (connection) {
  66. return (u32)connection->ready_state();
  67. }
  68. return (u32)ReadyState::Closed;
  69. }
  70. void ClientConnection::send(i32 connection_id, bool is_text, ByteBuffer const& data)
  71. {
  72. RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
  73. if (connection && connection->ready_state() == ReadyState::Open) {
  74. Message websocket_message(data, is_text);
  75. connection->send(websocket_message);
  76. }
  77. }
  78. void ClientConnection::close(i32 connection_id, u16 code, String const& reason)
  79. {
  80. RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
  81. if (connection && connection->ready_state() == ReadyState::Open)
  82. connection->close(code, reason);
  83. }
  84. Messages::WebSocketServer::SetCertificateResponse ClientConnection::set_certificate(i32 connection_id,
  85. [[maybe_unused]] String const& certificate, [[maybe_unused]] String const& key)
  86. {
  87. RefPtr<WebSocket> connection = m_connections.get(connection_id).value_or({});
  88. bool success = false;
  89. if (connection) {
  90. // NO OP here
  91. // connection->set_certificate(certificate, key);
  92. success = true;
  93. }
  94. return success;
  95. }
  96. void ClientConnection::did_connect(i32 connection_id)
  97. {
  98. async_connected(connection_id);
  99. }
  100. void ClientConnection::did_receive_message(i32 connection_id, Message message)
  101. {
  102. async_received(connection_id, message.is_text(), message.data());
  103. }
  104. void ClientConnection::did_error(i32 connection_id, i32 message)
  105. {
  106. async_errored(connection_id, message);
  107. }
  108. void ClientConnection::did_close(i32 connection_id, u16 code, String reason, bool was_clean)
  109. {
  110. async_closed(connection_id, code, reason, was_clean);
  111. deferred_invoke([this, connection_id] {
  112. m_connections.remove(connection_id);
  113. });
  114. }
  115. void ClientConnection::did_request_certificates(i32 connection_id)
  116. {
  117. async_certificate_requested(connection_id);
  118. }
  119. }