Serenity Operating System
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
8#pragma once
9
10#include <AK/Span.h>
11#include <LibCore/Object.h>
12#include <LibWebSocket/ConnectionInfo.h>
13#include <LibWebSocket/Impl/WebSocketImpl.h>
14#include <LibWebSocket/Message.h>
15
16namespace WebSocket {
17
18enum class ReadyState {
19 Connecting = 0,
20 Open = 1,
21 Closing = 2,
22 Closed = 3,
23};
24
25class WebSocket final : public Core::Object {
26 C_OBJECT(WebSocket)
27public:
28 static NonnullRefPtr<WebSocket> create(ConnectionInfo, RefPtr<WebSocketImpl> = nullptr);
29 virtual ~WebSocket() override = default;
30
31 URL const& url() const { return m_connection.url(); }
32
33 ReadyState ready_state();
34
35 DeprecatedString subprotocol_in_use();
36
37 // Call this to start the WebSocket connection.
38 void start();
39
40 // This can only be used if the `ready_state` is `ReadyState::Open`
41 void send(Message const&);
42
43 // This can only be used if the `ready_state` is `ReadyState::Open`
44 void close(u16 code = 1005, DeprecatedString const& reason = {});
45
46 Function<void()> on_open;
47 Function<void(u16 code, DeprecatedString reason, bool was_clean)> on_close;
48 Function<void(Message message)> on_message;
49
50 enum class Error {
51 CouldNotEstablishConnection,
52 ConnectionUpgradeFailed,
53 ServerClosedSocket,
54 };
55
56 Function<void(Error)> on_error;
57
58private:
59 WebSocket(ConnectionInfo, RefPtr<WebSocketImpl>);
60
61 // As defined in section 5.2
62 enum class OpCode : u8 {
63 Continuation = 0x0,
64 Text = 0x1,
65 Binary = 0x2,
66 ConnectionClose = 0x8,
67 Ping = 0x9,
68 Pong = 0xA,
69 };
70
71 void drain_read();
72
73 void send_client_handshake();
74 void read_server_handshake();
75
76 void read_frame();
77 void send_frame(OpCode, ReadonlyBytes, bool is_final);
78
79 void notify_open();
80 void notify_close(u16 code, DeprecatedString reason, bool was_clean);
81 void notify_error(Error);
82 void notify_message(Message);
83
84 void fatal_error(Error);
85 void discard_connection();
86
87 enum class InternalState {
88 NotStarted,
89 EstablishingProtocolConnection,
90 SendingClientHandshake,
91 WaitingForServerHandshake,
92 Open,
93 Closing,
94 Closed,
95 Errored,
96 };
97
98 InternalState m_state { InternalState::NotStarted };
99
100 DeprecatedString m_subprotocol_in_use { DeprecatedString::empty() };
101
102 DeprecatedString m_websocket_key;
103 bool m_has_read_server_handshake_first_line { false };
104 bool m_has_read_server_handshake_upgrade { false };
105 bool m_has_read_server_handshake_connection { false };
106 bool m_has_read_server_handshake_accept { false };
107
108 u16 m_last_close_code { 1005 };
109 DeprecatedString m_last_close_message;
110
111 ConnectionInfo m_connection;
112 RefPtr<WebSocketImpl> m_impl;
113
114 Vector<u8> m_buffered_data;
115};
116
117}