11#include <promeki/config.h>
12#if PROMEKI_ENABLE_HTTP
24PROMEKI_NAMESPACE_BEGIN
81class WebSocket :
public ObjectBase {
82 PROMEKI_OBJECT(WebSocket, ObjectBase)
85 using List = ::promeki::List<WebSocket *>;
96 enum CloseCode : uint16_t {
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
111 static constexpr int64_t DefaultMaxMessageBytes = 16 * 1024 * 1024;
114 explicit WebSocket(ObjectBase *parent =
nullptr);
117 ~WebSocket()
override;
141 Error connectToUrl(
const String &url);
151 void setRequestedSubprotocols(
const String &csv) { _requestedSubprotocols = csv; }
154 const String &requestedSubprotocols()
const {
return _requestedSubprotocols; }
161 void setRequestHeader(
const String &name,
const String &value);
179 void setSslContext(SslContext ctx) { _sslContext = std::move(ctx); }
182 SslContext sslContext()
const {
return _sslContext; }
189 static bool hasTlsSupport() {
return SslContext::hasTlsSupport(); }
207 void adoptUpgradedSocket(TcpSocket *socket);
214 Error sendTextMessage(
const String &message);
217 Error sendBinaryMessage(
const Buffer &message);
220 Error ping(
const Buffer &payload = Buffer());
230 void disconnect(uint16_t code = CloseNormal,
const String &reason = String());
241 State state()
const {
return _state; }
244 bool isConnected()
const {
return _state == Connected; }
247 const String &negotiatedSubprotocol()
const {
return _negotiatedSubprotocol; }
256 void setMaxMessageBytes(int64_t bytes) { _maxMessageBytes = bytes; }
259 PROMEKI_SIGNAL(connected);
262 PROMEKI_SIGNAL(disconnected);
265 PROMEKI_SIGNAL(textMessageReceived, String);
268 PROMEKI_SIGNAL(binaryMessageReceived, Buffer);
271 PROMEKI_SIGNAL(pongReceived, Buffer);
274 PROMEKI_SIGNAL(errorOccurred, Error);
278 UniquePtr<Impl> _impl;
280 EventLoop *_loop =
nullptr;
281 TcpSocket *_socket =
nullptr;
283 State _state = Disconnected;
284 bool _isClient =
false;
287 String _requestedSubprotocols;
288 String _negotiatedSubprotocol;
289 String _expectedAccept;
290 int64_t _maxMessageBytes = DefaultMaxMessageBytes;
291 bool _useTls =
false;
292 bool _handshakeDone =
false;
294 SslContext _sslContext;
296 void onIoReady(
int fd, uint32_t events);
299 void registerIo(uint32_t mask);
302 void writeClientHandshake();
303 void parseClientHandshakeResponse();
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);
317 static String computeAcceptValue(
const String &clientKey);