123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864 |
- #ifndef WEBSOCKETPP_FRAME_HPP
- #define WEBSOCKETPP_FRAME_HPP
- #include <algorithm>
- #include <string>
- #include <websocketpp/common/system_error.hpp>
- #include <websocketpp/common/network.hpp>
- #include <websocketpp/utilities.hpp>
- namespace websocketpp {
- namespace frame {
- static unsigned int const BASIC_HEADER_LENGTH = 2;
- static unsigned int const MAX_HEADER_LENGTH = 14;
- static unsigned int const MAX_EXTENDED_HEADER_LENGTH = 12;
- union uint16_converter {
- uint16_t i;
- uint8_t c[2];
- };
- union uint32_converter {
- uint32_t i;
- uint8_t c[4];
- };
- union uint64_converter {
- uint64_t i;
- uint8_t c[8];
- };
- namespace opcode {
- enum value {
- continuation = 0x0,
- text = 0x1,
- binary = 0x2,
- rsv3 = 0x3,
- rsv4 = 0x4,
- rsv5 = 0x5,
- rsv6 = 0x6,
- rsv7 = 0x7,
- close = 0x8,
- ping = 0x9,
- pong = 0xA,
- control_rsvb = 0xB,
- control_rsvc = 0xC,
- control_rsvd = 0xD,
- control_rsve = 0xE,
- control_rsvf = 0xF,
- CONTINUATION = 0x0,
- TEXT = 0x1,
- BINARY = 0x2,
- RSV3 = 0x3,
- RSV4 = 0x4,
- RSV5 = 0x5,
- RSV6 = 0x6,
- RSV7 = 0x7,
- CLOSE = 0x8,
- PING = 0x9,
- PONG = 0xA,
- CONTROL_RSVB = 0xB,
- CONTROL_RSVC = 0xC,
- CONTROL_RSVD = 0xD,
- CONTROL_RSVE = 0xE,
- CONTROL_RSVF = 0xF
- };
-
-
- inline bool reserved(value v) {
- return (v >= rsv3 && v <= rsv7) ||
- (v >= control_rsvb && v <= control_rsvf);
- }
-
-
- inline bool invalid(value v) {
- return (v > 0xF || v < 0);
- }
-
-
- inline bool is_control(value v) {
- return v >= 0x8;
- }
- }
- namespace limits {
-
- static unsigned int const basic_header_length = 2;
-
- static unsigned int const max_header_length = 14;
-
- static unsigned int const max_extended_header_length = 12;
-
- static uint8_t const payload_size_basic = 125;
-
- static uint16_t const payload_size_extended = 0xFFFF;
-
- static uint64_t const payload_size_jumbo = 0x7FFFFFFFFFFFFFFFLL;
-
-
- static uint8_t const close_reason_size = 123;
- }
- static uint8_t const BHB0_OPCODE = 0x0F;
- static uint8_t const BHB0_RSV3 = 0x10;
- static uint8_t const BHB0_RSV2 = 0x20;
- static uint8_t const BHB0_RSV1 = 0x40;
- static uint8_t const BHB0_FIN = 0x80;
- static uint8_t const BHB1_PAYLOAD = 0x7F;
- static uint8_t const BHB1_MASK = 0x80;
- static uint8_t const payload_size_code_16bit = 0x7E;
- static uint8_t const payload_size_code_64bit = 0x7F;
- typedef uint32_converter masking_key_type;
- struct basic_header {
- basic_header() : b0(0x00),b1(0x00) {}
- basic_header(uint8_t p0, uint8_t p1) : b0(p0), b1(p1) {}
- basic_header(opcode::value op, uint64_t size, bool fin, bool mask,
- bool rsv1 = false, bool rsv2 = false, bool rsv3 = false) : b0(0x00),
- b1(0x00)
- {
- if (fin) {
- b0 |= BHB0_FIN;
- }
- if (rsv1) {
- b0 |= BHB0_RSV1;
- }
- if (rsv2) {
- b0 |= BHB0_RSV2;
- }
- if (rsv3) {
- b0 |= BHB0_RSV3;
- }
- b0 |= (op & BHB0_OPCODE);
- if (mask) {
- b1 |= BHB1_MASK;
- }
- uint8_t basic_value;
- if (size <= limits::payload_size_basic) {
- basic_value = static_cast<uint8_t>(size);
- } else if (size <= limits::payload_size_extended) {
- basic_value = payload_size_code_16bit;
- } else {
- basic_value = payload_size_code_64bit;
- }
- b1 |= basic_value;
- }
- uint8_t b0;
- uint8_t b1;
- };
- struct extended_header {
- extended_header() {
- std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
- }
- extended_header(uint64_t payload_size) {
- std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
- copy_payload(payload_size);
- }
- extended_header(uint64_t payload_size, uint32_t masking_key) {
- std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
-
- int offset = copy_payload(payload_size);
-
- uint32_converter temp32;
- temp32.i = masking_key;
- std::copy(temp32.c,temp32.c+4,bytes+offset);
- }
- uint8_t bytes[MAX_EXTENDED_HEADER_LENGTH];
- private:
- int copy_payload(uint64_t payload_size) {
- int payload_offset = 0;
- if (payload_size <= limits::payload_size_basic) {
- payload_offset = 8;
- } else if (payload_size <= limits::payload_size_extended) {
- payload_offset = 6;
- }
- uint64_converter temp64;
- temp64.i = lib::net::_htonll(payload_size);
- std::copy(temp64.c+payload_offset,temp64.c+8,bytes);
- return 8-payload_offset;
- }
- };
- bool get_fin(basic_header const &h);
- void set_fin(basic_header &h, bool value);
- bool get_rsv1(basic_header const &h);
- void set_rsv1(basic_header &h, bool value);
- bool get_rsv2(basic_header const &h);
- void set_rsv2(basic_header &h, bool value);
- bool get_rsv3(basic_header const &h);
- void set_rsv3(basic_header &h, bool value);
- opcode::value get_opcode(basic_header const &h);
- bool get_masked(basic_header const &h);
- void set_masked(basic_header &h, bool value);
- uint8_t get_basic_size(basic_header const &);
- size_t get_header_len(basic_header const &);
- unsigned int get_masking_key_offset(basic_header const &);
- std::string write_header(basic_header const &, extended_header const &);
- masking_key_type get_masking_key(basic_header const &, extended_header const &);
- uint16_t get_extended_size(extended_header const &);
- uint64_t get_jumbo_size(extended_header const &);
- uint64_t get_payload_size(basic_header const &, extended_header const &);
- size_t prepare_masking_key(masking_key_type const & key);
- size_t circshift_prepared_key(size_t prepared_key, size_t offset);
- template <typename input_iter, typename output_iter>
- void byte_mask(input_iter b, input_iter e, output_iter o, masking_key_type
- const & key, size_t key_offset = 0);
- template <typename iter_type>
- void byte_mask(iter_type b, iter_type e, masking_key_type const & key,
- size_t key_offset = 0);
- void word_mask_exact(uint8_t * input, uint8_t * output, size_t length,
- masking_key_type const & key);
- void word_mask_exact(uint8_t * data, size_t length, masking_key_type const &
- key);
- size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
- size_t prepared_key);
- size_t word_mask_circ(uint8_t * data, size_t length, size_t prepared_key);
- inline bool get_fin(basic_header const & h) {
- return ((h.b0 & BHB0_FIN) == BHB0_FIN);
- }
- inline void set_fin(basic_header & h, bool value) {
- h.b0 = (value ? h.b0 | BHB0_FIN : h.b0 & ~BHB0_FIN);
- }
- inline bool get_rsv1(const basic_header &h) {
- return ((h.b0 & BHB0_RSV1) == BHB0_RSV1);
- }
- inline void set_rsv1(basic_header &h, bool value) {
- h.b0 = (value ? h.b0 | BHB0_RSV1 : h.b0 & ~BHB0_RSV1);
- }
- inline bool get_rsv2(const basic_header &h) {
- return ((h.b0 & BHB0_RSV2) == BHB0_RSV2);
- }
- inline void set_rsv2(basic_header &h, bool value) {
- h.b0 = (value ? h.b0 | BHB0_RSV2 : h.b0 & ~BHB0_RSV2);
- }
- inline bool get_rsv3(const basic_header &h) {
- return ((h.b0 & BHB0_RSV3) == BHB0_RSV3);
- }
- inline void set_rsv3(basic_header &h, bool value) {
- h.b0 = (value ? h.b0 | BHB0_RSV3 : h.b0 & ~BHB0_RSV3);
- }
- inline opcode::value get_opcode(const basic_header &h) {
- return opcode::value(h.b0 & BHB0_OPCODE);
- }
- inline bool get_masked(basic_header const & h) {
- return ((h.b1 & BHB1_MASK) == BHB1_MASK);
- }
- inline void set_masked(basic_header & h, bool value) {
- h.b1 = (value ? h.b1 | BHB1_MASK : h.b1 & ~BHB1_MASK);
- }
- inline uint8_t get_basic_size(const basic_header &h) {
- return h.b1 & BHB1_PAYLOAD;
- }
- inline size_t get_header_len(basic_header const & h) {
-
-
-
- size_t size = BASIC_HEADER_LENGTH + get_masking_key_offset(h);
-
- if (get_masked(h)) {
- size += 4;
- }
- return size;
- }
- inline unsigned int get_masking_key_offset(const basic_header &h) {
- if (get_basic_size(h) == payload_size_code_16bit) {
- return 2;
- } else if (get_basic_size(h) == payload_size_code_64bit) {
- return 8;
- } else {
- return 0;
- }
- }
- inline std::string prepare_header(const basic_header &h, const
- extended_header &e)
- {
- std::string ret;
- ret.push_back(char(h.b0));
- ret.push_back(char(h.b1));
- ret.append(
- reinterpret_cast<const char*>(e.bytes),
- get_header_len(h)-BASIC_HEADER_LENGTH
- );
- return ret;
- }
- inline masking_key_type get_masking_key(const basic_header &h, const
- extended_header &e)
- {
- masking_key_type temp32;
- if (!get_masked(h)) {
- temp32.i = 0;
- } else {
- unsigned int offset = get_masking_key_offset(h);
- std::copy(e.bytes+offset,e.bytes+offset+4,temp32.c);
- }
- return temp32;
- }
- inline uint16_t get_extended_size(const extended_header &e) {
- uint16_converter temp16;
- std::copy(e.bytes,e.bytes+2,temp16.c);
- return ntohs(temp16.i);
- }
- inline uint64_t get_jumbo_size(const extended_header &e) {
- uint64_converter temp64;
- std::copy(e.bytes,e.bytes+8,temp64.c);
- return lib::net::_ntohll(temp64.i);
- }
- inline uint64_t get_payload_size(const basic_header &h, const
- extended_header &e)
- {
- uint8_t val = get_basic_size(h);
- if (val <= limits::payload_size_basic) {
- return val;
- } else if (val == payload_size_code_16bit) {
- return get_extended_size(e);
- } else {
- return get_jumbo_size(e);
- }
- }
- inline size_t prepare_masking_key(const masking_key_type& key) {
- size_t low_bits = static_cast<size_t>(key.i);
- if (sizeof(size_t) == 8) {
- uint64_t high_bits = static_cast<size_t>(key.i);
- return static_cast<size_t>((high_bits << 32) | low_bits);
- } else {
- return low_bits;
- }
- }
- inline size_t circshift_prepared_key(size_t prepared_key, size_t offset) {
- if (offset == 0) {
- return prepared_key;
- }
- if (lib::net::is_little_endian()) {
- size_t temp = prepared_key << (sizeof(size_t)-offset)*8;
- return (prepared_key >> offset*8) | temp;
- } else {
- size_t temp = prepared_key >> (sizeof(size_t)-offset)*8;
- return (prepared_key << offset*8) | temp;
- }
- }
- template <typename input_iter, typename output_iter>
- void byte_mask(input_iter first, input_iter last, output_iter result,
- masking_key_type const & key, size_t key_offset)
- {
- size_t key_index = key_offset%4;
- while (first != last) {
- *result = *first ^ key.c[key_index++];
- key_index %= 4;
- ++result;
- ++first;
- }
- }
- template <typename iter_type>
- void byte_mask(iter_type b, iter_type e, masking_key_type const & key,
- size_t key_offset)
- {
- byte_mask(b,e,b,key,key_offset);
- }
- inline void word_mask_exact(uint8_t* input, uint8_t* output, size_t length,
- const masking_key_type& key)
- {
- size_t prepared_key = prepare_masking_key(key);
- size_t n = length/sizeof(size_t);
- size_t* input_word = reinterpret_cast<size_t*>(input);
- size_t* output_word = reinterpret_cast<size_t*>(output);
- for (size_t i = 0; i < n; i++) {
- output_word[i] = input_word[i] ^ prepared_key;
- }
- for (size_t i = n*sizeof(size_t); i < length; i++) {
- output[i] = input[i] ^ key.c[i%4];
- }
- }
- inline void word_mask_exact(uint8_t* data, size_t length, const
- masking_key_type& key)
- {
- word_mask_exact(data,data,length,key);
- }
- inline size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
- size_t prepared_key)
- {
- size_t n = length / sizeof(size_t);
- size_t l = length - (n * sizeof(size_t));
- size_t * input_word = reinterpret_cast<size_t *>(input);
- size_t * output_word = reinterpret_cast<size_t *>(output);
-
- for (size_t i = 0; i < n; i++) {
- output_word[i] = input_word[i] ^ prepared_key;
- }
-
- size_t start = length - l;
- uint8_t * byte_key = reinterpret_cast<uint8_t *>(&prepared_key);
- for (size_t i = 0; i < l; ++i) {
- output[start+i] = input[start+i] ^ byte_key[i];
- }
- return circshift_prepared_key(prepared_key,l);
- }
- inline size_t word_mask_circ(uint8_t* data, size_t length, size_t prepared_key){
- return word_mask_circ(data,data,length,prepared_key);
- }
- inline size_t byte_mask_circ(uint8_t * input, uint8_t * output, size_t length,
- size_t prepared_key)
- {
- uint32_converter key;
- key.i = prepared_key;
- for (size_t i = 0; i < length; ++i) {
- output[i] = input[i] ^ key.c[i % 4];
- }
- return circshift_prepared_key(prepared_key,length % 4);
- }
- inline size_t byte_mask_circ(uint8_t* data, size_t length, size_t prepared_key){
- return byte_mask_circ(data,data,length,prepared_key);
- }
- }
- }
- #endif
|