2
3
6
7
11#include <restinio/exception.hpp>
12#include <restinio/websocket/message.hpp>
14#include <restinio/utils/impl/bitops.hpp>
70 size_t payload_len )
noexcept
74 init_payload_len( payload_len );
81 std::uint32_t masking_key )
87 init_payload_len( payload_len );
124
125
138
139
140
144 if( payload_len > websocket_max_payload_size_without_ext )
148 websocket_long_ext_len_code:
149 websocket_short_ext_len_code;
172 m_loaded_data.reserve( m_expected_size );
185 return m_loaded_data.size() == m_expected_size;
190
191
192
196 if( m_loaded_data.size() == m_expected_size )
197 throw exception_t("Cannot add one more bytes to expected data.");
199 m_loaded_data.push_back(
static_cast<raw_data_t::value_type>(byte));
208 m_expected_size = expected_size;
209 m_loaded_data.clear();
210 m_loaded_data.reserve( expected_size );
224 for(
const auto byte: data )
227 number |=
static_cast<std::uint8_t>( byte );
240 for(
auto i = 0 ; i < Bytes ; ++i )
242 auto shift_value = (Bytes - i - 1) * 8;
243 data.push_back(
static_cast<raw_data_t::value_type>(
244 (number >> shift_value) & 0xFF) );
254
255
256
257
258
267 size_t parsed_bytes = 0;
269 while( parsed_bytes < size &&
272 byte_t byte =
static_cast<
byte_t >( data[parsed_bytes] );
291
292
298 m_expected_data.reset( websocket_first_two_bytes_size );
312
313
335 if( m_expected_data.add_byte_and_check_size(byte) )
364
365
370 m_expected_data.m_loaded_data );
374 if( payload_len > websocket_max_payload_size_without_ext )
376 size_t expected_data_size = payload_len == websocket_short_ext_len_code?
377 websocket_short_ext_payload_length:
378 websocket_long_ext_payload_length;
380 m_expected_data.reset( expected_data_size );
386 size_t expected_data_size = websocket_masking_key_size;
387 m_expected_data.reset( expected_data_size );
393 size_t expected_data_size = payload_len;
394 m_expected_data.reset( expected_data_size );
402
403
407 parse_ext_payload_len(
408 m_current_msg.m_payload_len,
409 m_expected_data.m_loaded_data );
413 size_t expected_data_size = websocket_masking_key_size;
414 m_expected_data.reset( expected_data_size );
427
428
432 m_current_msg.m_mask_flag,
433 m_expected_data.m_loaded_data );
443 m_current_msg.m_final_flag = (data[0] & bit_flag_7) != 0;
444 m_current_msg.m_rsv1_flag = (data[0] & bit_flag_6) != 0;
445 m_current_msg.m_rsv2_flag = (data[0] & bit_flag_5) != 0;
446 m_current_msg.m_rsv3_flag = (data[0] & bit_flag_4) != 0;
448 m_current_msg.m_opcode =
static_cast< opcode_t >( data[0] & opcode_mask );
450 m_current_msg.m_mask_flag = (data[1] & bit_flag_7) != 0;
451 m_current_msg.m_payload_len = data[1] & payload_len_mask;
457 std::uint8_t payload_len,
460 if( payload_len == websocket_short_ext_len_code )
462 read_number_from_big_endian_bytes(
465 else if( payload_len == websocket_long_ext_len_code )
467 read_number_from_big_endian_bytes(
480 read_number_from_big_endian_bytes(
492 const std::size_t MASK_SIZE = 4;
493 const uint8_t mask[ MASK_SIZE ] = {
494 n_bits_from< std::uint8_t, 24 >(masking_key),
495 n_bits_from< std::uint8_t, 16 >(masking_key),
496 n_bits_from< std::uint8_t, 8 >(masking_key),
497 n_bits_from< std::uint8_t, 0 >(masking_key),
500 const auto payload_size = payload.size();
501 for( std::size_t i = 0; i < payload_size; )
503 for( std::size_t j = 0; j < MASK_SIZE && i < payload_size; ++j, ++i )
505 payload[ i ] ^= mask[ j ];
512
513
528 result.push_back(
static_cast<raw_data_t::value_type>(byte) );
540 result.push_back(
static_cast<raw_data_t::value_type>(byte) );
542 else if ( length == websocket_short_ext_len_code )
544 byte |= websocket_short_ext_len_code;
546 result.push_back(
static_cast<raw_data_t::value_type>(byte) );
553 else if ( length == websocket_long_ext_len_code )
555 byte |= websocket_long_ext_len_code;
557 result.push_back(
static_cast<raw_data_t::value_type>(byte) );
569 using ch_type = raw_data_t::value_type;
572 result.push_back( n_bits_from< ch_type, 24 >(key) );
573 result.push_back( n_bits_from< ch_type, 16 >(key) );
574 result.push_back( n_bits_from< ch_type, 8 >(key) );
575 result.push_back( n_bits_from< ch_type, 0 >(key) );
583
584
591 return write_message_details(
592 message_details_t{ final_flag, opcode, payload_len } );
597
598
604 std::uint32_t masking_key )
606 return write_message_details(
607 message_details_t{ final_flag, opcode, payload_len, masking_key } );
Exception class for all exceptions thrown by RESTinio.
exception_t(const char *err)
Websocket message class with more detailed protocol information.
std::uint64_t payload_len() const
Get payload len.
bool m_rsv1_flag
Reserved flags.
message_details_t()=default
std::uint32_t m_masking_key
Masking key.
std::uint8_t m_payload_len
Payload len.
message_details_t(final_frame_flag_t final_flag, opcode_t opcode, size_t payload_len, std::uint32_t masking_key)
std::uint64_t m_ext_payload_len
Ext payload len.
bool m_final_flag
Final flag.
message_details_t(final_frame_flag_t final_flag, opcode_t opcode, size_t payload_len) noexcept
void init_payload_len(size_t payload_len)
Initialize payload len.
bool m_mask_flag
Mask flag.
void set_masking_key(std::uint32_t value)
Set masking key.
void process_extended_length()
Process extended length.
message_details_t m_current_msg
Current websocket message details.
void reset()
Reset internal state.
const message_details_t & current_message() const
Get current mesasge details.
void process_byte(byte_t byte)
Process one byte of incoming buffer.
void parse_first_2_bytes(const raw_data_t &data)
Parse first two bytes of message from buffer.
void parse_ext_payload_len(std::uint8_t payload_len, const raw_data_t &data)
Parse extended length from buffer.
void parse_masking_key(bool mask_flag, const raw_data_t &data)
Parse masking key from buffer.
@ waiting_for_first_2_bytes
size_t parser_execute(const char *data, size_t size)
Parse piece of data from buffer.
void process_masking_key()
Process extended length.
bool header_parsed() const
Check header of current websocket message is parsed.
state_t m_current_state
Current state.
expected_data_t m_expected_data
Buffer for parts of websocket message with known size.
void process_first_2_bytes()
Process first two bytes of message.
void read_number_from_big_endian_bytes(T &number, const raw_data_t &data)
Read number from buffer with network bytes order.
void mask_unmask_payload(std::uint32_t masking_key, raw_data_t &payload)
Do msak/unmask operation with buffer.
constexpr byte_t bit_flag_7
constexpr size_t websocket_max_payload_size_without_ext
constexpr size_t websocket_long_ext_payload_length
raw_data_t write_message_details(const message_details_t &message)
Serialize websocket message details into bytes buffer.
constexpr size_t websocket_short_ext_len_code
constexpr byte_t bit_flag_5
constexpr byte_t payload_len_mask
constexpr byte_t bit_flag_4
constexpr size_t websocket_short_ext_payload_length
raw_data_t write_message_details(final_frame_flag_t final_flag, opcode_t opcode, size_t payload_len, std::uint32_t masking_key)
Serialize websocket message details into bytes buffer.
constexpr byte_t bit_flag_6
constexpr byte_t opcode_mask
constexpr size_t websocket_long_ext_len_code
raw_data_t write_message_details(final_frame_flag_t final_flag, opcode_t opcode, size_t payload_len)
Serialize websocket message details into bytes buffer.
constexpr size_t websocket_masking_key_size
constexpr size_t websocket_first_two_bytes_size
Websocket parser constants.
void write_number_to_big_endian_bytes(std::uint64_t &number, raw_data_t &data)
Save number to buffer with network bytes order.
unsigned char byte_t
Alias for byte.
constexpr final_frame_flag_t final_frame
std::string raw_data_t
Bytes buffer.
final_frame_flag_t
WS frame (message) "final"/"not final" flag.
bool add_byte_and_check_size(byte_t byte)
Try to add one more byte to loaded data and check loaded data size.
void reset(size_t expected_size)
Reset internal state on next expected data size.
bool all_bytes_loaded() const
Check all bytes are loaded.
expected_data_t()=default
expected_data_t(size_t expected_size)
size_t m_expected_size
Expected data size in bytes.
raw_data_t m_loaded_data
Buffer for accumulating data.