2021-04-17 15:20:24 +00:00
|
|
|
/*
|
2021-04-25 09:30:39 +00:00
|
|
|
* Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
|
2022-03-04 21:08:30 +00:00
|
|
|
* Copyright (c) 2022, the SerenityOS developers.
|
2021-04-17 15:20:24 +00:00
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2021-04-17 15:20:24 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <AK/Span.h>
|
2023-08-06 16:09:39 +00:00
|
|
|
#include <LibCore/EventReceiver.h>
|
2021-04-17 15:20:24 +00:00
|
|
|
#include <LibWebSocket/ConnectionInfo.h>
|
2022-02-04 10:43:30 +00:00
|
|
|
#include <LibWebSocket/Impl/WebSocketImpl.h>
|
2021-04-17 15:20:24 +00:00
|
|
|
#include <LibWebSocket/Message.h>
|
|
|
|
|
|
|
|
namespace WebSocket {
|
|
|
|
|
|
|
|
enum class ReadyState {
|
|
|
|
Connecting = 0,
|
|
|
|
Open = 1,
|
|
|
|
Closing = 2,
|
|
|
|
Closed = 3,
|
|
|
|
};
|
|
|
|
|
2024-10-15 12:18:28 +00:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1
|
|
|
|
enum class CloseStatusCode : u16 {
|
|
|
|
Normal = 1000,
|
|
|
|
GoingAway = 1001,
|
|
|
|
ProtocolError = 1002,
|
|
|
|
UnsupportedData = 1003,
|
|
|
|
AbnormalClosure = 1006,
|
|
|
|
InvalidPayload = 1007,
|
|
|
|
PolicyViolation = 1008,
|
|
|
|
MessageTooBig = 1009,
|
|
|
|
MissingExtension = 1010,
|
|
|
|
UnexpectedCondition = 1011,
|
|
|
|
};
|
|
|
|
|
2023-08-06 16:09:39 +00:00
|
|
|
class WebSocket final : public Core::EventReceiver {
|
2021-04-17 15:20:24 +00:00
|
|
|
C_OBJECT(WebSocket)
|
|
|
|
public:
|
2022-11-08 18:17:29 +00:00
|
|
|
static NonnullRefPtr<WebSocket> create(ConnectionInfo, RefPtr<WebSocketImpl> = nullptr);
|
2022-03-04 21:08:30 +00:00
|
|
|
virtual ~WebSocket() override = default;
|
2021-04-17 15:20:24 +00:00
|
|
|
|
2024-03-18 03:22:27 +00:00
|
|
|
URL::URL const& url() const { return m_connection.url(); }
|
2021-04-17 15:20:24 +00:00
|
|
|
|
|
|
|
ReadyState ready_state();
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString subprotocol_in_use();
|
2022-12-31 10:37:10 +00:00
|
|
|
|
2021-04-17 15:20:24 +00:00
|
|
|
// Call this to start the WebSocket connection.
|
|
|
|
void start();
|
|
|
|
|
|
|
|
// This can only be used if the `ready_state` is `ReadyState::Open`
|
2021-09-18 10:48:34 +00:00
|
|
|
void send(Message const&);
|
2021-04-17 15:20:24 +00:00
|
|
|
|
|
|
|
// This can only be used if the `ready_state` is `ReadyState::Open`
|
2023-12-16 14:19:34 +00:00
|
|
|
void close(u16 code = 1005, ByteString const& reason = {});
|
2021-04-17 15:20:24 +00:00
|
|
|
|
|
|
|
Function<void()> on_open;
|
2023-12-16 14:19:34 +00:00
|
|
|
Function<void(u16 code, ByteString reason, bool was_clean)> on_close;
|
2021-04-17 15:20:24 +00:00
|
|
|
Function<void(Message message)> on_message;
|
2024-09-18 08:28:55 +00:00
|
|
|
Function<void(ReadyState)> on_ready_state_change;
|
|
|
|
Function<void(ByteString)> on_subprotocol;
|
2021-04-17 15:20:24 +00:00
|
|
|
|
|
|
|
enum class Error {
|
|
|
|
CouldNotEstablishConnection,
|
|
|
|
ConnectionUpgradeFailed,
|
|
|
|
ServerClosedSocket,
|
|
|
|
};
|
|
|
|
|
|
|
|
Function<void(Error)> on_error;
|
|
|
|
|
|
|
|
private:
|
2022-11-08 18:17:29 +00:00
|
|
|
WebSocket(ConnectionInfo, RefPtr<WebSocketImpl>);
|
2021-04-17 15:20:24 +00:00
|
|
|
|
|
|
|
// As defined in section 5.2
|
|
|
|
enum class OpCode : u8 {
|
|
|
|
Continuation = 0x0,
|
|
|
|
Text = 0x1,
|
|
|
|
Binary = 0x2,
|
|
|
|
ConnectionClose = 0x8,
|
|
|
|
Ping = 0x9,
|
|
|
|
Pong = 0xA,
|
|
|
|
};
|
|
|
|
|
|
|
|
void drain_read();
|
|
|
|
|
|
|
|
void send_client_handshake();
|
|
|
|
void read_server_handshake();
|
|
|
|
|
|
|
|
void read_frame();
|
|
|
|
void send_frame(OpCode, ReadonlyBytes, bool is_final);
|
|
|
|
|
|
|
|
void notify_open();
|
2023-12-16 14:19:34 +00:00
|
|
|
void notify_close(u16 code, ByteString reason, bool was_clean);
|
2021-04-17 15:20:24 +00:00
|
|
|
void notify_error(Error);
|
|
|
|
void notify_message(Message);
|
|
|
|
|
|
|
|
void fatal_error(Error);
|
|
|
|
void discard_connection();
|
|
|
|
|
|
|
|
enum class InternalState {
|
|
|
|
NotStarted,
|
|
|
|
EstablishingProtocolConnection,
|
|
|
|
SendingClientHandshake,
|
|
|
|
WaitingForServerHandshake,
|
|
|
|
Open,
|
|
|
|
Closing,
|
|
|
|
Closed,
|
|
|
|
Errored,
|
|
|
|
};
|
|
|
|
|
|
|
|
InternalState m_state { InternalState::NotStarted };
|
|
|
|
|
2024-09-18 08:28:55 +00:00
|
|
|
void set_state(InternalState);
|
|
|
|
|
2024-10-15 12:18:28 +00:00
|
|
|
void fail_connection(u16 close_status_code, WebSocket::Error, ByteString const& reason);
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_subprotocol_in_use { ByteString::empty() };
|
2022-12-31 10:37:10 +00:00
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_websocket_key;
|
2021-04-17 15:20:24 +00:00
|
|
|
bool m_has_read_server_handshake_first_line { false };
|
|
|
|
bool m_has_read_server_handshake_upgrade { false };
|
|
|
|
bool m_has_read_server_handshake_connection { false };
|
|
|
|
bool m_has_read_server_handshake_accept { false };
|
|
|
|
|
2024-09-25 08:54:55 +00:00
|
|
|
bool m_discard_connection_requested { false };
|
|
|
|
|
2021-04-17 15:20:24 +00:00
|
|
|
u16 m_last_close_code { 1005 };
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_last_close_message;
|
2021-04-17 15:20:24 +00:00
|
|
|
|
|
|
|
ConnectionInfo m_connection;
|
2022-02-04 10:43:30 +00:00
|
|
|
RefPtr<WebSocketImpl> m_impl;
|
2022-11-08 18:57:44 +00:00
|
|
|
|
|
|
|
Vector<u8> m_buffered_data;
|
2023-09-03 02:38:45 +00:00
|
|
|
ByteBuffer m_fragmented_data_buffer;
|
|
|
|
WebSocket::OpCode m_initial_fragment_opcode;
|
2021-04-17 15:20:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|