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>
39 namespace websocketpp {
48 static unsigned int const BASIC_HEADER_LENGTH = 2;
50 static unsigned int const MAX_HEADER_LENGTH = 14;
52 static unsigned int const MAX_EXTENDED_HEADER_LENGTH = 12;
55 union uint16_converter {
61 union uint32_converter {
67 union uint64_converter {
118 inline bool reserved(value v) {
119 return (v >= rsv3 && v <= rsv7) ||
120 (v >= control_rsvb && v <= control_rsvf);
130 inline bool invalid(value v) {
131 return (v > 0xF || v < 0);
139 inline bool is_control(value v) {
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;
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;
189 struct basic_header {
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;
277 bool get_fin(basic_header
const &h);
278 void set_fin(basic_header &h,
bool value);
279 bool get_rsv1(basic_header
const &h);
280 void set_rsv1(basic_header &h,
bool value);
281 bool get_rsv2(basic_header
const &h);
282 void set_rsv2(basic_header &h,
bool value);
283 bool get_rsv3(basic_header
const &h);
284 void set_rsv3(basic_header &h,
bool value);
285 opcode::value get_opcode(basic_header
const &h);
286 bool get_masked(basic_header
const &h);
287 void set_masked(basic_header &h,
bool value);
288 uint8_t get_basic_size(basic_header
const &);
289 size_t get_header_len(basic_header
const &);
290 unsigned int get_masking_key_offset(basic_header
const &);
292 std::string write_header(basic_header
const &, extended_header
const &);
293 masking_key_type get_masking_key(basic_header
const &, extended_header
const &);
294 uint16_t get_extended_size(extended_header
const &);
295 uint64_t get_jumbo_size(extended_header
const &);
296 uint64_t get_payload_size(basic_header
const &, extended_header
const &);
298 size_t prepare_masking_key(masking_key_type
const & key);
299 size_t circshift_prepared_key(size_t prepared_key, size_t offset);
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);
308 void word_mask_exact(uint8_t * input, uint8_t * output, size_t length,
309 masking_key_type
const & key);
310 void word_mask_exact(uint8_t * data, size_t length, masking_key_type
const &
312 size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
313 size_t prepared_key);
314 size_t word_mask_circ(uint8_t * data, size_t length, size_t prepared_key);
321 inline bool get_fin(basic_header
const & h) {
322 return ((h.b0 & BHB0_FIN) == BHB0_FIN);
330 inline void set_fin(basic_header & h,
bool value) {
331 h.b0 = (value ? h.b0 | BHB0_FIN : h.b0 & ~BHB0_FIN);
339 inline bool get_rsv1(
const basic_header &h) {
340 return ((h.b0 & BHB0_RSV1) == BHB0_RSV1);
348 inline void set_rsv1(basic_header &h,
bool value) {
349 h.b0 = (value ? h.b0 | BHB0_RSV1 : h.b0 & ~BHB0_RSV1);
357 inline bool get_rsv2(
const basic_header &h) {
358 return ((h.b0 & BHB0_RSV2) == BHB0_RSV2);
366 inline void set_rsv2(basic_header &h,
bool value) {
367 h.b0 = (value ? h.b0 | BHB0_RSV2 : h.b0 & ~BHB0_RSV2);
375 inline bool get_rsv3(
const basic_header &h) {
376 return ((h.b0 & BHB0_RSV3) == BHB0_RSV3);
384 inline void set_rsv3(basic_header &h,
bool value) {
385 h.b0 = (value ? h.b0 | BHB0_RSV3 : h.b0 & ~BHB0_RSV3);
393 inline opcode::value get_opcode(
const basic_header &h) {
394 return opcode::value(h.b0 & BHB0_OPCODE);
402 inline bool get_masked(basic_header
const & h) {
403 return ((h.b1 & BHB1_MASK) == BHB1_MASK);
411 inline void set_masked(basic_header & h,
bool value) {
412 h.b1 = (value ? h.b1 | BHB1_MASK : h.b1 & ~BHB1_MASK);
431 inline uint8_t get_basic_size(
const basic_header &h) {
432 return h.b1 & BHB1_PAYLOAD;
445 inline size_t get_header_len(basic_header
const & h) {
450 size_t size = BASIC_HEADER_LENGTH + get_masking_key_offset(h);
469 inline unsigned int get_masking_key_offset(
const basic_header &h) {
470 if (get_basic_size(h) == payload_size_code_16bit) {
472 }
else if (get_basic_size(h) == payload_size_code_64bit) {
489 inline std::string prepare_header(
const basic_header &h,
const
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
516 inline masking_key_type get_masking_key(
const basic_header &h,
const
519 masking_key_type temp32;
521 if (!get_masked(h)) {
524 unsigned int offset = get_masking_key_offset(h);
525 std::copy(e.bytes+offset,e.bytes+offset+4,temp32.c);
540 inline uint16_t get_extended_size(
const extended_header &e) {
541 uint16_converter temp16;
542 std::copy(e.bytes,e.bytes+2,temp16.c);
543 return ntohs(temp16.i);
555 inline uint64_t get_jumbo_size(
const extended_header &e) {
556 uint64_converter temp64;
557 std::copy(e.bytes,e.bytes+8,temp64.c);
558 return lib::net::_ntohll(temp64.i);
573 inline uint64_t get_payload_size(
const basic_header &h,
const
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);
595 inline size_t prepare_masking_key(
const masking_key_type& key) {
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);
612 inline size_t circshift_prepared_key(size_t prepared_key, size_t offset) {
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);
702 inline void word_mask_exact(uint8_t* input, uint8_t* output, size_t length,
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];
731 inline void word_mask_exact(uint8_t* data, size_t length,
const
732 masking_key_type& key)
734 word_mask_exact(data,data,length,key);
768 inline size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
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);
805 inline size_t word_mask_circ(uint8_t* data, size_t length, size_t prepared_key){
806 return word_mask_circ(data,data,length,prepared_key);
830 inline size_t byte_mask_circ(uint8_t * input, uint8_t * output, size_t length,
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);
857 inline size_t byte_mask_circ(uint8_t* data, size_t length, size_t prepared_key){
858 return byte_mask_circ(data,data,length,prepared_key);