MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / readWebSocketFrame

Function readWebSocketFrame

src/Server/WebTerminalRequestHandler.cpp:170–258  ·  view source on GitHub ↗

Read a single WebSocket frame from the socket. If deadline_ns is non-zero, abort when the monotonic clock exceeds it. `max_payload_size` caps the advertised payload length and is set tighter for pre-auth frames to prevent a single unauthenticated client from forcing the server to allocate up to 16 MiB before any credentials have been checked.

Source from the content-addressed store, hash-verified

168/// forcing the server to allocate up to 16 MiB before any credentials have
169/// been checked.
170WebSocketFrame readWebSocketFrame(Poco::Net::StreamSocket & socket, UInt64 deadline_ns = 0, uint64_t max_payload_size = 16 * 1024 * 1024)
171{
172 WebSocketFrame frame;
173 uint8_t header[2];
174
175 if (!readExact(socket, reinterpret_cast<char *>(header), 2, deadline_ns))
176 return frame;
177
178 frame.fin = (header[0] & 0x80) != 0;
179 frame.opcode = header[0] & 0x0F;
180
181 /// RSV1/RSV2/RSV3 must be zero (no extensions negotiated)
182 if (header[0] & 0x70)
183 {
184 frame.protocol_error = true;
185 return frame;
186 }
187
188 /// Reject reserved opcodes per RFC 6455 Section 5.2
189 if ((frame.opcode >= 0x03 && frame.opcode <= 0x07) || frame.opcode >= 0x0B)
190 {
191 frame.protocol_error = true;
192 return frame;
193 }
194
195 bool masked = (header[1] & 0x80) != 0;
196 uint64_t payload_len = header[1] & 0x7F;
197
198 /// RFC 6455: client-to-server frames MUST be masked
199 if (!masked)
200 {
201 frame.protocol_error = true;
202 return frame;
203 }
204
205 /// Control frames (opcode >= 0x08) must have FIN set and payload <= 125
206 if (frame.opcode >= 0x08)
207 {
208 if (!frame.fin || payload_len > 125)
209 {
210 frame.protocol_error = true;
211 return frame;
212 }
213 }
214
215 if (payload_len == 126)
216 {
217 uint8_t ext[2];
218 if (!readExact(socket, reinterpret_cast<char *>(ext), 2, deadline_ns))
219 return frame;
220 payload_len = (static_cast<uint64_t>(ext[0]) << 8) | ext[1];
221 }
222 else if (payload_len == 127)
223 {
224 uint8_t ext[8];
225 if (!readExact(socket, reinterpret_cast<char *>(ext), 8, deadline_ns))
226 return frame;
227 payload_len = 0;

Callers 1

Calls 3

readExactFunction · 0.85
resizeMethod · 0.45
dataMethod · 0.45

Tested by

no test coverage detected