4#include "../AsyncStreams/AsyncStreams.h"
5#include "../Common/Function.h"
6#include "../Common/Result.h"
7#include "../Common/Span.h"
14struct HttpAsyncClient;
15struct HttpAsyncClientRequest;
16struct HttpAsyncClientResponse;
50 uint64_t payloadLength = 0;
51 uint8_t maskKey[4] = {0, 0, 0, 0};
53 [[nodiscard]]
bool isControlFrame()
const;
65 [[nodiscard]]
bool isValid()
const
67 return readableStream !=
nullptr and writableStream !=
nullptr and buffersPool !=
nullptr;
78 StringSpan connection;
79 StringSpan secWebSocketKey;
80 StringSpan secWebSocketVersion;
86 uint32_t statusCode = 0;
89 StringSpan connection;
90 StringSpan secWebSocketAccept;
96 enum class Status : uint8_t
103 Status status = Status::BadRequest;
105 [[nodiscard]]
bool accepted()
const {
return status == Status::Accepted; }
106 [[nodiscard]]
int httpStatusCode()
const;
112 static constexpr size_t ClientKeyLength = 24;
113 static constexpr size_t AcceptKeyLength = 28;
114 static constexpr size_t NonceLength = 16;
116 static Result createClientKey(Span<const uint8_t> nonce, Span<char> storage, StringSpan& key);
117 static Result validateClientKey(StringSpan key);
118 static Result computeAccept(StringSpan clientKey, Span<char> storage, StringSpan& accept);
120 static bool headerContainsToken(StringSpan headerValue, StringSpan token);
127 StringSpan expectedClientKey);
131 static Result writeServerAccept(
HttpResponse& response, StringSpan clientKey, Span<char> acceptStorage,
134 Span<char> acceptStorage);
142 Function<void(Result)> onError;
150 void onClientError(Result result);
151 void fail(Result result);
155 StringSpan clientKey;
162 Function<Result(Span<char>,
bool)> onFramePayload;
165 Result parse(Span<char> data,
size_t& consumedBytes);
168 enum class State : uint8_t
177 Result onHeaderReady();
178 Result finishCurrentFrame();
183 State state = State::HeaderByte0;
185 bool fragmentedMessageInProgress =
false;
187 uint8_t headerByte0 = 0;
189 uint8_t extendedLengthBytesExpected = 0;
190 uint8_t extendedLengthBytesRead = 0;
191 uint8_t maskBytesRead = 0;
193 uint64_t extendedLengthAccumulator = 0;
194 uint64_t payloadBytesRemaining = 0;
195 uint64_t payloadBytesConsumed = 0;
204 Result writePayload(Span<char> payload);
205 Result finishFrame();
211 bool frameInProgress =
false;
212 bool fragmentedMessageInProgress =
false;
214 uint64_t payloadBytesRemaining = 0;
215 uint64_t payloadBytesWritten = 0;
223 void reset(Span<char> messageStorage);
226 Result onFramePayload(Span<char> payload,
bool frameFinished);
228 [[nodiscard]]
size_t getCurrentMessageSize()
const {
return messageSize; }
231 Span<char> messageStorage;
236 size_t messageSize = 0;
238 bool assemblingMessage =
false;
239 bool ignoringFrame =
false;
247 Function<Result(Span<char>)> onPing;
248 Function<Result(Span<char>)> onPong;
249 Function<Result(uint16_t, Span<char>)> onClose;
252 void setAutomaticMaskKey(
const uint8_t maskKey[4]);
254 Result receive(Span<char> data,
size_t& consumedBytes);
257 Span<const char>& encodedFrame);
258 Result sendData(
HttpWebSocketOpcode opcode, Span<const char> payload,
bool fin,
const uint8_t* maskKey,
259 Span<char> storage, Span<const char>& encodedFrame);
260 Result sendPing(Span<const char> payload,
const uint8_t* maskKey, Span<char> storage,
261 Span<const char>& encodedFrame);
262 Result sendPong(Span<const char> payload,
const uint8_t* maskKey, Span<char> storage,
263 Span<const char>& encodedFrame);
264 Result sendClose(uint16_t statusCode, Span<const char> reason,
const uint8_t* maskKey, Span<char> storage,
265 Span<const char>& encodedFrame);
267 [[nodiscard]]
bool hasPendingControlFrame()
const {
return pendingControlFrame.sizeInBytes() > 0; }
268 Result getPendingControlFrame(Span<const char>& frame)
const;
269 void clearPendingControlFrame();
271 [[nodiscard]]
bool hasCloseBeenSent()
const {
return closeSent; }
272 [[nodiscard]]
bool hasCloseBeenReceived()
const {
return closeReceived; }
276 Result onReaderPayload(Span<char> payload,
bool frameFinished);
277 Result handleControlFrame(Span<char> payload);
286 char controlPayload[125] = {0};
287 size_t controlPayloadSize = 0;
288 char automaticControlStorage[2 + 8 + 4 + 125] = {0};
289 Span<const char> pendingControlFrame;
290 uint8_t automaticMaskKey[4] = {0, 0, 0, 0};
292 bool automaticMaskKeySet =
false;
293 bool closeSent =
false;
294 bool closeReceived =
false;
301 Function<void()> onEnd;
302 Function<void(Result)> onError;
307 Result writeFrame(Span<const char> frame);
308 Result flushPendingControlFrame();
310 [[nodiscard]]
bool isAttached()
const {
return transport.isValid(); }
319 Result onEndpointDataFrame(
HttpWebSocketOpcode opcode, Span<char> payload,
bool frameFinished);
320 void fail(Result result);
325 bool dataListenerAdded =
false;
326 bool endListenerAdded =
false;
327 bool closeListenerAdded =
false;
342 Function<Result(
size_t, Span<const char>)> onBroadcastFrame;
344 Result init(Span<HttpWebSocketHubClient> clientStorage);
347 Result leave(
size_t clientIndex);
349 Result broadcastFrame(Span<const char> encodedFrame);
350 Result broadcastText(Span<const char> payload, Span<char> frameStorage);
352 [[nodiscard]]
size_t getNumClients()
const {
return numClients; }
353 [[nodiscard]]
size_t getCapacity()
const {
return clients.sizeInElements(); }
354 [[nodiscard]]
bool isClientActive(
size_t clientIndex)
const;
357 Span<HttpWebSocketHubClient> clients;
358 size_t numClients = 0;
HttpWebSocketEndpointRole
Identifies the local endpoint role to validate masking rules.
Definition HttpWebSocket.h:38
HttpWebSocketOpcode
WebSocket frame opcode as defined by RFC 6455.
Definition HttpWebSocket.h:26
Definition AsyncStreams.h:66
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:177
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1447
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:228
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:364
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:428
Incoming HTTP response received by the client.
Definition HttpConnection.h:259
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:75
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:490
Method
Method of the current request / response.
Definition HttpParser.h:19
Incoming HTTP request received by the server.
Definition HttpConnection.h:233
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:383
Normalized client-side WebSocket opening handshake response data.
Definition HttpWebSocket.h:85
Small client-side helper that upgrades an HttpAsyncClient connection to a WebSocket transport.
Definition HttpWebSocket.h:140
Optional stream pump that binds a WebSocket transport to an endpoint lifecycle.
Definition HttpWebSocket.h:299
Small frame-lifecycle helper for ping / pong, close, and explicit fixed-buffer send backpressure.
Definition HttpWebSocket.h:244
Incremental WebSocket frame reader operating on caller-owned mutable byte slices.
Definition HttpWebSocket.h:160
Incremental WebSocket frame writer operating on caller-owned header storage and payload buffers.
Definition HttpWebSocket.h:200
Outcome of validating a WebSocket opening handshake.
Definition HttpWebSocket.h:95
Dependency-free RFC 6455 opening handshake helpers.
Definition HttpWebSocket.h:111
Fixed-slot WebSocket hub client entry.
Definition HttpWebSocket.h:332
Optional caller-buffered message assembly helper for applications that want complete messages.
Definition HttpWebSocket.h:220
Normalized server-side WebSocket opening handshake data.
Definition HttpWebSocket.h:73
Small fixed-capacity broadcast helper for server-side WebSocket fan-out.
Definition HttpWebSocket.h:341
Minimal transport handoff shape for later HTTP upgrade integration.
Definition HttpWebSocket.h:58