28 #ifndef WEBSOCKETPP_FRAME_HPP
29 #define WEBSOCKETPP_FRAME_HPP
34 #include <websocketpp/common/system_error.hpp>
35 #include <websocketpp/common/network.hpp>
37 #include <websocketpp/utilities.hpp>
55 union uint16_converter {
61 union uint32_converter {
67 union uint64_converter {
119 return (v >= rsv3 && v <= rsv7) ||
120 (v >= control_rsvb && v <= control_rsvf);
131 return (v > 0xF || v < 0);
174 static uint8_t
const BHB0_OPCODE = 0x0F;
175 static uint8_t
const BHB0_RSV3 = 0x10;
176 static uint8_t
const BHB0_RSV2 = 0x20;
177 static uint8_t
const BHB0_RSV1 = 0x40;
178 static uint8_t
const BHB0_FIN = 0x80;
180 static uint8_t
const BHB1_PAYLOAD = 0x7F;
181 static uint8_t
const BHB1_MASK = 0x80;
183 static uint8_t
const payload_size_code_16bit = 0x7E;
184 static uint8_t
const payload_size_code_64bit = 0x7F;
186 typedef uint32_converter masking_key_type;
190 basic_header() : b0(0x00),b1(0x00) {}
192 basic_header(uint8_t p0, uint8_t p1) : b0(p0), b1(p1) {}
194 basic_header(
opcode::value op, uint64_t size,
bool fin,
bool mask,
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;
235 struct extended_header {
237 std::fill_n(
this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
240 extended_header(uint64_t payload_size) {
241 std::fill_n(
this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
243 copy_payload(payload_size);
246 extended_header(uint64_t payload_size, uint32_t masking_key) {
247 std::fill_n(
this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
250 int offset = copy_payload(payload_size);
253 uint32_converter temp32;
254 temp32.i = masking_key;
255 std::copy(temp32.c,temp32.c+4,bytes+offset);
258 uint8_t bytes[MAX_EXTENDED_HEADER_LENGTH];
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) {
269 uint64_converter temp64;
270 temp64.i = lib::net::_htonll(payload_size);
271 std::copy(temp64.c+payload_offset,temp64.c+8,bytes);
273 return 8-payload_offset;
292 std::string write_header(basic_header
const &, extended_header
const &);
302 template <
typename input_iter,
typename output_iter>
303 void byte_mask(input_iter b, input_iter e, output_iter o, masking_key_type
304 const & key, size_t key_offset = 0);
305 template <
typename iter_type>
306 void byte_mask(iter_type b, iter_type e, masking_key_type
const & key,
307 size_t key_offset = 0);
309 masking_key_type
const & key);
310 void word_mask_exact(uint8_t * data, size_t length, masking_key_type
const &
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);
394 return opcode::value(h.b0 & BHB0_OPCODE);
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;
450 size_t size = BASIC_HEADER_LENGTH + get_masking_key_offset(h);
470 if (get_basic_size(h) == payload_size_code_16bit) {
472 }
else if (get_basic_size(h) == payload_size_code_64bit) {
494 ret.push_back(
char(h.b0));
495 ret.push_back(
char(h.b1));
497 reinterpret_cast<
const char*>(e.bytes),
498 get_header_len(h)-BASIC_HEADER_LENGTH
519 masking_key_type temp32;
525 std::copy(e.bytes+offset,e.bytes+offset+4,temp32.c);
541 uint16_converter temp16;
542 std::copy(e.bytes,e.bytes+2,temp16.c);
543 return ntohs(temp16.i);
556 uint64_converter temp64;
557 std::copy(e.bytes,e.bytes+8,temp64.c);
558 return lib::net::_ntohll(temp64.i);
576 uint8_t val = get_basic_size(h);
578 if (val <= limits::payload_size_basic) {
580 }
else if (val == payload_size_code_16bit) {
581 return get_extended_size(e);
583 return get_jumbo_size(e);
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);
616 if (lib::net::is_little_endian()) {
617 size_t temp = prepared_key << (
sizeof(size_t)-offset)*8;
618 return (prepared_key >> offset*8) | temp;
620 size_t temp = prepared_key >> (
sizeof(size_t)-offset)*8;
621 return (prepared_key << offset*8) | temp;
644 template <
typename input_iter,
typename output_iter>
645 void byte_mask(input_iter first, input_iter last, output_iter result,
646 masking_key_type
const & key, size_t key_offset)
648 size_t key_index = key_offset%4;
649 while (first != last) {
650 *result = *first ^ key.c[key_index++];
674 template <
typename iter_type>
675 void byte_mask(iter_type b, iter_type e, masking_key_type
const & key,
678 byte_mask(b,e,b,key,key_offset);
703 const masking_key_type& key)
705 size_t prepared_key = prepare_masking_key(key);
706 size_t n = length/
sizeof(size_t);
707 size_t* input_word =
reinterpret_cast<size_t*>(input);
708 size_t* output_word =
reinterpret_cast<size_t*>(output);
710 for (size_t i = 0; i < n; i++) {
711 output_word[i] = input_word[i] ^ prepared_key;
714 for (size_t i = n*
sizeof(size_t); i < length; i++) {
715 output[i] = input[i] ^ key.c[i%4];
732 masking_key_type& key)
734 word_mask_exact(data,data,length,key);
771 size_t n = length /
sizeof(size_t);
772 size_t l = length - (n *
sizeof(size_t));
773 size_t * input_word =
reinterpret_cast<size_t *>(input);
774 size_t * output_word =
reinterpret_cast<size_t *>(output);
777 for (size_t i = 0; i < n; i++) {
778 output_word[i] = input_word[i] ^ prepared_key;
782 size_t start = length - l;
783 uint8_t * byte_key =
reinterpret_cast<uint8_t *>(&prepared_key);
784 for (size_t i = 0; i < l; ++i) {
785 output[start+i] = input[start+i] ^ byte_key[i];
788 return circshift_prepared_key(prepared_key,l);
806 return word_mask_circ(data,data,length,prepared_key);
833 uint32_converter key;
834 key.i = prepared_key;
836 for (size_t i = 0; i < length; ++i) {
837 output[i] = input[i] ^ key.c[i % 4];
840 return circshift_prepared_key(prepared_key,length % 4);
858 return byte_mask_circ(data,data,length,prepared_key);