libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
websocket.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_HTTP
13#include <functional>
14#include <promeki/namespace.h>
15#include <promeki/objectbase.h>
16#include <promeki/error.h>
17#include <promeki/buffer.h>
18#include <promeki/string.h>
19#include <promeki/url.h>
20#include <promeki/list.h>
21#include <promeki/uniqueptr.h>
22#include <promeki/sslcontext.h>
23
24PROMEKI_NAMESPACE_BEGIN
25
26class TcpSocket;
27class EventLoop;
28class HttpRequest;
29class HttpResponse;
30
81class WebSocket : public ObjectBase {
82 PROMEKI_OBJECT(WebSocket, ObjectBase)
83 public:
85 using List = ::promeki::List<WebSocket *>;
86
88 enum State {
89 Disconnected,
90 Connecting,
91 Connected,
92 Closing
93 };
94
96 enum CloseCode : uint16_t {
97 CloseNormal = 1000,
98 CloseGoingAway = 1001,
99 CloseProtocolError = 1002,
100 CloseUnsupportedData = 1003,
101 CloseNoStatus = 1005,
102 CloseAbnormal = 1006,
103 CloseInvalidPayload = 1007,
104 ClosePolicyViolation = 1008,
105 CloseMessageTooBig = 1009,
106 CloseMissingExtension = 1010,
107 CloseInternalError = 1011
108 };
109
111 static constexpr int64_t DefaultMaxMessageBytes = 16 * 1024 * 1024;
112
114 explicit WebSocket(ObjectBase *parent = nullptr);
115
117 ~WebSocket() override;
118
119 // ----------------------------------------------------
120 // Client-side connect
121 // ----------------------------------------------------
122
141 Error connectToUrl(const String &url);
142
151 void setRequestedSubprotocols(const String &csv) { _requestedSubprotocols = csv; }
152
154 const String &requestedSubprotocols() const { return _requestedSubprotocols; }
155
161 void setRequestHeader(const String &name, const String &value);
162
179 void setSslContext(SslContext ctx) { _sslContext = std::move(ctx); }
180
182 SslContext sslContext() const { return _sslContext; }
183
189 static bool hasTlsSupport() { return SslContext::hasTlsSupport(); }
190
191 // ----------------------------------------------------
192 // Server-side adoption (used by HttpServer::routeWebSocket)
193 // ----------------------------------------------------
194
207 void adoptUpgradedSocket(TcpSocket *socket);
208
209 // ----------------------------------------------------
210 // Application API
211 // ----------------------------------------------------
212
214 Error sendTextMessage(const String &message);
215
217 Error sendBinaryMessage(const Buffer &message);
218
220 Error ping(const Buffer &payload = Buffer());
221
230 void disconnect(uint16_t code = CloseNormal, const String &reason = String());
231
238 void abort();
239
241 State state() const { return _state; }
242
244 bool isConnected() const { return _state == Connected; }
245
247 const String &negotiatedSubprotocol() const { return _negotiatedSubprotocol; }
248
256 void setMaxMessageBytes(int64_t bytes) { _maxMessageBytes = bytes; }
257
259 PROMEKI_SIGNAL(connected);
260
262 PROMEKI_SIGNAL(disconnected);
263
265 PROMEKI_SIGNAL(textMessageReceived, String);
266
268 PROMEKI_SIGNAL(binaryMessageReceived, Buffer);
269
271 PROMEKI_SIGNAL(pongReceived, Buffer);
272
274 PROMEKI_SIGNAL(errorOccurred, Error);
275
276 private:
277 struct Impl;
278 UniquePtr<Impl> _impl;
279
280 EventLoop *_loop = nullptr;
281 TcpSocket *_socket = nullptr;
282 int _ioHandle = -1;
283 State _state = Disconnected;
284 bool _isClient = false;
285
286 Url _url;
287 String _requestedSubprotocols;
288 String _negotiatedSubprotocol;
289 String _expectedAccept;
290 int64_t _maxMessageBytes = DefaultMaxMessageBytes;
291 bool _useTls = false;
292 bool _handshakeDone = false;
293
294 SslContext _sslContext;
295
296 void onIoReady(int fd, uint32_t events);
297 void readSome();
298 void pumpWrite();
299 void registerIo(uint32_t mask);
300
301 // Client-side handshake.
302 void writeClientHandshake();
303 void parseClientHandshakeResponse();
304
305 // Frame helpers.
306 Error sendFrame(uint8_t opcode, const void *data, size_t len, bool fin = true);
307 void processIncomingBytes();
308 void handleControlFrame(uint8_t opcode, Buffer payload);
309 void handleDataMessage(uint8_t opcode, Buffer payload);
310 void enqueueClose(uint16_t code, const String &reason);
311 void finalizeClose(Error err);
312
313 public:
314 // Internals exposed only so HttpServer::routeWebSocket
315 // can build the proper Sec-WebSocket-Accept. Not
316 // intended for application use.
317 static String computeAcceptValue(const String &clientKey);
318};
319
320PROMEKI_NAMESPACE_END
321
322#endif // PROMEKI_ENABLE_HTTP