File Coverage

src/panda/protocol/websocket/Frame.cc
Criterion Covered Total %
statement 45 45 100.0
branch 81 108 75.0
condition n/a
subroutine n/a
pod n/a
total 126 153 82.3


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