File Coverage

src/panda/protocol/websocket/utils.cc
Criterion Covered Total %
statement 26 47 55.3
branch 10 32 31.2
condition n/a
subroutine n/a
pod n/a
total 36 79 45.5


line stmt bran cond sub pod time code
1             #include "inc.h"
2             #include "utils.h"
3             #include "iterator.h"
4             #include
5             #include
6              
7             namespace panda { namespace protocol { namespace websocket {
8              
9             union _check_endianess { unsigned x; unsigned char c; };
10 18           static const bool am_i_little = (_check_endianess{1}).c;
11              
12 18           string StringPairIterator::global_empty = "";
13              
14             // case-insensitive jenkins_one_at_a_time_hash
15 0           uint32_t string_hash32_ci (const char *key, size_t len) {
16             uint32_t hash, i;
17 0 0         for (hash = i = 0; i < len; ++i) {
18 0           hash += std::tolower(key[i]);
19 0           hash += (hash << 10);
20 0           hash ^= (hash >> 6);
21             }
22 0           hash += (hash << 3);
23 0           hash ^= (hash >> 11);
24 0           hash += (hash << 15);
25 0           return hash;
26             }
27              
28 75529           static inline uint32_t rotate_shift (uint32_t x, unsigned shift) {
29 75529 100         if (shift % 32 == 0) return x;
30 56339           return am_i_little ? ((x >> shift) | (x << (sizeof(x)*8 - shift))) :
31 56339 50         ((x << shift) | (x >> (sizeof(x)*8 - shift)));
32             }
33              
34 75529           void crypt_mask (char* str, size_t len, uint32_t mask, uint64_t bytes_received) {
35 75529           mask = rotate_shift(mask, (bytes_received & 3)*8);
36 75529           const uint64_t mask64 = ((uint64_t)mask << 32) | mask;
37 75529           auto str64 = (uint64_t*)str;
38 75529           auto end64 = str64 + (len / 8);
39              
40 100250 100         while (str64 != end64) *str64++ ^= mask64;
41              
42 75529           auto cstr = (unsigned char*)str64;
43 75529           auto cmask = (const unsigned char*)&mask64;
44 75529           switch (len & 7) {
45 14           case 7: *cstr++ ^= *cmask++; // fallthrough
46 22           case 6: *cstr++ ^= *cmask++; // fallthrough
47 59           case 5: *cstr++ ^= *cmask++; // fallthrough
48 110           case 4: *cstr++ ^= *cmask++; // fallthrough
49 139           case 3: *cstr++ ^= *cmask++; // fallthrough
50 161           case 2: *cstr++ ^= *cmask++; // fallthrough
51 75314           case 1: *cstr++ ^= *cmask++;
52             };
53 75529           }
54              
55 252 50         static std::map close_messages = {
    100          
    0          
56             {CloseCode::NOERR , "no error"},
57             {CloseCode::DONE , "Done"},
58             {CloseCode::AWAY , "Away"},
59             {CloseCode::PROTOCOL_ERROR , "WS Protocol Error"},
60             {CloseCode::INVALID_DATA , "WS Invalid Data"},
61             {CloseCode::UNKNOWN , "WS Unknown"},
62             {CloseCode::ABNORMALLY , "Abnormally"},
63             {CloseCode::INVALID_TEXT , "Invalid Text"},
64             {CloseCode::BAD_REQUEST , "Bad Request"},
65             {CloseCode::MAX_SIZE , "Max Size"},
66             {CloseCode::EXTENSION_NEEDED , "Extension Needed"},
67             {CloseCode::INTERNAL_ERROR , "Internal Error"},
68             {CloseCode::TLS , "TLS error"}
69 234           };
70              
71 0           string close_message(uint16_t code) {
72 0 0         auto iter = close_messages.find(code);
73 0 0         if (iter == close_messages.end()) {
74 0 0         return to_string(code);
75             } else {
76 0 0         return iter->second;
77             }
78              
79             }
80              
81 0           bool register_close_codes(std::initializer_list > pairs) {
82 0 0         for (const auto& p : pairs) {
83 0 0         close_messages.insert({p.first, p.second});
84             }
85 0           return true;
86             }
87              
88 0           std::ostream& operator<< (std::ostream& s, const ccfmt& cc) {
89 0 0         s << cc.code << ": " << cc.msg ? cc.msg : close_message(cc.code);
90 0           return s;
91             }
92              
93 72 50         }}}
    50