28#ifndef WEBSOCKETPP_FRAME_HPP
29#define WEBSOCKETPP_FRAME_HPP
48static unsigned int const BASIC_HEADER_LENGTH = 2;
50static unsigned int const MAX_HEADER_LENGTH = 14;
52static unsigned int const MAX_EXTENDED_HEADER_LENGTH = 12;
131 return (v > 0xF || v < 0);
147 static unsigned int const basic_header_length = 2;
150 static unsigned int const max_header_length = 14;
153 static unsigned int const max_extended_header_length = 12;
156 static uint8_t const payload_size_basic = 125;
159 static uint16_t const payload_size_extended = 0xFFFF;
162 static uint64_t const payload_size_jumbo = 0x7FFFFFFFFFFFFFFFLL;
169 static uint8_t const close_reason_size = 123;
174static uint8_t const BHB0_OPCODE = 0x0F;
175static uint8_t const BHB0_RSV3 = 0x10;
176static uint8_t const BHB0_RSV2 = 0x20;
177static uint8_t const BHB0_RSV1 = 0x40;
178static uint8_t const BHB0_FIN = 0x80;
180static uint8_t const BHB1_PAYLOAD = 0x7F;
181static uint8_t const BHB1_MASK = 0x80;
183static uint8_t const payload_size_code_16bit = 0x7E;
184static uint8_t const payload_size_code_64bit = 0x7F;
195 bool rsv1 =
false,
bool rsv2 =
false,
bool rsv3 =
false) :
b0(0x00),
210 b0 |= (
op & BHB0_OPCODE);
218 if (size <= limits::payload_size_basic) {
219 basic_value =
static_cast<uint8_t>(size);
220 }
else if (size <= limits::payload_size_extended) {
221 basic_value = payload_size_code_16bit;
223 basic_value = payload_size_code_64bit;
237 std::fill_n(this->
bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
241 std::fill_n(this->
bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
243 copy_payload(payload_size);
247 std::fill_n(this->
bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
250 int offset = copy_payload(payload_size);
254 temp32.
i = masking_key;
255 std::copy(temp32.
c,temp32.
c+4,
bytes+offset);
260 int copy_payload(
uint64_t payload_size) {
261 int payload_offset = 0;
263 if (payload_size <= limits::payload_size_basic) {
265 }
else if (payload_size <= limits::payload_size_extended) {
271 std::copy(temp64.
c+payload_offset,temp64.
c+8,
bytes);
273 return 8-payload_offset;
277bool get_fin(basic_header
const &h);
279bool get_rsv1(basic_header
const &h);
281bool get_rsv2(basic_header
const &h);
283bool get_rsv3(basic_header
const &h);
302template <
typename input_iter,
typename output_iter>
304 const & key,
size_t key_offset = 0);
305template <
typename iter_type>
307 size_t key_offset = 0);
313 size_t prepared_key);
322 return ((h.
b0 & BHB0_FIN) == BHB0_FIN);
331 h.
b0 = (
value ? h.
b0 | BHB0_FIN : h.
b0 & ~BHB0_FIN);
340 return ((h.
b0 & BHB0_RSV1) == BHB0_RSV1);
349 h.
b0 = (
value ? h.
b0 | BHB0_RSV1 : h.
b0 & ~BHB0_RSV1);
358 return ((h.
b0 & BHB0_RSV2) == BHB0_RSV2);
367 h.
b0 = (
value ? h.
b0 | BHB0_RSV2 : h.
b0 & ~BHB0_RSV2);
376 return ((h.
b0 & BHB0_RSV3) == BHB0_RSV3);
385 h.
b0 = (
value ? h.
b0 | BHB0_RSV3 : h.
b0 & ~BHB0_RSV3);
403 return ((h.
b1 & BHB1_MASK) == BHB1_MASK);
412 h.
b1 = (
value ? h.
b1 | BHB1_MASK : h.
b1 & ~BHB1_MASK);
432 return h.
b1 & BHB1_PAYLOAD;
494 ret.push_back(
char(h.
b0));
495 ret.push_back(
char(h.
b1));
497 reinterpret_cast<const char*
>(e.
bytes),
525 std::copy(e.
bytes+offset,e.
bytes+offset+4,temp32.
c);
543 return ntohs(temp16.
i);
578 if (val <= limits::payload_size_basic) {
580 }
else if (val == payload_size_code_16bit) {
596 size_t low_bits =
static_cast<size_t>(key.i);
598 if (
sizeof(
size_t) == 8) {
599 uint64_t high_bits =
static_cast<size_t>(key.i);
600 return static_cast<size_t>((high_bits << 32) | low_bits);
614 size_t temp = prepared_key << (
sizeof(size_t)-offset)*8;
615 return (prepared_key >> offset*8) | temp;
617 size_t temp = prepared_key >> (
sizeof(size_t)-offset)*8;
618 return (prepared_key << offset*8) | temp;
641template <
typename input_iter,
typename output_iter>
642void byte_mask(input_iter first, input_iter last, output_iter result,
645 size_t key_index = key_offset%4;
646 while (first != last) {
647 *result = *first ^ key.c[key_index++];
671template <
typename iter_type>
703 size_t n = length/
sizeof(size_t);
704 size_t* input_word =
reinterpret_cast<size_t*
>(input);
705 size_t* output_word =
reinterpret_cast<size_t*
>(output);
707 for (
size_t i = 0; i < n; i++) {
708 output_word[i] = input_word[i] ^ prepared_key;
711 for (
size_t i = n*
sizeof(
size_t); i < length; i++) {
712 output[i] = input[i] ^ key.c[i%4];
768 size_t n = length /
sizeof(size_t);
769 size_t l = length - (n *
sizeof(size_t));
770 size_t * input_word =
reinterpret_cast<size_t *
>(input);
771 size_t * output_word =
reinterpret_cast<size_t *
>(output);
774 for (
size_t i = 0; i < n; i++) {
775 output_word[i] = input_word[i] ^ prepared_key;
779 size_t start = length -
l;
781 for (
size_t i = 0; i <
l; ++i) {
782 output[start+i] = input[start+i] ^ byte_key[i];
831 key.
i = prepared_key;
833 for (
size_t i = 0; i < length; ++i) {
834 output[i] = input[i] ^ key.c[i % 4];
bool invalid(value v)
Check if an opcode is invalid.
bool is_control(value v)
Check if an opcode is for a control frame.
unsigned int get_masking_key_offset(basic_header const &)
Calculate the offset location of the masking key within the extended header.
void set_rsv2(basic_header &h, bool value)
Set the frame's RSV2 bit.
opcode::value get_opcode(basic_header const &h)
Extract opcode from basic header.
void set_rsv3(basic_header &h, bool value)
Set the frame's RSV3 bit.
uint64_t get_payload_size(basic_header const &, extended_header const &)
Extract the full payload size field from a WebSocket header.
uint8_t get_basic_size(basic_header const &)
Extracts the raw payload length specified in the basic header.
size_t byte_mask_circ(uint8_t *input, uint8_t *output, size_t length, size_t prepared_key)
Circular byte aligned mask/unmask.
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.
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
std::string write_header(basic_header const &, extended_header const &)
bool get_rsv2(basic_header const &h)
check whether the frame's RSV2 bit is set
uint16_t get_extended_size(extended_header const &)
Extract the extended size field from an extended header.
bool get_fin(basic_header const &h)
Check whether the frame's FIN bit is set.
size_t circshift_prepared_key(size_t prepared_key, size_t offset)
circularly shifts the supplied prepared masking key by offset bytes
uint32_converter masking_key_type
bool get_rsv1(basic_header const &h)
check whether the frame's RSV1 bit is set
void set_masked(basic_header &h, bool value)
Set the frame's MASK bit.
size_t word_mask_circ(uint8_t *input, uint8_t *output, size_t length, size_t prepared_key)
Circular word aligned mask/unmask.
void set_rsv1(basic_header &h, bool value)
Set the frame's RSV1 bit.
size_t get_header_len(basic_header const &)
Calculates the full length of the header based on the first bytes.
void set_fin(basic_header &h, bool value)
Set the frame's FIN bit.
uint64_t get_jumbo_size(extended_header const &)
Extract the jumbo size field from an extended header.
void word_mask_exact(uint8_t *input, uint8_t *output, size_t length, masking_key_type const &key)
Exact word aligned mask/unmask.
std::string prepare_header(const basic_header &h, const extended_header &e)
Generate a properly sized contiguous string that encodes a full frame header.
masking_key_type get_masking_key(basic_header const &, extended_header const &)
Extract the masking key from a frame header.
size_t prepare_masking_key(masking_key_type const &key)
Extract a masking key into a value the size of a machine word.
uint64_t _htonll(uint64_t src)
Convert 64 bit value to network byte order.
uint64_t _ntohll(uint64_t src)
Convert 64 bit value to host byte order.
Namespace for the WebSocket++ project.
unsigned __int64 uint64_t
Two byte conversion union.
Four byte conversion union.
Eight byte conversion union.