18 return std::string(
data.begin(),
data.end());
31 : is_client_(is_client)
39 buffer_.insert(buffer_.end(), data.begin(), data.end());
51 if (!header_opt.has_value())
57 const auto& header = header_opt.value();
60 const size_t header_size =
62 const size_t frame_size = header_size + header.payload_len;
65 if (buffer_.size() < frame_size)
75 buffer_.erase(buffer_.begin(), buffer_.begin() + frame_size);
81 handle_data_frame(header, payload);
85 handle_control_frame(header, payload);
91 const std::vector<uint8_t>& payload)
98 if (fragmented_message_.empty())
105 fragmented_message_.insert(fragmented_message_.end(), payload.begin(),
114 msg.
data = std::move(fragmented_message_);
120 fragmented_message_.clear();
125 fragmented_message_.clear();
129 if (message_callback_)
131 message_callback_(msg);
141 fragmented_type_ = header.opcode;
142 fragmented_message_ = payload;
160 if (message_callback_)
162 message_callback_(msg);
169 const std::vector<uint8_t>& payload)
180 if (header.payload_len > 125)
186 switch (header.opcode)
189 handle_ping(payload);
192 handle_pong(payload);
195 handle_close(payload);
207 ping_callback_(payload);
215 pong_callback_(payload);
224 if (payload.size() >= 2)
227 code =
static_cast<ws_close_code>((payload[0] << 8) | payload[1]);
230 if (payload.size() > 2)
232 reason = std::string(payload.begin() + 2, payload.end());
235 std::vector<uint8_t> reason_bytes(reason.begin(), reason.end());
236 if (!is_valid_utf8(reason_bytes))
247 close_callback_(code, reason);
252 -> std::vector<uint8_t>
255 std::vector<uint8_t> payload(
text.begin(),
text.end());
258 if (!is_valid_utf8(payload))
270 -> std::vector<uint8_t>
277 -> std::vector<uint8_t>
280 if (payload.size() > 125)
290 -> std::vector<uint8_t>
293 if (payload.size() > 125)
303 -> std::vector<uint8_t>
305 std::vector<uint8_t> payload;
308 payload.push_back(
static_cast<uint8_t
>((
static_cast<uint16_t
>(code) >> 8) & 0xFF));
309 payload.push_back(
static_cast<uint8_t
>(
static_cast<uint16_t
>(code) & 0xFF));
315 std::vector<uint8_t> reason_bytes(reason.begin(), reason.end());
316 if (is_valid_utf8(reason_bytes))
318 payload.insert(payload.end(), reason.begin(), reason.end());
323 if (payload.size() > 125)
333 std::function<
void(
const ws_message&)> callback) ->
void
335 message_callback_ = std::move(callback);
339 std::function<
void(
const std::vector<uint8_t>&)> callback) ->
void
341 ping_callback_ = std::move(callback);
345 std::function<
void(
const std::vector<uint8_t>&)> callback) ->
void
347 pong_callback_ = std::move(callback);
351 std::function<
void(
ws_close_code,
const std::string&)> callback) ->
void
353 close_callback_ = std::move(callback);
359 while (i < data.size())
361 uint8_t
byte = data[i];
364 int bytes_to_follow = 0;
366 if ((
byte & 0x80) == 0x00)
371 else if ((
byte & 0xE0) == 0xC0)
376 else if ((
byte & 0xF0) == 0xE0)
381 else if ((
byte & 0xF8) == 0xF0)
393 if (i + bytes_to_follow >= data.size())
399 for (
int j = 1; j <= bytes_to_follow; ++j)
401 if ((data[i + j] & 0xC0) != 0x80)
408 i += bytes_to_follow + 1;
static auto encode_frame(ws_opcode opcode, std::vector< uint8_t > &&payload, bool fin=true, bool mask=false) -> std::vector< uint8_t >
Encodes data into a WebSocket frame.
static auto decode_payload(const ws_frame_header &header, const std::vector< uint8_t > &data) -> std::vector< uint8_t >
Decodes the payload from a WebSocket frame.
static auto calculate_header_size(uint64_t payload_len, bool mask) -> size_t
Calculates the size of the frame header.
static auto decode_header(const std::vector< uint8_t > &data) -> std::optional< ws_frame_header >
Decodes a WebSocket frame header from raw data.
auto handle_ping(const std::vector< uint8_t > &payload) -> void
Handles a ping frame.
auto handle_pong(const std::vector< uint8_t > &payload) -> void
Handles a pong frame.
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 create_close(ws_close_code code, std::string &&reason="") -> std::vector< uint8_t >
Creates a close control frame.
static auto is_valid_utf8(const std::vector< uint8_t > &data) -> bool
Validates UTF-8 encoding.
auto handle_close(const std::vector< uint8_t > &payload) -> void
Handles a close frame.
auto create_ping(std::vector< uint8_t > &&payload={}) -> std::vector< uint8_t >
Creates a ping control frame.
auto handle_data_frame(const ws_frame_header &header, const std::vector< uint8_t > &payload) -> void
Handles a data frame (text or binary).
websocket_protocol(bool is_client)
Constructs a WebSocket protocol handler.
auto process_frames() -> void
Processes incoming frames from the buffer.
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 create_text_message(std::string &&text) -> std::vector< uint8_t >
Creates a text message frame.
auto create_binary_message(std::vector< uint8_t > &&data) -> std::vector< uint8_t >
Creates a binary message frame.
auto handle_control_frame(const ws_frame_header &header, const std::vector< uint8_t > &payload) -> void
Handles a control frame (ping, pong, close).
auto set_pong_callback(std::function< void(const std::vector< uint8_t > &)> callback) -> void
Sets the callback for pong frames.
auto process_data(std::span< const uint8_t > data) -> void
Processes incoming WebSocket data.
@ text
Text message (UTF-8 encoded)
ws_opcode
WebSocket frame operation codes as defined in RFC 6455.
@ text
Text frame (UTF-8 encoded)
@ close
Connection close frame.
@ continuation
Continuation frame.
ws_close_code
WebSocket close status codes (RFC 6455 Section 7.4).
@ protocol_error
Protocol error.
Represents a complete WebSocket message.
auto as_binary() const -> const std::vector< uint8_t > &
Returns message data as binary (reference).
ws_message_type type
Message type.
std::vector< uint8_t > data
Message payload.
auto as_text() const -> std::string
Converts message data to string (for text messages).