File Coverage

src/panda/protocol/websocket/Parser.cc
Criterion Covered Total %
statement 133 135 98.5
branch 161 224 71.8
condition n/a
subroutine n/a
pod n/a
total 294 359 81.8


line stmt bran cond sub pod time code
1             #include "Parser.h"
2             #include
3             #include
4             #include
5              
6             namespace panda { namespace protocol { namespace websocket {
7              
8             using std::cout;
9             using std::endl;
10              
11 279           void Parser::configure (const Config& cfg) {
12 279           _max_frame_size = cfg.max_frame_size;
13 279           _max_message_size = cfg.max_message_size;
14 279           _max_handshake_size = cfg.max_handshake_size;
15 279           _check_utf8 = cfg.check_utf8;
16              
17 279 100         if (!_flags[ESTABLISHED]) {
18 275           _deflate_cfg = cfg.deflate;
19 275 100         if (_deflate_cfg) _deflate_cfg->max_message_size = _max_message_size;
20             }
21              
22 279 50         if (_frame) _frame->max_size(_max_frame_size);
23 279 50         if (_message) _message->max_size(_max_message_size);
24 279           _message_frame.max_size(_max_frame_size);
25 279           }
26              
27 132           void Parser::reset () {
28 132           _buffer.clear();
29 132           _flags.reset();
30 132           _frame = NULL;
31 132           _frame_count = 0;
32 132           _message = NULL;
33 132           _message_frame.reset();
34 132 50         if (_deflate_ext) _deflate_ext->reset();
35 132           _suggested_close_code = 0;
36 132           }
37              
38 76185           bool Parser::_parse_frame (Frame& frame) {
39 76185 50         if (!frame.parse(_buffer)) {
    100          
40 75720           _buffer.clear();
41 75720           return false;
42             }
43              
44 75           auto _err = [&]() -> bool {
45 75           _buffer.clear();
46 75           _frame_count = 0;
47 75           _flags.reset(RECV_FRAME);
48 75           _flags.reset(RECV_INFLATE);
49 75           _utf8_checker.reset();
50 75 100         if (frame.error & errc::invalid_utf8) _suggested_close_code = CloseCode::INVALID_TEXT;
51 73 100         else if (frame.error & errc::max_frame_size) _suggested_close_code = CloseCode::MAX_SIZE;
52 71           else _suggested_close_code = CloseCode::PROTOCOL_ERROR;
53              
54 75           return true;
55 465           };
56              
57 12           auto _seterr = [&](const std::error_code& ec) -> bool {
58 12           frame.error = ec;
59 12           return _err();
60 465           };
61              
62 465 100         if (frame.error) return _err();
    50          
63              
64 406 50         if (frame.is_control()) { // control frames can't be fragmented, no need to increment frame count
    100          
65 40 100         if (!_frame_count) _flags.reset(RECV_FRAME); // do not reset state if control frame arrives in the middle of message
    50          
66 40 100         if (frame.opcode() == Opcode::CLOSE) {
67 17           _buffer.clear();
68 17 50         _flags.set(RECV_CLOSED);
69 17 100         if (frame.close_code() == CloseCode::UNKNOWN) _suggested_close_code = CloseCode::DONE;
70 13           else _suggested_close_code = frame.close_code();
71              
72 17 100         if (_check_utf8 && frame.close_message()) {
    50          
    50          
    100          
    100          
    0          
73 3           _utf8_checker.reset();
74 3 50         if (!_utf8_checker.write(frame.close_message()) || !_utf8_checker.finish()) return _seterr(errc::invalid_utf8);
    50          
    100          
    50          
    50          
    100          
    50          
    0          
75             }
76             }
77 39           return true;
78             }
79              
80 366 100         if (_frame_count == 0) {
81 228 100         if (frame.opcode() == Opcode::CONTINUE) return _seterr(errc::initial_continue);
    50          
82 224 100         if (frame.rsv1()) {
83 43 100         if (_deflate_ext) _flags.set(RECV_INFLATE);
    50          
84 2 50         else return _seterr(errc::unexpected_rsv);
85             }
86 222 50         if (frame.rsv2() | frame.rsv3()) return _seterr(errc::unexpected_rsv);
    0          
87             }
88             else {
89 138 100         if (frame.opcode() != Opcode::CONTINUE) return _seterr(errc::fragment_no_continue);
    50          
90             }
91              
92 356 100         if (_flags[RECV_INFLATE]) {
93 50 50         _deflate_ext->uncompress(frame);
94 50 100         if (frame.error) return _err();
    50          
95             }
96              
97 352 100         if (_check_utf8) {
98 11 100         if (_frame_count == 0 && frame.opcode() == Opcode::TEXT) _flags.set(RECV_TEXT);
    50          
    100          
    50          
99 11 50         if (_flags[RECV_TEXT] && !_utf8_checker.write(frame.payload)) return _seterr(errc::invalid_utf8);
    50          
    100          
    50          
    100          
    50          
    0          
100 10 100         if (frame.final()) {
101 3 50         if (!_utf8_checker.finish()) return _seterr(errc::invalid_utf8);
    0          
102 3 50         _flags.reset(RECV_TEXT);
103             }
104             }
105              
106 351 100         if (frame.final()) {
107 204 50         _flags.reset(RECV_FRAME);
108 204 50         _flags.reset(RECV_INFLATE);
109 204           _frame_count = 0;
110             }
111 147           else ++_frame_count;
112              
113 76185           return true;
114             }
115              
116 72491           FrameSP Parser::_get_frame () {
117 72491 100         if (!_flags[ESTABLISHED]) throw Error("not established");
118 72489 100         if (_flags[RECV_MESSAGE]) throw Error("message is being parsed");
119 72487 100         if (_flags[RECV_CLOSED]) { _buffer.clear(); return nullptr; }
120 72475 100         if (!_buffer) return nullptr;
121              
122 72409 50         _flags.set(RECV_FRAME);
123 72409 100         if (!_frame) _frame = new Frame(_recv_mask_required, _max_frame_size);
    50          
    50          
124              
125 72409 50         if (!_parse_frame(*_frame)) return nullptr;
    100          
126              
127 72604           FrameSP ret = std::move(_frame);
128 117           _frame = nullptr;
129 117           return ret;
130             }
131              
132 3884           MessageSP Parser::_get_message () {
133 3884 100         if (!_flags[ESTABLISHED]) throw Error("not established");
134 3883 100         if (_flags[RECV_FRAME]) throw Error("frame mode active");
135 3881 100         if (_flags[RECV_CLOSED]) { _buffer.clear(); return nullptr; }
136 3874 100         if (!_buffer) return nullptr;
137              
138 3696 50         _flags.set(RECV_MESSAGE);
139 3696 100         if (!_message) _message = new Message(_max_message_size);
    50          
    50          
140              
141 80           while (1) {
142 3776 50         if (!_parse_frame(_message_frame)) return nullptr;
    100          
143              
144             // control frame arrived in the middle of fragmented message - wrap in new message and return (state remains MESSAGE)
145             // because user can only switch to getting frames after receiving non-control message
146 348 100         if (!_message_frame.error && _message_frame.is_control() && _message->frame_count) {
    50          
    100          
    100          
    100          
147 5 50         auto cntl_msg = new Message(_max_message_size);
    50          
148 5 50         bool done = cntl_msg->add_frame(_message_frame);
149 5 50         assert(done);
150 5           _message_frame.reset();
151 5           return cntl_msg;
152             }
153              
154 343 50         bool done = _message->add_frame(_message_frame);
155 343           _message_frame.reset();
156              
157 343 100         if (done) break;
158 136 100         if (!_buffer) return nullptr;
159             }
160              
161 207 100         if (_message->error) {
162 26 100         if (_message->error & errc::max_message_size) _suggested_close_code = CloseCode::MAX_SIZE;
163             }
164              
165 207 50         _flags.reset(RECV_MESSAGE);
166 207 50         _flags.reset(RECV_INFLATE);
167 4088           MessageSP ret = std::move(_message);
168 207           _message = nullptr;
169 207           return ret;
170             }
171              
172 33           FrameHeader Parser::_prepare_control_header (Opcode opcode) {
173 33           _check_send();
174 33 100         if (opcode == Opcode::CLOSE) {
175 8           _flags.set(SEND_CLOSED);
176 8           _flags.reset(SEND_FRAME);
177             }
178 33 100         return FrameHeader(opcode, true, 0, 0, 0, !_recv_mask_required, _recv_mask_required ? 0 : (uint32_t)std::rand());
179             }
180              
181 194           FrameHeader Parser::_prepare_frame_header (bool final) {
182 194 100         if (!_flags[SEND_FRAME]) throw Error("can't send frame: message has not been started");
183              
184 192 50         if (FrameHeader::is_control_opcode(_send_opcode)) {
185 0 0         if (!final) throw Error("control frame must be final");
186 0           return _prepare_control_header(_send_opcode);
187             }
188              
189             Opcode opcode;
190             bool rsv1;
191              
192 192 100         if (_sent_frame_count) {
193 18           opcode = Opcode::CONTINUE;
194 18           rsv1 = false;
195             }
196             else {
197 174           opcode = _send_opcode;
198 174           rsv1 = _flags[SEND_DEFLATE];
199             }
200              
201 192 100         if (final) {
202 168           _sent_frame_count = 0;
203 168           _flags.reset(SEND_FRAME);
204 168           _flags.reset(SEND_DEFLATE);
205             }
206 24           else ++_sent_frame_count;
207              
208 192 100         return FrameHeader(opcode, final, rsv1, 0, 0, !_recv_mask_required, _recv_mask_required ? 0 : (uint32_t)std::rand());
209             }
210              
211 72 50         }}}
    50