Make getUserData type safe
This commit is contained in:
@@ -53,7 +53,7 @@ struct TemplatedApp {
|
|||||||
private:
|
private:
|
||||||
/* The app always owns at least one http context, but creates websocket contexts on demand */
|
/* The app always owns at least one http context, but creates websocket contexts on demand */
|
||||||
HttpContext<SSL> *httpContext;
|
HttpContext<SSL> *httpContext;
|
||||||
std::vector<WebSocketContext<SSL, true> *> webSocketContexts;
|
std::vector<WebSocketContext<SSL, true, int> *> webSocketContexts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -134,6 +134,7 @@ public:
|
|||||||
return !httpContext;
|
return !httpContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename UserData>
|
||||||
struct WebSocketBehavior {
|
struct WebSocketBehavior {
|
||||||
/* Disabled compression by default - probably a bad default */
|
/* Disabled compression by default - probably a bad default */
|
||||||
CompressOptions compression = DISABLED;
|
CompressOptions compression = DISABLED;
|
||||||
@@ -151,16 +152,16 @@ public:
|
|||||||
/* Maximum socket lifetime in seconds before forced closure (defaults to disabled) */
|
/* Maximum socket lifetime in seconds before forced closure (defaults to disabled) */
|
||||||
unsigned short maxLifetime = 0;
|
unsigned short maxLifetime = 0;
|
||||||
MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *, struct us_socket_context_t *)> upgrade = nullptr;
|
MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *, struct us_socket_context_t *)> upgrade = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> open = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *)> open = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *, std::string_view, OpCode)> message = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *, std::string_view, OpCode)> message = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> drain = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *)> drain = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> ping = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *)> ping = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> pong = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *)> pong = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *, int, std::string_view)> close = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *, int, std::string_view)> close = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename UserData>
|
template <typename UserData>
|
||||||
TemplatedApp &&ws(std::string pattern, WebSocketBehavior &&behavior) {
|
TemplatedApp &&ws(std::string pattern, WebSocketBehavior<UserData> &&behavior) {
|
||||||
/* Don't compile if alignment rules cannot be satisfied */
|
/* Don't compile if alignment rules cannot be satisfied */
|
||||||
static_assert(alignof(UserData) <= LIBUS_EXT_ALIGNMENT,
|
static_assert(alignof(UserData) <= LIBUS_EXT_ALIGNMENT,
|
||||||
"µWebSockets cannot satisfy UserData alignment requirements. You need to recompile µSockets with LIBUS_EXT_ALIGNMENT adjusted accordingly.");
|
"µWebSockets cannot satisfy UserData alignment requirements. You need to recompile µSockets with LIBUS_EXT_ALIGNMENT adjusted accordingly.");
|
||||||
@@ -180,10 +181,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Every route has its own websocket context with its own behavior and user data type */
|
/* Every route has its own websocket context with its own behavior and user data type */
|
||||||
auto *webSocketContext = WebSocketContext<SSL, true>::create(Loop::get(), (us_socket_context_t *) httpContext);
|
auto *webSocketContext = WebSocketContext<SSL, true, UserData>::create(Loop::get(), (us_socket_context_t *) httpContext);
|
||||||
|
|
||||||
/* We need to clear this later on */
|
/* We need to clear this later on */
|
||||||
webSocketContexts.push_back(webSocketContext);
|
webSocketContexts.push_back((WebSocketContext<SSL, true, int> *) webSocketContext);
|
||||||
|
|
||||||
/* Quick fix to disable any compression if set */
|
/* Quick fix to disable any compression if set */
|
||||||
#ifdef UWS_NO_ZLIB
|
#ifdef UWS_NO_ZLIB
|
||||||
@@ -206,7 +207,7 @@ public:
|
|||||||
webSocketContext->getExt()->openHandler = std::move(behavior.open);
|
webSocketContext->getExt()->openHandler = std::move(behavior.open);
|
||||||
webSocketContext->getExt()->messageHandler = std::move(behavior.message);
|
webSocketContext->getExt()->messageHandler = std::move(behavior.message);
|
||||||
webSocketContext->getExt()->drainHandler = std::move(behavior.drain);
|
webSocketContext->getExt()->drainHandler = std::move(behavior.drain);
|
||||||
webSocketContext->getExt()->closeHandler = std::move([closeHandler = std::move(behavior.close)](WebSocket<SSL, true> *ws, int code, std::string_view message) mutable {
|
webSocketContext->getExt()->closeHandler = std::move([closeHandler = std::move(behavior.close)](WebSocket<SSL, true, UserData> *ws, int code, std::string_view message) mutable {
|
||||||
if (closeHandler) {
|
if (closeHandler) {
|
||||||
closeHandler(ws, code, message);
|
closeHandler(ws, code, message);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -29,13 +29,13 @@
|
|||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
|
|
||||||
template <bool, bool> struct WebSocketContext;
|
template <bool, bool, typename> struct WebSocketContext;
|
||||||
|
|
||||||
template <bool SSL>
|
template <bool SSL>
|
||||||
struct AsyncSocket {
|
struct AsyncSocket {
|
||||||
template <bool> friend struct HttpContext;
|
template <bool> friend struct HttpContext;
|
||||||
template <bool, bool> friend struct WebSocketContext;
|
template <bool, bool, typename> friend struct WebSocketContext;
|
||||||
template <bool> friend struct WebSocketContextData;
|
template <bool, typename> friend struct WebSocketContextData;
|
||||||
friend struct TopicTree;
|
friend struct TopicTree;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
+2
-2
@@ -214,7 +214,7 @@ public:
|
|||||||
struct us_socket_context_t *webSocketContext) {
|
struct us_socket_context_t *webSocketContext) {
|
||||||
|
|
||||||
/* Extract needed parameters from WebSocketContextData */
|
/* Extract needed parameters from WebSocketContextData */
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, webSocketContext);
|
WebSocketContextData<SSL, UserData> *webSocketContextData = (WebSocketContextData<SSL, UserData> *) us_socket_context_ext(SSL, webSocketContext);
|
||||||
|
|
||||||
/* Note: OpenSSL can be used here to speed this up somewhat */
|
/* Note: OpenSSL can be used here to speed this up somewhat */
|
||||||
char secWebSocketAccept[29] = {};
|
char secWebSocketAccept[29] = {};
|
||||||
@@ -281,7 +281,7 @@ public:
|
|||||||
bool wasCorked = Super::isCorked();
|
bool wasCorked = Super::isCorked();
|
||||||
|
|
||||||
/* Adopting a socket invalidates it, do not rely on it directly to carry any data */
|
/* Adopting a socket invalidates it, do not rely on it directly to carry any data */
|
||||||
WebSocket<SSL, true> *webSocket = (WebSocket<SSL, true> *) us_socket_context_adopt_socket(SSL,
|
WebSocket<SSL, true, UserData> *webSocket = (WebSocket<SSL, true, UserData> *) us_socket_context_adopt_socket(SSL,
|
||||||
(us_socket_context_t *) webSocketContext, (us_socket_t *) this, sizeof(WebSocketData) + sizeof(UserData));
|
(us_socket_context_t *) webSocketContext, (us_socket_t *) this, sizeof(WebSocketData) + sizeof(UserData));
|
||||||
|
|
||||||
/* For whatever reason we were corked, update cork to the new socket */
|
/* For whatever reason we were corked, update cork to the new socket */
|
||||||
|
|||||||
+12
-13
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
|
|
||||||
template <bool SSL, bool isServer>
|
template <bool SSL, bool isServer, typename USERDATA>
|
||||||
struct WebSocket : AsyncSocket<SSL> {
|
struct WebSocket : AsyncSocket<SSL> {
|
||||||
template <bool> friend struct TemplatedApp;
|
template <bool> friend struct TemplatedApp;
|
||||||
template <bool> friend struct HttpResponse;
|
template <bool> friend struct HttpResponse;
|
||||||
@@ -41,10 +41,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/* Returns pointer to the per socket user data */
|
/* Returns pointer to the per socket user data */
|
||||||
void *getUserData() {
|
USERDATA *getUserData() {
|
||||||
WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this);
|
WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this);
|
||||||
/* We just have it overallocated by sizeof type */
|
/* We just have it overallocated by sizeof type */
|
||||||
return (webSocketData + 1);
|
return (USERDATA *) (webSocketData + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See AsyncSocket */
|
/* See AsyncSocket */
|
||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
/* Send or buffer a WebSocket frame, compressed or not. Returns BACKPRESSURE on increased user space backpressure,
|
/* Send or buffer a WebSocket frame, compressed or not. Returns BACKPRESSURE on increased user space backpressure,
|
||||||
* DROPPED on dropped message (due to backpressure) or SUCCCESS if you are free to send even more now. */
|
* DROPPED on dropped message (due to backpressure) or SUCCCESS if you are free to send even more now. */
|
||||||
SendStatus send(std::string_view message, OpCode opCode = OpCode::BINARY, bool compress = false) {
|
SendStatus send(std::string_view message, OpCode opCode = OpCode::BINARY, bool compress = false) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -159,17 +159,16 @@ public:
|
|||||||
bool ok = send(std::string_view(closePayload, closePayloadLength), OpCode::CLOSE);
|
bool ok = send(std::string_view(closePayload, closePayloadLength), OpCode::CLOSE);
|
||||||
|
|
||||||
/* FIN if we are ok and not corked */
|
/* FIN if we are ok and not corked */
|
||||||
WebSocket<SSL, true> *webSocket = (WebSocket<SSL, true> *) this;
|
if (!this->isCorked()) {
|
||||||
if (!webSocket->isCorked()) {
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
/* If we are not corked, and we just sent off everything, we need to FIN right here.
|
/* If we are not corked, and we just sent off everything, we need to FIN right here.
|
||||||
* In all other cases, we need to fin either if uncork was successful, or when drainage is complete. */
|
* In all other cases, we need to fin either if uncork was successful, or when drainage is complete. */
|
||||||
webSocket->shutdown();
|
this->shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit close event */
|
/* Emit close event */
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
if (webSocketContextData->closeHandler) {
|
if (webSocketContextData->closeHandler) {
|
||||||
@@ -199,7 +198,7 @@ public:
|
|||||||
|
|
||||||
/* Subscribe to a topic according to MQTT rules and syntax. Returns [numSubscribers, success]. */
|
/* Subscribe to a topic according to MQTT rules and syntax. Returns [numSubscribers, success]. */
|
||||||
std::pair<unsigned int, bool> subscribe(std::string_view topic, bool nonStrict = false) {
|
std::pair<unsigned int, bool> subscribe(std::string_view topic, bool nonStrict = false) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -214,7 +213,7 @@ public:
|
|||||||
|
|
||||||
/* Unsubscribe from a topic, returns true if we were subscribed. Returns [numSubscribers, success]. */
|
/* Unsubscribe from a topic, returns true if we were subscribed. Returns [numSubscribers, success]. */
|
||||||
std::pair<unsigned int, bool> unsubscribe(std::string_view topic, bool nonStrict = false) {
|
std::pair<unsigned int, bool> unsubscribe(std::string_view topic, bool nonStrict = false) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -225,7 +224,7 @@ public:
|
|||||||
|
|
||||||
/* Returns whether this socket is subscribed to the specified topic */
|
/* Returns whether this socket is subscribed to the specified topic */
|
||||||
bool isSubscribed(std::string_view topic) {
|
bool isSubscribed(std::string_view topic) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -239,7 +238,7 @@ public:
|
|||||||
|
|
||||||
/* Returns number of subscribers for this topic, or 0 for failure */
|
/* Returns number of subscribers for this topic, or 0 for failure */
|
||||||
unsigned int numSubscribers(std::string_view topic) {
|
unsigned int numSubscribers(std::string_view topic) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -274,7 +273,7 @@ public:
|
|||||||
* We, the WebSocket, must be subscribed to the topic itself and if so - no message will be sent to ourselves.
|
* We, the WebSocket, must be subscribed to the topic itself and if so - no message will be sent to ourselves.
|
||||||
* Use App::publish for an unconditional publish that simply publishes to whomever might be subscribed. */
|
* Use App::publish for an unconditional publish that simply publishes to whomever might be subscribed. */
|
||||||
bool publish(std::string_view topic, std::string_view message, OpCode opCode = OpCode::TEXT, bool compress = false) {
|
bool publish(std::string_view topic, std::string_view message, OpCode opCode = OpCode::TEXT, bool compress = false) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
|
||||||
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+20
-20
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
|
|
||||||
template <bool SSL, bool isServer>
|
template <bool SSL, bool isServer, typename USERDATA>
|
||||||
struct WebSocketContext {
|
struct WebSocketContext {
|
||||||
template <bool> friend struct TemplatedApp;
|
template <bool> friend struct TemplatedApp;
|
||||||
template <bool, typename> friend struct WebSocketProtocol;
|
template <bool, typename> friend struct WebSocketProtocol;
|
||||||
@@ -36,8 +36,8 @@ private:
|
|||||||
return (us_socket_context_t *) this;
|
return (us_socket_context_t *) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketContextData<SSL> *getExt() {
|
WebSocketContextData<SSL, USERDATA> *getExt() {
|
||||||
return (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
|
return (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have negotiated compression, set this frame compressed */
|
/* If we have negotiated compression, set this frame compressed */
|
||||||
@@ -59,7 +59,7 @@ private:
|
|||||||
/* Returns true on breakage */
|
/* Returns true on breakage */
|
||||||
static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState<isServer> *webSocketState, void *s) {
|
static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState<isServer> *webSocketState, void *s) {
|
||||||
/* WebSocketData and WebSocketContextData */
|
/* WebSocketData and WebSocketContextData */
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
|
WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
|
||||||
|
|
||||||
/* Is this a non-control frame? */
|
/* Is this a non-control frame? */
|
||||||
@@ -90,7 +90,7 @@ private:
|
|||||||
|
|
||||||
/* Emit message event & break if we are closed or shut down when returning */
|
/* Emit message event & break if we are closed or shut down when returning */
|
||||||
if (webSocketContextData->messageHandler) {
|
if (webSocketContextData->messageHandler) {
|
||||||
webSocketContextData->messageHandler((WebSocket<SSL, isServer> *) s, std::string_view(data, length), (OpCode) opCode);
|
webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
|
||||||
if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
|
if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ private:
|
|||||||
|
|
||||||
/* Emit message and check for shutdown or close */
|
/* Emit message and check for shutdown or close */
|
||||||
if (webSocketContextData->messageHandler) {
|
if (webSocketContextData->messageHandler) {
|
||||||
webSocketContextData->messageHandler((WebSocket<SSL, isServer> *) s, std::string_view(data, length), (OpCode) opCode);
|
webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
|
||||||
if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
|
if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ private:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Control frames need the websocket to send pings, pongs and close */
|
/* Control frames need the websocket to send pings, pongs and close */
|
||||||
WebSocket<SSL, isServer> *webSocket = (WebSocket<SSL, isServer> *) s;
|
WebSocket<SSL, isServer, USERDATA> *webSocket = (WebSocket<SSL, isServer, USERDATA> *) s;
|
||||||
|
|
||||||
if (!remainingBytes && fin && !webSocketData->controlTipLength) {
|
if (!remainingBytes && fin && !webSocketData->controlTipLength) {
|
||||||
if (opCode == CLOSE) {
|
if (opCode == CLOSE) {
|
||||||
@@ -225,13 +225,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
|
static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
|
|
||||||
/* Return true for refuse, false for accept */
|
/* Return true for refuse, false for accept */
|
||||||
return webSocketContextData->maxPayloadLength < length;
|
return webSocketContextData->maxPayloadLength < length;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketContext<SSL, isServer> *init() {
|
WebSocketContext<SSL, isServer, USERDATA> *init() {
|
||||||
/* Adopting a socket does not trigger open event.
|
/* Adopting a socket does not trigger open event.
|
||||||
* We arreive as WebSocket with timeout set and
|
* We arreive as WebSocket with timeout set and
|
||||||
* any backpressure from HTTP state kept. */
|
* any backpressure from HTTP state kept. */
|
||||||
@@ -242,10 +242,10 @@ private:
|
|||||||
WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
|
WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
|
||||||
if (!webSocketData->isShuttingDown) {
|
if (!webSocketData->isShuttingDown) {
|
||||||
/* Emit close event */
|
/* Emit close event */
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
|
|
||||||
if (webSocketContextData->closeHandler) {
|
if (webSocketContextData->closeHandler) {
|
||||||
webSocketContextData->closeHandler((WebSocket<SSL, true> *) s, 1006, {(char *) reason, (size_t) code});
|
webSocketContextData->closeHandler((WebSocket<SSL, isServer, USERDATA> *) s, 1006, {(char *) reason, (size_t) code});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure to unsubscribe from any pub/sub node at exit */
|
/* Make sure to unsubscribe from any pub/sub node at exit */
|
||||||
@@ -272,7 +272,7 @@ private:
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
auto *asyncSocket = (AsyncSocket<SSL> *) s;
|
auto *asyncSocket = (AsyncSocket<SSL> *) s;
|
||||||
|
|
||||||
/* Every time we get data and not in shutdown state we simply reset the timeout */
|
/* Every time we get data and not in shutdown state we simply reset the timeout */
|
||||||
@@ -283,7 +283,7 @@ private:
|
|||||||
asyncSocket->cork();
|
asyncSocket->cork();
|
||||||
|
|
||||||
/* This parser has virtually no overhead */
|
/* This parser has virtually no overhead */
|
||||||
WebSocketProtocol<isServer, WebSocketContext<SSL, isServer>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
|
WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
|
||||||
|
|
||||||
/* Uncorking a closed socekt is fine, in fact it is needed */
|
/* Uncorking a closed socekt is fine, in fact it is needed */
|
||||||
asyncSocket->uncork();
|
asyncSocket->uncork();
|
||||||
@@ -325,7 +325,7 @@ private:
|
|||||||
/* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
|
/* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
|
||||||
/* Also reset timeout if we came here with 0 backpressure */
|
/* Also reset timeout if we came here with 0 backpressure */
|
||||||
if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
|
if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
|
asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
|
||||||
webSocketData->hasTimedOut = false;
|
webSocketData->hasTimedOut = false;
|
||||||
}
|
}
|
||||||
@@ -339,9 +339,9 @@ private:
|
|||||||
}
|
}
|
||||||
} else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
|
} else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
|
||||||
/* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
|
/* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
if (webSocketContextData->drainHandler) {
|
if (webSocketContextData->drainHandler) {
|
||||||
webSocketContextData->drainHandler((WebSocket<SSL, isServer> *) s);
|
webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
|
||||||
}
|
}
|
||||||
/* No need to check for closed here as we leave the handler immediately*/
|
/* No need to check for closed here as we leave the handler immediately*/
|
||||||
}
|
}
|
||||||
@@ -362,7 +362,7 @@ private:
|
|||||||
us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
|
us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
|
auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
|
|
||||||
if (webSocketContextData->sendPingsAutomatically && !webSocketData->hasTimedOut) {
|
if (webSocketContextData->sendPingsAutomatically && !webSocketData->hasTimedOut) {
|
||||||
webSocketData->hasTimedOut = true;
|
webSocketData->hasTimedOut = true;
|
||||||
@@ -383,7 +383,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
|
WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
|
||||||
webSocketContextData->~WebSocketContextData();
|
webSocketContextData->~WebSocketContextData();
|
||||||
|
|
||||||
us_socket_context_free(SSL, (us_socket_context_t *) this);
|
us_socket_context_free(SSL, (us_socket_context_t *) this);
|
||||||
@@ -392,13 +392,13 @@ private:
|
|||||||
public:
|
public:
|
||||||
/* WebSocket contexts are always child contexts to a HTTP context so no SSL options are needed as they are inherited */
|
/* WebSocket contexts are always child contexts to a HTTP context so no SSL options are needed as they are inherited */
|
||||||
static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext) {
|
static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext) {
|
||||||
WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL>));
|
WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL, USERDATA>));
|
||||||
if (!webSocketContext) {
|
if (!webSocketContext) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init socket context data */
|
/* Init socket context data */
|
||||||
new ((WebSocketContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL>;
|
new ((WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL, USERDATA>;
|
||||||
return webSocketContext->init();
|
return webSocketContext->init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,11 +27,11 @@
|
|||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
|
|
||||||
template <bool, bool> struct WebSocket;
|
template <bool, bool, typename> struct WebSocket;
|
||||||
|
|
||||||
/* todo: this looks identical to WebSocketBehavior, why not just std::move that entire thing in? */
|
/* todo: this looks identical to WebSocketBehavior, why not just std::move that entire thing in? */
|
||||||
|
|
||||||
template <bool SSL>
|
template <bool SSL, typename USERDATA>
|
||||||
struct WebSocketContextData {
|
struct WebSocketContextData {
|
||||||
private:
|
private:
|
||||||
/* Used for prepending unframed messages when using dedicated compressors */
|
/* Used for prepending unframed messages when using dedicated compressors */
|
||||||
@@ -47,13 +47,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/* The callbacks for this context */
|
/* The callbacks for this context */
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> openHandler = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, USERDATA> *)> openHandler = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *, std::string_view, OpCode)> messageHandler = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, USERDATA> *, std::string_view, OpCode)> messageHandler = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> drainHandler = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, USERDATA> *)> drainHandler = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *, int, std::string_view)> closeHandler = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, USERDATA> *, int, std::string_view)> closeHandler = nullptr;
|
||||||
/* Todo: these should take message also; breaking change for v0.18 */
|
/* Todo: these should take message also; breaking change for v0.18 */
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> pingHandler = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, USERDATA> *)> pingHandler = nullptr;
|
||||||
MoveOnlyFunction<void(WebSocket<SSL, true> *)> pongHandler = nullptr;
|
MoveOnlyFunction<void(WebSocket<SSL, true, USERDATA> *)> pongHandler = nullptr;
|
||||||
|
|
||||||
/* Settings for this context */
|
/* Settings for this context */
|
||||||
size_t maxPayloadLength = 0;
|
size_t maxPayloadLength = 0;
|
||||||
@@ -135,7 +135,7 @@ public:
|
|||||||
/* However, dedicated compression has its own path */
|
/* However, dedicated compression has its own path */
|
||||||
if (compression != SHARED_COMPRESSOR) {
|
if (compression != SHARED_COMPRESSOR) {
|
||||||
|
|
||||||
WebSocket<SSL, true> *ws = (WebSocket<SSL, true> *) asyncSocket;
|
WebSocket<SSL, true, int> *ws = (WebSocket<SSL, true, int> *) asyncSocket;
|
||||||
|
|
||||||
/* For performance reasons we always cork when in dedicated mode.
|
/* For performance reasons we always cork when in dedicated mode.
|
||||||
* Is this really the best? We already kind of cork things in Zlib?
|
* Is this really the best? We already kind of cork things in Zlib?
|
||||||
|
|||||||
+3
-3
@@ -29,9 +29,9 @@ namespace uWS {
|
|||||||
|
|
||||||
struct WebSocketData : AsyncSocketData<false>, WebSocketState<true> {
|
struct WebSocketData : AsyncSocketData<false>, WebSocketState<true> {
|
||||||
/* This guy has a lot of friends - why? */
|
/* This guy has a lot of friends - why? */
|
||||||
template <bool, bool> friend struct WebSocketContext;
|
template <bool, bool, typename> friend struct WebSocketContext;
|
||||||
template <bool> friend struct WebSocketContextData;
|
template <bool, typename> friend struct WebSocketContextData;
|
||||||
template <bool, bool> friend struct WebSocket;
|
template <bool, bool, typename> friend struct WebSocket;
|
||||||
template <bool> friend struct HttpContext;
|
template <bool> friend struct HttpContext;
|
||||||
private:
|
private:
|
||||||
std::string fragmentBuffer;
|
std::string fragmentBuffer;
|
||||||
|
|||||||
Reference in New Issue
Block a user