Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
parser.hh
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18
19#pragma once
20
21#include <seastar/core/seastar.hh>
22#include <seastar/core/iostream.hh>
23
24namespace seastar::experimental::websocket {
25
28
32enum opcodes {
33 CONTINUATION = 0x0,
34 TEXT = 0x1,
35 BINARY = 0x2,
36 CLOSE = 0x8,
37 PING = 0x9,
38 PONG = 0xA,
39 INVALID = 0xFF,
40};
41
43 static constexpr uint8_t FIN = 7;
44 static constexpr uint8_t RSV1 = 6;
45 static constexpr uint8_t RSV2 = 5;
46 static constexpr uint8_t RSV3 = 4;
47 static constexpr uint8_t MASKED = 7;
48
49 uint8_t fin : 1;
50 uint8_t rsv1 : 1;
51 uint8_t rsv2 : 1;
52 uint8_t rsv3 : 1;
53 uint8_t opcode : 4;
54 uint8_t masked : 1;
55 uint8_t length : 7;
56 frame_header(const char* input) {
57 this->fin = (input[0] >> FIN) & 1;
58 this->rsv1 = (input[0] >> RSV1) & 1;
59 this->rsv2 = (input[0] >> RSV2) & 1;
60 this->rsv3 = (input[0] >> RSV3) & 1;
61 this->opcode = input[0] & 0b1111;
62 this->masked = (input[1] >> MASKED) & 1;
63 this->length = (input[1] & 0b1111111);
64 }
65 // Returns length of the rest of the header.
66 uint64_t get_rest_of_header_length() {
67 size_t next_read_length = sizeof(uint32_t); // Masking key
68 if (length == 126) {
69 next_read_length += sizeof(uint16_t);
70 } else if (length == 127) {
71 next_read_length += sizeof(uint64_t);
72 }
73 return next_read_length;
74 }
75 uint8_t get_fin() {return fin;}
76 uint8_t get_rsv1() {return rsv1;}
77 uint8_t get_rsv2() {return rsv2;}
78 uint8_t get_rsv3() {return rsv3;}
79 uint8_t get_opcode() {return opcode;}
80 uint8_t get_masked() {return masked;}
81 uint8_t get_length() {return length;}
82
83 bool is_opcode_known() {
84 //https://datatracker.ietf.org/doc/html/rfc6455#section-5.1
85 return opcode < 0xA && !(opcode < 0x8 && opcode > 0x2);
86 }
87};
88
90 enum class parsing_state : uint8_t {
91 flags_and_payload_data,
92 payload_length_and_mask,
93 payload
94 };
95 enum class connection_state : uint8_t {
96 valid,
97 closed,
98 error
99 };
102 // What parser is currently doing.
103 parsing_state _state;
104 // State of connection - can be valid, closed or should be closed
105 // due to error.
106 connection_state _cstate;
107 sstring _buffer;
108 std::unique_ptr<frame_header> _header;
109 uint64_t _payload_length = 0;
110 uint64_t _consumed_payload_length = 0;
111 uint32_t _masking_key;
112 buff_t _result;
113
114 static future<consumption_result_t> dont_stop() {
115 return make_ready_future<consumption_result_t>(continue_consuming{});
116 }
117 static future<consumption_result_t> stop(buff_t data) {
118 return make_ready_future<consumption_result_t>(stop_consuming(std::move(data)));
119 }
120 uint64_t remaining_payload_length() const {
121 return _payload_length - _consumed_payload_length;
122 }
123
124 // Removes mask from payload given in p.
125 void remove_mask(buff_t& p, size_t n) {
126 char *payload = p.get_write();
127 for (uint64_t i = 0, j = 0; i < n; ++i, j = (j + 1) % 4) {
128 payload[i] ^= static_cast<char>(((_masking_key << (j * 8)) >> 24));
129 }
130 }
131public:
132 websocket_parser() : _state(parsing_state::flags_and_payload_data),
133 _cstate(connection_state::valid),
134 _masking_key(0) {}
136 bool is_valid() { return _cstate == connection_state::valid; }
137 bool eof() { return _cstate == connection_state::closed; }
138 opcodes opcode() const;
139 buff_t result();
140};
141
143}
Definition: iostream.hh:238
A representation of a possibly not-yet-computed value.
Definition: future.hh:1197
Definition: iostream.hh:218
CharType * get_write() noexcept
Definition: temporary_buffer.hh:128
opcodes
Possible type of a websocket frame.
Definition: parser.hh:32
Definition: iostream.hh:215