|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #include "FrameHeader.h"  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #include "utils.h"  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #include   | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #include   | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #include   | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #include   | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 namespace panda { namespace protocol { namespace websocket {  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 using std::cout;  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 using std::endl;  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static const int MAX_SIZE = 14;  // 2 bytes required + 8-byte length + 4-byte mask  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #pragma pack(push,1)  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     struct BinaryFirst {  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         uint8_t opcode : 4;  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         bool    rsv3   : 1;  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         bool    rsv2   : 1;  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         bool    rsv1   : 1;  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         bool    fin    : 1;  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     struct BinarySecond {  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         uint8_t slen : 7;  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         bool    mask : 1;  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #pragma pack(pop)  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
29
 | 
1030
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 bool FrameHeader::parse (string& buf) {  | 
| 
30
 | 
1030
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     assert(_state != State::DONE);  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
32
 | 
1030
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     auto data = buf.data();  | 
| 
33
 | 
1030
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     auto end  = data + buf.length();  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
35
 | 
1030
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (_state == State::FIRST) {  | 
| 
36
 | 
465
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (data == end) return false;  | 
| 
37
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         auto first = *((BinaryFirst*)data++);  | 
| 
38
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         fin    = first.fin;  | 
| 
39
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         rsv1   = first.rsv1;  | 
| 
40
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         rsv2   = first.rsv2;  | 
| 
41
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         rsv3   = first.rsv3;  | 
| 
42
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         opcode = (Opcode)first.opcode;  | 
| 
43
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _state = State::SECOND;  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
1030
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (_state == State::SECOND) {  | 
| 
47
 | 
576
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (data == end) return false;  | 
| 
48
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         auto second = *((BinarySecond*)data++);  | 
| 
49
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         has_mask = second.mask;  | 
| 
50
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _slen    = second.slen;  | 
| 
51
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _state = State::LENGTH;  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         //cout << "FrameHeader[parse]: HASMASK=" << has_mask << ", SLEN=" << (int)_slen << endl;  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
55
 | 
919
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (_state == State::LENGTH) {  | 
| 
56
 | 
495
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (_slen < 126) {  | 
| 
57
 | 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             length = _slen;  | 
| 
58
 | 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             _state = State::MASK;  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             //cout << "FrameHeader[parse]: LENGTH(7)=" << length << endl;  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
61
 | 
160
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else if (data == end) return false;  | 
| 
62
 | 
148
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else if (_slen == 126) {  | 
| 
63
 | 
139
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if (!parse_binary_number(_len16, data, end - data)) return false;  | 
| 
64
 | 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             length = be2h16(_len16);  | 
| 
65
 | 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             _state = State::MASK;  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             //cout << "FrameHeader[parse]: LENGTH(16)=" << length << endl;  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else { // 127  | 
| 
69
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if (!parse_binary_number(length, data, end - data)) return false;  | 
| 
70
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             length = be2h64(length);  | 
| 
71
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             _state = State::MASK;  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             //cout << "FrameHeader[parse]: LENGTH(64)=" << length << endl;  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
76
 | 
889
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (_state == State::MASK) {  | 
| 
77
 | 
889
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (!has_mask) _state = State::DONE;  | 
| 
78
 | 
827
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else if (data == end) return false;  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
| 
80
 | 
721
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if (!parse_binary_number(mask, data, end - data)) return false;  | 
| 
81
 | 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             _state = State::DONE;  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             //cout << "FrameHeader[parse]: MASK=" << mask << endl;  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
465
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (data == end) buf.clear();       // no extra data after the end of frame  | 
| 
87
 | 
330
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else buf.offset(data - buf.data()); // leave rest in buffer  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
89
 | 
1030
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return true;  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
92
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 string FrameHeader::compile (size_t plen) const {  | 
| 
93
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     string ret(MAX_SIZE);  | 
| 
94
 | 
234
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char* ptr = ret.buf();  | 
| 
95
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     const char*const begin = ptr;  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
97
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     *((BinaryFirst*)ptr++) = BinaryFirst{(uint8_t)opcode, rsv3, rsv2, rsv1, fin};  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
99
 | 
234
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (plen < 126) {  | 
| 
100
 | 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *((BinarySecond*)ptr++) = BinarySecond{(uint8_t)plen, has_mask};  | 
| 
101
 | 
116
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else if (plen < 65536) {  | 
| 
102
 | 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *((BinarySecond*)ptr++) = BinarySecond{126, has_mask};  | 
| 
103
 | 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *((uint16_t*)ptr) = h2be16(plen);  | 
| 
104
 | 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ptr += sizeof(uint16_t);  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
106
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *((BinarySecond*)ptr++) = BinarySecond{127, has_mask};  | 
| 
107
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *((uint64_t*)ptr) = h2be64(plen);  | 
| 
108
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ptr += sizeof(uint64_t);  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
234
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (has_mask) {  | 
| 
112
 | 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *((uint32_t*)ptr) = mask;  | 
| 
113
 | 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ptr += sizeof(uint32_t);  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
116
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ret.length(ptr - begin);  | 
| 
117
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return ret;  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
120
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 bool FrameHeader::parse_close_payload (const string& payload, uint16_t& code, string& message) {  | 
| 
121
 | 
31
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!payload) code = (uint16_t)CloseCode::UNKNOWN;  | 
| 
122
 | 
31
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else if (payload.length() < sizeof(code)) {  | 
| 
123
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         code = (uint16_t)CloseCode::UNKNOWN;  | 
| 
124
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return false;  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
126
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     auto ptr = payload.data();  | 
| 
127
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     code = be2h16(*((uint16_t*)ptr));  | 
| 
128
 | 
25
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     message = payload.substr(sizeof(code));  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     // check for invalid close codes  | 
| 
130
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return !CloseCode::is_sending_forbidden(code);  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
133
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 string FrameHeader::compile_close_payload (uint16_t code, const string& message) {  | 
| 
134
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     size_t sz = sizeof(code) + message.length();  | 
| 
135
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     string ret(sz);  | 
| 
136
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char* buf = ret.buf();  | 
| 
137
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     *((uint16_t*)buf) = h2be16(code);  | 
| 
138
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     buf += sizeof(code);  | 
| 
139
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (message.length()) std::memcpy(buf, message.data(), message.length());  | 
| 
140
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ret.length(sz);  | 
| 
141
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return ret;  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
144
 | 
72
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }}}  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    |