18 : tcp_socket_(std::move(socket))
19 , protocol_(is_client)
29 std::vector<uint8_t>(payload));
31 std::move(pong_frame),
32 [](std::error_code, std::size_t) {});
58 const std::string& path, uint16_t port,
59 std::function<
void(std::error_code)> handler)
63 auto handshake_request =
67 auto key_start = handshake_request.find(
"Sec-WebSocket-Key: ");
68 std::string client_key;
69 if (key_start != std::string::npos)
72 auto key_end = handshake_request.find(
"\r\n", key_start);
73 client_key = handshake_request.substr(key_start, key_end - key_start);
77 std::vector<uint8_t> request_data(handshake_request.begin(),
78 handshake_request.end());
80 tcp_socket_->async_send(
81 std::move(request_data),
82 [
this, client_key, handler](std::error_code ec, std::size_t)
92 tcp_socket_->set_receive_callback_view(
93 [
this, client_key, handler](std::span<const uint8_t> data)
96 std::string response(data.begin(), data.end());
100 response, client_key);
104 handler(std::make_error_code(std::errc::protocol_error));
112 tcp_socket_->set_receive_callback_view(
113 [
this](std::span<const uint8_t> data)
114 { on_tcp_receive(data); });
116 handler(std::error_code{});
120 tcp_socket_->start_read();
129 tcp_socket_->set_receive_callback_view(
130 [
this, handler](std::span<const uint8_t> data)
133 std::string request(data.begin(), data.end());
140 handler(std::make_error_code(std::errc::protocol_error));
145 auto it = result.headers.find(
"sec-websocket-key");
146 if (it == result.headers.end())
148 handler(std::make_error_code(std::errc::protocol_error));
152 std::string client_key = it->second;
156 std::vector<uint8_t> response_data(response.begin(), response.end());
159 tcp_socket_->async_send(
160 std::move(response_data),
161 [
this, handler](std::error_code ec, std::size_t)
173 tcp_socket_->set_receive_callback_view(
174 [
this](std::span<const uint8_t> data)
175 { on_tcp_receive(data); });
177 handler(std::error_code{});
182 tcp_socket_->start_read();
189 std::function<
void(std::error_code, std::size_t)> handler) ->
VoidResult
194 "WebSocket connection not open");
198 auto frame_data = protocol_.create_text_message(std::move(
message));
200 if (frame_data.empty())
203 "Invalid UTF-8 in text message");
207 tcp_socket_->async_send(std::move(frame_data), std::move(handler));
213 std::vector<uint8_t>&& data,
214 std::function<
void(std::error_code, std::size_t)> handler) ->
VoidResult
219 "WebSocket connection not open");
223 auto frame_data = protocol_.create_binary_message(std::move(data));
226 tcp_socket_->async_send(std::move(frame_data), std::move(handler));
232 std::vector<uint8_t> payload, std::function<
void(std::error_code)> handler)
236 auto frame_data = protocol_.create_ping(std::move(payload));
239 tcp_socket_->async_send(std::move(frame_data),
240 [handler](std::error_code ec, std::size_t)
250 std::function<
void(std::error_code)> handler)
257 auto frame_data = protocol_.create_close(code, std::string(reason));
260 tcp_socket_->async_send(std::move(frame_data),
261 [
this, handler](std::error_code ec, std::size_t)
276 handler(std::error_code{});
289 std::function<
void(
const ws_message&)> callback) ->
void
291 std::lock_guard<std::mutex> lock(callback_mutex_);
292 message_callback_ = std::move(callback);
296 std::function<
void(
const std::vector<uint8_t>&)> callback) ->
void
298 std::lock_guard<std::mutex> lock(callback_mutex_);
299 ping_callback_ = std::move(callback);
303 std::function<
void(
const std::vector<uint8_t>&)> callback) ->
void
305 std::lock_guard<std::mutex> lock(callback_mutex_);
306 pong_callback_ = std::move(callback);
310 std::function<
void(
ws_close_code,
const std::string&)> callback) ->
void
312 std::lock_guard<std::mutex> lock(callback_mutex_);
313 close_callback_ = std::move(callback);
317 std::function<
void(std::error_code)> callback) ->
void
319 std::lock_guard<std::mutex> lock(callback_mutex_);
320 error_callback_ = std::move(callback);
326 protocol_.process_data(data);
335 std::lock_guard<std::mutex> lock(callback_mutex_);
344 std::lock_guard<std::mutex> lock(callback_mutex_);
345 if (message_callback_)
347 message_callback_(msg);
354 std::lock_guard<std::mutex> lock(callback_mutex_);
357 ping_callback_(payload);
364 std::lock_guard<std::mutex> lock(callback_mutex_);
367 pong_callback_(payload);
372 const std::string& reason) ->
void
377 std::lock_guard<std::mutex> lock(callback_mutex_);
380 close_callback_(code, reason);
static auto create_server_response(const std::string &client_key) -> std::string
Creates a WebSocket handshake response (server-side).
static auto create_client_handshake(std::string_view host, std::string_view path, uint16_t port, const std::map< std::string, std::string > &extra_headers={}) -> std::string
Creates a WebSocket handshake request (client-side).
static auto validate_server_response(const std::string &response, const std::string &expected_key) -> ws_handshake_result
Validates a WebSocket handshake response (client-side).
static auto parse_client_request(const std::string &request) -> ws_handshake_result
Parses a WebSocket handshake request (server-side).
auto set_message_callback(std::function< void(const ws_message &)> callback) -> void
Sets the callback for data messages.
auto create_pong(std::vector< uint8_t > &&payload={}) -> std::vector< uint8_t >
Creates a pong control frame.
auto set_close_callback(std::function< void(ws_close_code, const std::string &)> callback) -> void
Sets the callback for close frames.
auto set_ping_callback(std::function< void(const std::vector< uint8_t > &)> callback) -> void
Sets the callback for ping frames.
auto set_pong_callback(std::function< void(const std::vector< uint8_t > &)> callback) -> void
Sets the callback for pong frames.
auto is_open() const -> bool
Checks if the connection is open and ready.
auto state() const -> ws_state
Gets the current connection state.
auto handle_protocol_ping(const std::vector< uint8_t > &payload) -> void
Handles a ping frame from the protocol layer.
std::shared_ptr< tcp_socket > tcp_socket_
auto set_error_callback(std::function< void(std::error_code)> callback) -> void
Sets the callback for errors.
auto async_send_binary(std::vector< uint8_t > &&data, std::function< void(std::error_code, std::size_t)> handler) -> VoidResult
Sends a binary message.
auto async_handshake(const std::string &host, const std::string &path, uint16_t port, std::function< void(std::error_code)> handler) -> void
Performs WebSocket client handshake (RFC 6455 Section 4.1).
~websocket_socket()
Destructor.
auto handle_protocol_message(const ws_message &msg) -> void
Handles a decoded message from the protocol layer.
auto on_tcp_receive(std::span< const uint8_t > data) -> void
Called by tcp_socket when data is received.
auto set_close_callback(std::function< void(ws_close_code, const std::string &)> callback) -> void
Sets the callback for received close frames.
websocket_socket(std::shared_ptr< tcp_socket > socket, bool is_client)
Constructs a websocket_socket wrapping an existing tcp_socket.
auto start_read() -> void
Starts reading WebSocket frames from the underlying socket.
auto async_accept(std::function< void(std::error_code)> handler) -> void
Accepts WebSocket server handshake (RFC 6455 Section 4.2).
websocket_protocol protocol_
std::atomic< ws_state > state_
auto handle_protocol_close(ws_close_code code, const std::string &reason) -> void
Handles a close frame from the protocol layer.
auto async_send_text(std::string &&message, std::function< void(std::error_code, std::size_t)> handler) -> VoidResult
Sends a text message (UTF-8 encoded).
auto async_send_ping(std::vector< uint8_t > payload, std::function< void(std::error_code)> handler) -> void
Sends a ping control frame.
auto set_message_callback(std::function< void(const ws_message &)> callback) -> void
Sets the callback for received messages.
auto async_close(ws_close_code code, const std::string &reason, std::function< void(std::error_code)> handler) -> void
Initiates the WebSocket closing handshake.
auto on_tcp_error(std::error_code ec) -> void
Called by tcp_socket when an error occurs.
auto set_ping_callback(std::function< void(const std::vector< uint8_t > &)> callback) -> void
Sets the callback for received ping frames.
auto set_pong_callback(std::function< void(const std::vector< uint8_t > &)> callback) -> void
Sets the callback for received pong frames.
auto handle_protocol_pong(const std::vector< uint8_t > &payload) -> void
Handles a pong frame from the protocol layer.
constexpr int invalid_argument
constexpr int connection_closed
ws_state
WebSocket connection state (RFC 6455 Section 7).
@ closed
Connection closed.
@ closing
Close handshake initiated.
@ open
Connection established and ready.
ws_close_code
WebSocket close status codes (RFC 6455 Section 7.4).
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
Represents a complete WebSocket message.