28 #ifndef WEBSOCKETPP_FRAME_HPP
29 #define WEBSOCKETPP_FRAME_HPP
33 #include <websocketpp/common/system_error.hpp>
34 #include <websocketpp/common/network.hpp>
36 #include <websocketpp/utilities.hpp>
118 return (v >= rsv3 && v <= rsv7) ||
119 (v >= control_rsvb && v <= control_rsvf);
130 return (v > 0xF || v < 0);
173 static uint8_t
const BHB0_OPCODE = 0x0F;
174 static uint8_t
const BHB0_RSV3 = 0x10;
175 static uint8_t
const BHB0_RSV2 = 0x20;
176 static uint8_t
const BHB0_RSV1 = 0x40;
177 static uint8_t
const BHB0_FIN = 0x80;
179 static uint8_t
const BHB1_PAYLOAD = 0x7F;
180 static uint8_t
const BHB1_MASK = 0x80;
182 static uint8_t
const payload_size_code_16bit = 0x7E;
183 static uint8_t
const payload_size_code_64bit = 0x7F;
191 basic_header(uint8_t p0, uint8_t p1) : b0(p0), b1(p1) {}
193 basic_header(opcode::value op, uint64_t size,
bool fin,
bool mask,
194 bool rsv1 =
false,
bool rsv2 =
false,
bool rsv3 =
false) : b0(0x00),
209 b0 |= (op & BHB0_OPCODE);
218 basic_value =
static_cast<uint8_t
>(size);
220 basic_value = payload_size_code_16bit;
222 basic_value = payload_size_code_64bit;
236 std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
240 std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
242 copy_payload(payload_size);
246 std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
249 int offset = copy_payload(payload_size);
253 temp32.i = masking_key;
254 std::copy(temp32.c,temp32.c+4,bytes+offset);
259 int copy_payload(uint64_t payload_size) {
260 int payload_offset = 0;
269 temp64.i = lib::net::htonll(payload_size);
270 std::copy(temp64.c+payload_offset,temp64.c+8,bytes);
272 return 8-payload_offset;
301 template <
typename input_iter,
typename output_iter>
302 void byte_mask(input_iter b, input_iter e, output_iter o, masking_key_type
303 const & key,
size_t key_offset = 0);
304 template <
typename iter_type>
305 void byte_mask(iter_type b, iter_type e, masking_key_type
const & key,
306 size_t key_offset = 0);
308 masking_key_type
const & key);
309 void word_mask_exact(uint8_t * data,
size_t length, masking_key_type
const &
311 size_t word_mask_circ(uint8_t * input, uint8_t * output,
size_t length,
312 size_t prepared_key);
313 size_t word_mask_circ(uint8_t * data,
size_t length,
size_t prepared_key);
321 return ((h.b0 & BHB0_FIN) == BHB0_FIN);
330 h.b0 = (value ? h.b0 | BHB0_FIN : h.b0 & ~BHB0_FIN);
339 return ((h.b0 & BHB0_RSV1) == BHB0_RSV1);
348 h.b0 = (value ? h.b0 | BHB0_RSV1 : h.b0 & ~BHB0_RSV1);
357 return ((h.b0 & BHB0_RSV2) == BHB0_RSV2);
366 h.b0 = (value ? h.b0 | BHB0_RSV2 : h.b0 & ~BHB0_RSV2);
375 return ((h.b0 & BHB0_RSV3) == BHB0_RSV3);
384 h.b0 = (value ? h.b0 | BHB0_RSV3 : h.b0 & ~BHB0_RSV3);
393 return opcode::value(h.b0 & BHB0_OPCODE);
402 return ((h.b1 & BHB1_MASK) == BHB1_MASK);
411 h.b1 = (value ? h.b1 | BHB1_MASK : h.b1 & ~BHB1_MASK);
431 return h.b1 & BHB1_PAYLOAD;
473 basic_value =
static_cast<uint8_t
>(size);
475 basic_value = payload_size_code_16bit;
477 basic_value = payload_size_code_64bit;
480 return lib::error_code();
483 h.b1 = (basic_value & BHB1_PAYLOAD) | (h.b1 & BHB1_MASK);
485 return lib::error_code();
522 ret.push_back(
char(h.b0));
523 ret.push_back(
char(h.b1));
525 reinterpret_cast<const char*>(e.bytes),
547 masking_key_type temp32;
553 std::copy(e.bytes+offset,e.bytes+offset+4,temp32.c);
570 std::copy(e.bytes,e.bytes+2,temp16.c);
571 return ntohs(temp16.i);
585 std::copy(e.bytes,e.bytes+8,temp64.c);
586 return lib::net::ntohll(temp64.i);
608 }
else if (val == payload_size_code_16bit) {
624 size_t low_bits =
static_cast<size_t>(key.i);
626 if (
sizeof(
size_t) == 8) {
627 uint64_t high_bits =
static_cast<size_t>(key.i);
628 return static_cast<size_t>((high_bits << 32) | low_bits);
641 if (lib::net::is_little_endian()) {
642 size_t temp = prepared_key << (
sizeof(size_t)-offset)*8;
643 return (prepared_key >> offset*8) | temp;
645 size_t temp = prepared_key >> (
sizeof(size_t)-offset)*8;
646 return (prepared_key << offset*8) | temp;
669 template <
typename input_iter,
typename output_iter>
670 void byte_mask(input_iter first, input_iter last, output_iter result,
671 masking_key_type
const & key,
size_t key_offset)
673 size_t key_index = key_offset%4;
674 while (first != last) {
675 *result = *first ^ key.c[key_index++];
699 template <
typename iter_type>
700 void byte_mask(iter_type b, iter_type e, masking_key_type
const & key,
728 const masking_key_type& key)
731 size_t n = length/
sizeof(size_t);
732 size_t* input_word =
reinterpret_cast<size_t*
>(input);
733 size_t* output_word =
reinterpret_cast<size_t*
>(output);
735 for (
size_t i = 0; i < n; i++) {
736 output_word[i] = input_word[i] ^ prepared_key;
739 for (
size_t i = n*
sizeof(
size_t); i < length; i++) {
740 output[i] = input[i] ^ key.c[i%4];
757 masking_key_type& key)
796 size_t n = length /
sizeof(size_t);
797 size_t l = length - (n *
sizeof(size_t));
798 size_t * input_word =
reinterpret_cast<size_t *
>(input);
799 size_t * output_word =
reinterpret_cast<size_t *
>(output);
802 for (
size_t i = 0; i < n; i++) {
803 output_word[i] = input_word[i] ^ prepared_key;
807 size_t start = length - l;
808 uint8_t * byte_key =
reinterpret_cast<uint8_t *
>(&prepared_key);
809 for (
size_t i = 0; i < l; ++i) {
810 output[start+i] = input[start+i] ^ byte_key[i];
859 key.i = prepared_key;
861 for (
size_t i = 0; i < length; ++i) {
862 output[i] = input[i] ^ key.c[i % 4];
889 #endif //WEBSOCKETPP_FRAME_HPP
bool is_control(value v)
Check if an opcode is for a control frame.
bool invalid(value v)
Check if an opcode is invalid.
bool get_rsv1(basic_header const &h)
check whether the frame's RSV1 bit is set
uint16_t value
The type of a close code value.
void set_rsv1(basic_header &h, bool value)
Set the frame's RSV1 bit.
bool get_rsv3(basic_header const &h)
check whether the frame's RSV3 bit is set
bool get_masked(basic_header const &h)
check whether the frame is masked
uint16_t get_extended_size(extended_header const &)
Extract the extended size field from an extended header.
bool get_rsv2(basic_header const &h)
check whether the frame's RSV2 bit is set
static unsigned int const max_header_length
Maximum length of a WebSocket header.
opcode::value get_opcode(basic_header const &h)
Extract opcode from basic header.
static uint8_t const payload_size_basic
Maximum size of a basic WebSocket payload.
masking_key_type get_masking_key(basic_header const &, extended_header const &)
Extract the masking key from a frame header.
Eight byte conversion union.
Two byte conversion union.
Four byte conversion union.
lib::error_code set_size(basic_header &h, extended_header &eh, uint64_t size)
Set the frame's size.
void byte_mask(input_iter b, input_iter e, output_iter o, masking_key_type const &key, size_t key_offset=0)
Byte by byte mask/unmask.
static uint64_t const payload_size_jumbo
Maximum size of a jumbo WebSocket payload (basic payload = 127)
size_t get_header_len(basic_header const &)
Calculates the full length of the header based on the first bytes.
size_t circshift_prepared_key(size_t prepared_key, size_t offset)
circularly shifts the supplied prepared masking key by offset bytes
static unsigned int const basic_header_length
Minimum length of a WebSocket frame header.
size_t word_mask_circ(uint8_t *input, uint8_t *output, size_t length, size_t prepared_key)
Circular word aligned mask/unmask.
void word_mask_exact(uint8_t *input, uint8_t *output, size_t length, masking_key_type const &key)
Exact word aligned mask/unmask.
size_t prepare_masking_key(masking_key_type const &key)
Extract a masking key into a value the size of a machine word.
uint8_t get_basic_size(basic_header const &)
Extracts the raw payload length specified in the basic header.
uint64_t get_jumbo_size(extended_header const &)
Extract the jumbo size field from an extended header.
Namespace for the WebSocket++ project.
uint64_t get_payload_size(basic_header const &, extended_header const &)
Extract the full payload size field from a WebSocket header.
static unsigned int const MAX_EXTENDED_HEADER_LENGTH
Maximum length of the variable portion of the WebSocket header.
unsigned int get_masking_key_offset(basic_header const &)
Calculate the offset location of the masking key within the extended header.
static unsigned int const max_extended_header_length
Maximum length of the variable portion of the WebSocket header.
static unsigned int const MAX_HEADER_LENGTH
Maximum length of a WebSocket header.
void set_masked(basic_header &h, bool value)
Set the frame's MASK bit.
std::string prepare_header(const basic_header &h, const extended_header &e)
Generate a properly sized contiguous string that encodes a full frame header.
static uint16_t const payload_size_extended
Maximum size of an extended WebSocket payload (basic payload = 126)
size_t byte_mask_circ(uint8_t *input, uint8_t *output, size_t length, size_t prepared_key)
Circular byte aligned mask/unmask.
static uint8_t const close_reason_size
Maximum size of close frame reason.
void set_fin(basic_header &h, bool value)
Set the frame's FIN bit.
bool reserved(value v)
Check if an opcode is reserved.
bool get_fin(basic_header const &h)
Check whether the frame's FIN bit is set.
void set_rsv2(basic_header &h, bool value)
Set the frame's RSV2 bit.
static unsigned int const BASIC_HEADER_LENGTH
Minimum length of a WebSocket frame header.
void set_rsv3(basic_header &h, bool value)
Set the frame's RSV3 bit.