line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "Frame.h" |
2
|
|
|
|
|
|
|
#include |
3
|
|
|
|
|
|
|
#include |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
namespace panda { namespace protocol { namespace websocket { |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
using std::cout; |
8
|
|
|
|
|
|
|
using std::endl; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
// returns true if frame is done |
11
|
76185
|
|
|
|
|
|
bool Frame::parse (string& buf) { |
12
|
76185
|
50
|
|
|
|
|
assert(_state != State::DONE); |
13
|
|
|
|
|
|
|
|
14
|
59
|
|
|
|
|
|
auto _err = [&](const std::error_code& ec) -> bool { |
15
|
59
|
|
|
|
|
|
error = ec; |
16
|
59
|
|
|
|
|
|
_state = State::DONE; |
17
|
59
|
|
|
|
|
|
return true; |
18
|
76185
|
|
|
|
|
|
}; |
19
|
|
|
|
|
|
|
|
20
|
76185
|
100
|
|
|
|
|
if (_state == State::HEADER) { |
21
|
1030
|
50
|
|
|
|
|
if (!_header.parse(buf)) return false; |
|
|
100
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
23
|
465
|
50
|
|
|
|
|
if (opcode() > Opcode::PONG || (opcode() > Opcode::BINARY && opcode() < Opcode::CLOSE)) return _err(errc::invalid_opcode); |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
455
|
50
|
|
|
|
|
if (is_control()) { |
|
|
100
|
|
|
|
|
|
26
|
83
|
100
|
|
|
|
|
if (!final()) return _err(errc::control_fragmented); |
|
|
50
|
|
|
|
|
|
27
|
71
|
100
|
|
|
|
|
if (_header.length > MAX_CONTROL_PAYLOAD) return _err(errc::control_payload_too_big); |
|
|
50
|
|
|
|
|
|
28
|
59
|
100
|
|
|
|
|
if (_header.rsv1) return _err(errc::control_frame_compression); |
|
|
50
|
|
|
|
|
|
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
430
|
100
|
|
|
|
|
if (!_header.has_mask && _mask_required && _header.length) return _err(errc::not_masked); |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
32
|
426
|
100
|
|
|
|
|
if (_max_size && _header.length > _max_size) return _err(errc::max_frame_size); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
34
|
424
|
100
|
|
|
|
|
_state = _header.length ? State::PAYLOAD : State::DONE; |
35
|
424
|
|
|
|
|
|
_payload_bytes_left = _header.length; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
75579
|
100
|
|
|
|
|
if (_state == State::PAYLOAD) { |
39
|
75549
|
100
|
|
|
|
|
if (!buf) return false; |
40
|
75467
|
|
|
|
|
|
auto buflen = buf.length(); |
41
|
|
|
|
|
|
|
//cout << "Frame[parse]: have buflen=" << buflen << ", payloadleft=" << _payload_bytes_left << endl; |
42
|
75467
|
100
|
|
|
|
|
if (buflen >= _payload_bytes_left) { // last needed buffer |
43
|
394
|
100
|
|
|
|
|
if (_header.has_mask) crypt_mask(buf.shared_buf(), _payload_bytes_left, _header.mask, _header.length - _payload_bytes_left); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
44
|
394
|
100
|
|
|
|
|
if (buflen == _payload_bytes_left) { // payload is the whole buf |
45
|
288
|
50
|
|
|
|
|
payload.push_back(buf); |
46
|
288
|
|
|
|
|
|
buf.clear(); |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
else { // have extra data after payload |
49
|
106
|
50
|
|
|
|
|
payload.push_back(buf.substr(0, _payload_bytes_left)); |
|
|
50
|
|
|
|
|
|
50
|
106
|
50
|
|
|
|
|
buf.offset(_payload_bytes_left); // leave the rest in buf |
51
|
|
|
|
|
|
|
} |
52
|
394
|
|
|
|
|
|
_state = State::DONE; |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
else { // not last buffer |
55
|
75073
|
100
|
|
|
|
|
if (_header.has_mask) crypt_mask(buf.shared_buf(), buflen, _header.mask, _header.length - _payload_bytes_left); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
56
|
75073
|
|
|
|
|
|
_payload_bytes_left -= buflen; |
57
|
75073
|
50
|
|
|
|
|
payload.push_back(buf); |
58
|
75467
|
|
|
|
|
|
return false; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
424
|
100
|
|
|
|
|
if (opcode() == Opcode::CLOSE) { |
63
|
|
|
|
|
|
|
//cout << "HERE1\n"; |
64
|
35
|
100
|
|
|
|
|
if (!_header.length) _close_code = (uint16_t)CloseCode::UNKNOWN; |
65
|
|
|
|
|
|
|
else { |
66
|
66
|
|
|
|
|
|
string str; |
67
|
31
|
100
|
|
|
|
|
if (payload.size() == 1) str = payload[0]; |
|
|
50
|
|
|
|
|
|
68
|
|
|
|
|
|
|
else { |
69
|
11
|
50
|
|
|
|
|
str.reserve(_header.length); |
70
|
47
|
100
|
|
|
|
|
for (const auto& s : payload) str += s; |
|
|
50
|
|
|
|
|
|
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
31
|
50
|
|
|
|
|
if (!FrameHeader::parse_close_payload(str, _close_code, _close_message)) return _err(errc::close_frame_invalid_data); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
13
|
|
|
|
|
|
payload.clear(); |
76
|
13
|
50
|
|
|
|
|
payload.push_back(_close_message); |
77
|
31
|
100
|
|
|
|
|
_header.length = _close_message.length(); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
//cout << "Frame[parse]: CLOSE CODE=" << _close_code << " MSG=" << _close_message << endl; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
76185
|
|
|
|
|
|
return true; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
72
|
50
|
|
|
|
|
}}} |
|
|
50
|
|
|
|
|
|