WebSocket.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Base64.h>
  8. #include <AK/Random.h>
  9. #include <LibCrypto/Hash/HashManager.h>
  10. #include <LibWebSocket/Impl/WebSocketImplSerenity.h>
  11. #include <LibWebSocket/WebSocket.h>
  12. #include <unistd.h>
  13. namespace WebSocket {
  14. // Note : The websocket protocol is defined by RFC 6455, found at https://tools.ietf.org/html/rfc6455
  15. // In this file, section numbers will refer to the RFC 6455
  16. NonnullRefPtr<WebSocket> WebSocket::create(ConnectionInfo connection, RefPtr<WebSocketImpl> impl)
  17. {
  18. return adopt_ref(*new WebSocket(move(connection), move(impl)));
  19. }
  20. WebSocket::WebSocket(ConnectionInfo connection, RefPtr<WebSocketImpl> impl)
  21. : m_connection(move(connection))
  22. , m_impl(move(impl))
  23. {
  24. }
  25. void WebSocket::start()
  26. {
  27. VERIFY(m_state == WebSocket::InternalState::NotStarted);
  28. if (!m_impl)
  29. m_impl = adopt_ref(*new WebSocketImplSerenity);
  30. m_impl->on_connection_error = [this] {
  31. dbgln("WebSocket: Connection error (underlying socket)");
  32. fatal_error(WebSocket::Error::CouldNotEstablishConnection);
  33. };
  34. m_impl->on_connected = [this] {
  35. if (m_state != WebSocket::InternalState::EstablishingProtocolConnection)
  36. return;
  37. m_state = WebSocket::InternalState::SendingClientHandshake;
  38. send_client_handshake();
  39. drain_read();
  40. };
  41. m_impl->on_ready_to_read = [this] {
  42. drain_read();
  43. };
  44. m_state = WebSocket::InternalState::EstablishingProtocolConnection;
  45. m_impl->connect(m_connection);
  46. }
  47. ReadyState WebSocket::ready_state()
  48. {
  49. switch (m_state) {
  50. case WebSocket::InternalState::NotStarted:
  51. case WebSocket::InternalState::EstablishingProtocolConnection:
  52. case WebSocket::InternalState::SendingClientHandshake:
  53. case WebSocket::InternalState::WaitingForServerHandshake:
  54. return ReadyState::Connecting;
  55. case WebSocket::InternalState::Open:
  56. return ReadyState::Open;
  57. case WebSocket::InternalState::Closing:
  58. return ReadyState::Closing;
  59. case WebSocket::InternalState::Closed:
  60. case WebSocket::InternalState::Errored:
  61. return ReadyState::Closed;
  62. default:
  63. VERIFY_NOT_REACHED();
  64. return ReadyState::Closed;
  65. }
  66. }
  67. void WebSocket::send(Message const& message)
  68. {
  69. // Calling send on a socket that is not opened is not allowed
  70. VERIFY(m_state == WebSocket::InternalState::Open);
  71. VERIFY(m_impl);
  72. if (message.is_text())
  73. send_frame(WebSocket::OpCode::Text, message.data(), true);
  74. else
  75. send_frame(WebSocket::OpCode::Binary, message.data(), true);
  76. }
  77. void WebSocket::close(u16 code, String const& message)
  78. {
  79. VERIFY(m_impl);
  80. switch (m_state) {
  81. case InternalState::NotStarted:
  82. case InternalState::EstablishingProtocolConnection:
  83. case InternalState::SendingClientHandshake:
  84. case InternalState::WaitingForServerHandshake:
  85. // FIXME: Fail the connection.
  86. m_state = InternalState::Closing;
  87. break;
  88. case InternalState::Open: {
  89. auto message_bytes = message.bytes();
  90. auto close_payload = ByteBuffer::create_uninitialized(message_bytes.size() + 2).release_value_but_fixme_should_propagate_errors(); // FIXME: Handle possible OOM situation.
  91. close_payload.overwrite(0, (u8*)&code, 2);
  92. close_payload.overwrite(2, message_bytes.data(), message_bytes.size());
  93. send_frame(WebSocket::OpCode::ConnectionClose, close_payload, true);
  94. m_state = InternalState::Closing;
  95. break;
  96. }
  97. default:
  98. break;
  99. }
  100. }
  101. void WebSocket::drain_read()
  102. {
  103. if (m_impl->eof()) {
  104. // The connection got closed by the server
  105. m_state = WebSocket::InternalState::Closed;
  106. notify_close(m_last_close_code, m_last_close_message, true);
  107. discard_connection();
  108. return;
  109. }
  110. switch (m_state) {
  111. case InternalState::NotStarted:
  112. case InternalState::EstablishingProtocolConnection:
  113. case InternalState::SendingClientHandshake: {
  114. auto initializing_bytes = m_impl->read(1024);
  115. if (!initializing_bytes.is_error())
  116. dbgln("drain_read() was called on a websocket that isn't opened yet. Read {} bytes from the socket.", initializing_bytes.value().size());
  117. } break;
  118. case InternalState::WaitingForServerHandshake: {
  119. read_server_handshake();
  120. } break;
  121. case InternalState::Open:
  122. case InternalState::Closing: {
  123. auto result = m_impl->read(65536);
  124. if (result.is_error()) {
  125. fatal_error(WebSocket::Error::ServerClosedSocket);
  126. return;
  127. }
  128. auto bytes = result.release_value();
  129. m_buffered_data.append(bytes.data(), bytes.size());
  130. read_frame();
  131. } break;
  132. case InternalState::Closed:
  133. case InternalState::Errored: {
  134. auto closed_bytes = m_impl->read(1024);
  135. if (!closed_bytes.is_error())
  136. dbgln("drain_read() was called on a closed websocket. Read {} bytes from the socket.", closed_bytes.value().size());
  137. } break;
  138. default:
  139. VERIFY_NOT_REACHED();
  140. }
  141. }
  142. // The client handshake message is defined in the second list of section 4.1
  143. void WebSocket::send_client_handshake()
  144. {
  145. VERIFY(m_impl);
  146. VERIFY(m_state == WebSocket::InternalState::SendingClientHandshake);
  147. StringBuilder builder;
  148. // 2. and 3. GET /resource name/ HTTP 1.1
  149. builder.appendff("GET {} HTTP/1.1\r\n", m_connection.resource_name());
  150. // 4. Host
  151. auto url = m_connection.url();
  152. builder.appendff("Host: {}", url.host());
  153. if (!m_connection.is_secure() && url.port_or_default() != 80)
  154. builder.appendff(":{}", url.port_or_default());
  155. else if (m_connection.is_secure() && url.port_or_default() != 443)
  156. builder.appendff(":{}", url.port_or_default());
  157. builder.append("\r\n"sv);
  158. // 5. and 6. Connection Upgrade
  159. builder.append("Upgrade: websocket\r\n"sv);
  160. builder.append("Connection: Upgrade\r\n"sv);
  161. // 7. 16-byte nonce encoded as Base64
  162. u8 nonce_data[16];
  163. fill_with_random(nonce_data, 16);
  164. m_websocket_key = encode_base64(ReadonlyBytes(nonce_data, 16));
  165. builder.appendff("Sec-WebSocket-Key: {}\r\n", m_websocket_key);
  166. // 8. Origin (optional field)
  167. if (!m_connection.origin().is_empty()) {
  168. builder.appendff("Origin: {}\r\n", m_connection.origin());
  169. }
  170. // 9. Websocket version
  171. builder.append("Sec-WebSocket-Version: 13\r\n"sv);
  172. // 10. Websocket protocol (optional field)
  173. if (!m_connection.protocols().is_empty()) {
  174. builder.append("Sec-WebSocket-Protocol: "sv);
  175. builder.join(',', m_connection.protocols());
  176. builder.append("\r\n"sv);
  177. }
  178. // 11. Websocket extensions (optional field)
  179. if (!m_connection.extensions().is_empty()) {
  180. builder.append("Sec-WebSocket-Extensions: "sv);
  181. builder.join(',', m_connection.extensions());
  182. builder.append("\r\n"sv);
  183. }
  184. // 12. Additional headers
  185. for (auto& header : m_connection.headers()) {
  186. builder.appendff("{}: {}\r\n", header.name, header.value);
  187. }
  188. builder.append("\r\n"sv);
  189. m_state = WebSocket::InternalState::WaitingForServerHandshake;
  190. auto success = m_impl->send(builder.to_string().bytes());
  191. VERIFY(success);
  192. }
  193. // The server handshake message is defined in the third list of section 4.1
  194. void WebSocket::read_server_handshake()
  195. {
  196. VERIFY(m_impl);
  197. VERIFY(m_state == WebSocket::InternalState::WaitingForServerHandshake);
  198. // Read the server handshake
  199. if (!m_impl->can_read_line())
  200. return;
  201. if (!m_has_read_server_handshake_first_line) {
  202. auto header = m_impl->read_line(PAGE_SIZE).release_value_but_fixme_should_propagate_errors();
  203. auto parts = header.split(' ');
  204. if (parts.size() < 2) {
  205. dbgln("WebSocket: Server HTTP Handshake contained HTTP header was malformed");
  206. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  207. discard_connection();
  208. return;
  209. }
  210. if (parts[0] != "HTTP/1.1") {
  211. dbgln("WebSocket: Server HTTP Handshake contained HTTP header {} which isn't supported", parts[0]);
  212. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  213. discard_connection();
  214. return;
  215. }
  216. if (parts[1] != "101") {
  217. // 1. If the status code is not 101, handle as per HTTP procedures.
  218. // FIXME : This could be a redirect or a 401 authentication request, which we do not handle.
  219. dbgln("WebSocket: Server HTTP Handshake return status {} which isn't supported", parts[1]);
  220. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  221. return;
  222. }
  223. m_has_read_server_handshake_first_line = true;
  224. }
  225. // Read the rest of the reply until we find an empty line
  226. while (m_impl->can_read_line()) {
  227. auto line = m_impl->read_line(PAGE_SIZE).release_value_but_fixme_should_propagate_errors();
  228. if (line.is_whitespace()) {
  229. // We're done with the HTTP headers.
  230. // Fail the connection if we're missing any of the following:
  231. if (!m_has_read_server_handshake_upgrade) {
  232. // 2. |Upgrade| should be present
  233. dbgln("WebSocket: Server HTTP Handshake didn't contain an |Upgrade| header");
  234. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  235. return;
  236. }
  237. if (!m_has_read_server_handshake_connection) {
  238. // 2. |Connection| should be present
  239. dbgln("WebSocket: Server HTTP Handshake didn't contain a |Connection| header");
  240. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  241. return;
  242. }
  243. if (!m_has_read_server_handshake_accept) {
  244. // 2. |Sec-WebSocket-Accept| should be present
  245. dbgln("WebSocket: Server HTTP Handshake didn't contain a |Sec-WebSocket-Accept| header");
  246. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  247. return;
  248. }
  249. m_state = WebSocket::InternalState::Open;
  250. notify_open();
  251. return;
  252. }
  253. auto parts = line.split(':');
  254. if (parts.size() < 2) {
  255. // The header field is not valid
  256. dbgln("WebSocket: Got invalid header line {} in the Server HTTP handshake", line);
  257. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  258. return;
  259. }
  260. auto header_name = parts[0];
  261. if (header_name.equals_ignoring_case("Upgrade"sv)) {
  262. // 2. |Upgrade| should be case-insensitive "websocket"
  263. if (!parts[1].trim_whitespace().equals_ignoring_case("websocket"sv)) {
  264. dbgln("WebSocket: Server HTTP Handshake Header |Upgrade| should be 'websocket', got '{}'. Failing connection.", parts[1]);
  265. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  266. return;
  267. }
  268. m_has_read_server_handshake_upgrade = true;
  269. continue;
  270. }
  271. if (header_name.equals_ignoring_case("Connection"sv)) {
  272. // 3. |Connection| should be case-insensitive "Upgrade"
  273. if (!parts[1].trim_whitespace().equals_ignoring_case("Upgrade"sv)) {
  274. dbgln("WebSocket: Server HTTP Handshake Header |Connection| should be 'Upgrade', got '{}'. Failing connection.", parts[1]);
  275. return;
  276. }
  277. m_has_read_server_handshake_connection = true;
  278. continue;
  279. }
  280. if (header_name.equals_ignoring_case("Sec-WebSocket-Accept"sv)) {
  281. // 4. |Sec-WebSocket-Accept| should be base64(SHA1(|Sec-WebSocket-Key| + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
  282. auto expected_content = String::formatted("{}258EAFA5-E914-47DA-95CA-C5AB0DC85B11", m_websocket_key);
  283. Crypto::Hash::Manager hash;
  284. hash.initialize(Crypto::Hash::HashKind::SHA1);
  285. hash.update(expected_content);
  286. auto expected_sha1 = hash.digest();
  287. auto expected_sha1_string = encode_base64(ReadonlyBytes(expected_sha1.immutable_data(), expected_sha1.data_length()));
  288. if (!parts[1].trim_whitespace().equals_ignoring_case(expected_sha1_string)) {
  289. dbgln("WebSocket: Server HTTP Handshake Header |Sec-Websocket-Accept| should be '{}', got '{}'. Failing connection.", expected_sha1_string, parts[1]);
  290. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  291. return;
  292. }
  293. m_has_read_server_handshake_accept = true;
  294. continue;
  295. }
  296. if (header_name.equals_ignoring_case("Sec-WebSocket-Extensions"sv)) {
  297. // 5. |Sec-WebSocket-Extensions| should not contain an extension that doesn't appear in m_connection->extensions()
  298. auto server_extensions = parts[1].split(',');
  299. for (auto const& extension : server_extensions) {
  300. auto trimmed_extension = extension.trim_whitespace();
  301. bool found_extension = false;
  302. for (auto const& supported_extension : m_connection.extensions()) {
  303. if (trimmed_extension.equals_ignoring_case(supported_extension)) {
  304. found_extension = true;
  305. }
  306. }
  307. if (!found_extension) {
  308. dbgln("WebSocket: Server HTTP Handshake Header |Sec-WebSocket-Extensions| contains '{}', which is not supported by the client. Failing connection.", trimmed_extension);
  309. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  310. return;
  311. }
  312. }
  313. continue;
  314. }
  315. if (header_name.equals_ignoring_case("Sec-WebSocket-Protocol"sv)) {
  316. // 6. |Sec-WebSocket-Protocol| should not contain an extension that doesn't appear in m_connection->protocols()
  317. auto server_protocols = parts[1].split(',');
  318. for (auto const& protocol : server_protocols) {
  319. auto trimmed_protocol = protocol.trim_whitespace();
  320. bool found_protocol = false;
  321. for (auto const& supported_protocol : m_connection.protocols()) {
  322. if (trimmed_protocol.equals_ignoring_case(supported_protocol)) {
  323. found_protocol = true;
  324. }
  325. }
  326. if (!found_protocol) {
  327. dbgln("WebSocket: Server HTTP Handshake Header |Sec-WebSocket-Protocol| contains '{}', which is not supported by the client. Failing connection.", trimmed_protocol);
  328. fatal_error(WebSocket::Error::ConnectionUpgradeFailed);
  329. return;
  330. }
  331. }
  332. continue;
  333. }
  334. }
  335. // If needed, we will keep reading the header on the next drain_read call
  336. }
  337. void WebSocket::read_frame()
  338. {
  339. VERIFY(m_impl);
  340. VERIFY(m_state == WebSocket::InternalState::Open || m_state == WebSocket::InternalState::Closing);
  341. size_t cursor = 0;
  342. auto get_buffered_bytes = [&](size_t count) -> ReadonlyBytes {
  343. if (cursor + count > m_buffered_data.size())
  344. return {};
  345. auto bytes = m_buffered_data.span().slice(cursor, count);
  346. cursor += count;
  347. return bytes;
  348. };
  349. auto head_bytes = get_buffered_bytes(2);
  350. if (head_bytes.is_null() || head_bytes.is_empty()) {
  351. // The connection got closed.
  352. m_state = WebSocket::InternalState::Closed;
  353. notify_close(m_last_close_code, m_last_close_message, true);
  354. discard_connection();
  355. return;
  356. }
  357. bool is_final_frame = head_bytes[0] & 0x80;
  358. if (!is_final_frame) {
  359. // FIXME: Support fragmented frames
  360. TODO();
  361. }
  362. auto op_code = (WebSocket::OpCode)(head_bytes[0] & 0x0f);
  363. bool is_masked = head_bytes[1] & 0x80;
  364. // Parse the payload length.
  365. size_t payload_length;
  366. auto payload_length_bits = head_bytes[1] & 0x7f;
  367. if (payload_length_bits == 127) {
  368. // A code of 127 means that the next 8 bytes contains the payload length
  369. auto actual_bytes = get_buffered_bytes(8);
  370. if (actual_bytes.is_null())
  371. return;
  372. u64 full_payload_length = (u64)((u64)(actual_bytes[0] & 0xff) << 56)
  373. | (u64)((u64)(actual_bytes[1] & 0xff) << 48)
  374. | (u64)((u64)(actual_bytes[2] & 0xff) << 40)
  375. | (u64)((u64)(actual_bytes[3] & 0xff) << 32)
  376. | (u64)((u64)(actual_bytes[4] & 0xff) << 24)
  377. | (u64)((u64)(actual_bytes[5] & 0xff) << 16)
  378. | (u64)((u64)(actual_bytes[6] & 0xff) << 8)
  379. | (u64)((u64)(actual_bytes[7] & 0xff) << 0);
  380. VERIFY(full_payload_length <= NumericLimits<size_t>::max());
  381. payload_length = (size_t)full_payload_length;
  382. } else if (payload_length_bits == 126) {
  383. // A code of 126 means that the next 2 bytes contains the payload length
  384. auto actual_bytes = get_buffered_bytes(2);
  385. if (actual_bytes.is_null())
  386. return;
  387. payload_length = (size_t)((size_t)(actual_bytes[0] & 0xff) << 8)
  388. | (size_t)((size_t)(actual_bytes[1] & 0xff) << 0);
  389. } else {
  390. payload_length = (size_t)payload_length_bits;
  391. }
  392. // Parse the mask, if it exists.
  393. // Note : this is technically non-conformant with Section 5.1 :
  394. // > A server MUST NOT mask any frames that it sends to the client.
  395. // > A client MUST close a connection if it detects a masked frame.
  396. // > (These rules might be relaxed in a future specification.)
  397. // But because it doesn't cost much, we can support receiving masked frames anyways.
  398. u8 masking_key[4];
  399. if (is_masked) {
  400. auto masking_key_data = get_buffered_bytes(4);
  401. if (masking_key_data.is_null())
  402. return;
  403. masking_key[0] = masking_key_data[0];
  404. masking_key[1] = masking_key_data[1];
  405. masking_key[2] = masking_key_data[2];
  406. masking_key[3] = masking_key_data[3];
  407. }
  408. auto payload = ByteBuffer::create_uninitialized(payload_length).release_value_but_fixme_should_propagate_errors(); // FIXME: Handle possible OOM situation.
  409. u64 read_length = 0;
  410. while (read_length < payload_length) {
  411. auto payload_part = get_buffered_bytes(payload_length - read_length);
  412. if (payload_part.is_null())
  413. return;
  414. // We read at most "actual_length - read" bytes, so this is safe to do.
  415. payload.overwrite(read_length, payload_part.data(), payload_part.size());
  416. read_length += payload_part.size();
  417. }
  418. if (cursor == m_buffered_data.size()) {
  419. m_buffered_data.clear();
  420. } else {
  421. Vector<u8> new_buffered_data;
  422. new_buffered_data.append(m_buffered_data.data() + cursor, m_buffered_data.size() - cursor);
  423. m_buffered_data = move(new_buffered_data);
  424. }
  425. if (is_masked) {
  426. // Unmask the payload
  427. for (size_t i = 0; i < payload.size(); ++i) {
  428. payload[i] = payload[i] ^ (masking_key[i % 4]);
  429. }
  430. }
  431. if (op_code == WebSocket::OpCode::ConnectionClose) {
  432. if (payload.size() > 1) {
  433. m_last_close_code = (((u16)(payload[0] & 0xff) << 8) | ((u16)(payload[1] & 0xff)));
  434. m_last_close_message = String(ReadonlyBytes(payload.offset_pointer(2), payload.size() - 2));
  435. }
  436. m_state = WebSocket::InternalState::Closing;
  437. return;
  438. }
  439. if (op_code == WebSocket::OpCode::Ping) {
  440. // Immediately send a pong frame as a reply, with the given payload.
  441. send_frame(WebSocket::OpCode::Pong, payload, true);
  442. return;
  443. }
  444. if (op_code == WebSocket::OpCode::Pong) {
  445. // We can safely ignore the pong
  446. return;
  447. }
  448. if (op_code == WebSocket::OpCode::Continuation) {
  449. // FIXME: Support fragmented frames
  450. TODO();
  451. }
  452. if (op_code == WebSocket::OpCode::Text) {
  453. notify_message(Message(payload, true));
  454. return;
  455. }
  456. if (op_code == WebSocket::OpCode::Binary) {
  457. notify_message(Message(payload, false));
  458. return;
  459. }
  460. dbgln("Websocket: Found unknown opcode {}", (u8)op_code);
  461. }
  462. void WebSocket::send_frame(WebSocket::OpCode op_code, ReadonlyBytes payload, bool is_final)
  463. {
  464. VERIFY(m_impl);
  465. VERIFY(m_state == WebSocket::InternalState::Open);
  466. u8 frame_head[1] = { (u8)((is_final ? 0x80 : 0x00) | ((u8)(op_code)&0xf)) };
  467. m_impl->send(ReadonlyBytes(frame_head, 1));
  468. // Section 5.1 : a client MUST mask all frames that it sends to the server
  469. bool has_mask = true;
  470. // FIXME: If the payload has a size > size_t max on a 32-bit platform, we could
  471. // technically stream it via non-final packets. However, the size was already
  472. // truncated earlier in the call stack when stuffing into a ReadonlyBytes
  473. if (payload.size() > NumericLimits<u16>::max()) {
  474. // Send (the 'mask' flag + 127) + the 8-byte payload length
  475. if constexpr (sizeof(size_t) >= 8) {
  476. u8 payload_length[9] = {
  477. (u8)((has_mask ? 0x80 : 0x00) | 127),
  478. (u8)((payload.size() >> 56) & 0xff),
  479. (u8)((payload.size() >> 48) & 0xff),
  480. (u8)((payload.size() >> 40) & 0xff),
  481. (u8)((payload.size() >> 32) & 0xff),
  482. (u8)((payload.size() >> 24) & 0xff),
  483. (u8)((payload.size() >> 16) & 0xff),
  484. (u8)((payload.size() >> 8) & 0xff),
  485. (u8)((payload.size() >> 0) & 0xff),
  486. };
  487. m_impl->send(ReadonlyBytes(payload_length, 9));
  488. } else {
  489. u8 payload_length[9] = {
  490. (u8)((has_mask ? 0x80 : 0x00) | 127),
  491. 0,
  492. 0,
  493. 0,
  494. 0,
  495. (u8)((payload.size() >> 24) & 0xff),
  496. (u8)((payload.size() >> 16) & 0xff),
  497. (u8)((payload.size() >> 8) & 0xff),
  498. (u8)((payload.size() >> 0) & 0xff),
  499. };
  500. m_impl->send(ReadonlyBytes(payload_length, 9));
  501. }
  502. } else if (payload.size() >= 126) {
  503. // Send (the 'mask' flag + 126) + the 2-byte payload length
  504. u8 payload_length[3] = {
  505. (u8)((has_mask ? 0x80 : 0x00) | 126),
  506. (u8)((payload.size() >> 8) & 0xff),
  507. (u8)((payload.size() >> 0) & 0xff),
  508. };
  509. m_impl->send(ReadonlyBytes(payload_length, 3));
  510. } else {
  511. // Send the mask flag + the payload in a single byte
  512. u8 payload_length[1] = {
  513. (u8)((has_mask ? 0x80 : 0x00) | (u8)(payload.size() & 0x7f)),
  514. };
  515. m_impl->send(ReadonlyBytes(payload_length, 1));
  516. }
  517. if (has_mask) {
  518. // Section 10.3 :
  519. // > Clients MUST choose a new masking key for each frame, using an algorithm
  520. // > that cannot be predicted by end applications that provide data
  521. u8 masking_key[4];
  522. fill_with_random(masking_key, 4);
  523. m_impl->send(ReadonlyBytes(masking_key, 4));
  524. // don't try to send empty payload
  525. if (payload.size() == 0)
  526. return;
  527. // Mask the payload
  528. auto buffer_result = ByteBuffer::create_uninitialized(payload.size());
  529. if (!buffer_result.is_error()) {
  530. auto& masked_payload = buffer_result.value();
  531. for (size_t i = 0; i < payload.size(); ++i) {
  532. masked_payload[i] = payload[i] ^ (masking_key[i % 4]);
  533. }
  534. m_impl->send(masked_payload);
  535. }
  536. } else if (payload.size() > 0) {
  537. m_impl->send(payload);
  538. }
  539. }
  540. void WebSocket::fatal_error(WebSocket::Error error)
  541. {
  542. m_state = WebSocket::InternalState::Errored;
  543. notify_error(error);
  544. discard_connection();
  545. }
  546. void WebSocket::discard_connection()
  547. {
  548. deferred_invoke([this] {
  549. VERIFY(m_impl);
  550. m_impl->discard_connection();
  551. m_impl->on_connection_error = nullptr;
  552. m_impl->on_connected = nullptr;
  553. m_impl->on_ready_to_read = nullptr;
  554. m_impl = nullptr;
  555. });
  556. }
  557. void WebSocket::notify_open()
  558. {
  559. if (!on_open)
  560. return;
  561. on_open();
  562. }
  563. void WebSocket::notify_close(u16 code, String reason, bool was_clean)
  564. {
  565. if (!on_close)
  566. return;
  567. on_close(code, move(reason), was_clean);
  568. }
  569. void WebSocket::notify_error(WebSocket::Error error)
  570. {
  571. if (!on_error)
  572. return;
  573. on_error(error);
  574. }
  575. void WebSocket::notify_message(Message message)
  576. {
  577. if (!on_message)
  578. return;
  579. on_message(move(message));
  580. }
  581. }