Upgrade to uSockets 0.2.0a1 (experimental)
This commit is contained in:
@@ -77,7 +77,7 @@ public:
|
|||||||
webSocketContexts = std::move(other.webSocketContexts);
|
webSocketContexts = std::move(other.webSocketContexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplatedApp(us_new_socket_context_options_t options = {}) {
|
TemplatedApp(us_socket_context_options_t options = {}) {
|
||||||
httpContext = uWS::HttpContext<SSL>::create(uWS::Loop::get(), options);
|
httpContext = uWS::HttpContext<SSL>::create(uWS::Loop::get(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ public:
|
|||||||
"µ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.");
|
||||||
|
|
||||||
/* 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_new_socket_context_t *) httpContext);
|
auto *webSocketContext = WebSocketContext<SSL, true>::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);
|
||||||
@@ -116,7 +116,7 @@ public:
|
|||||||
|
|
||||||
/* If we are the first one to use compression, initialize it */
|
/* If we are the first one to use compression, initialize it */
|
||||||
if (behavior.compression) {
|
if (behavior.compression) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(us_new_socket_context_loop(SSL, webSocketContext->getSocketContext()));
|
LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, webSocketContext->getSocketContext()));
|
||||||
|
|
||||||
/* Initialize loop's deflate inflate streams */
|
/* Initialize loop's deflate inflate streams */
|
||||||
if (!loopData->zlibContext) {
|
if (!loopData->zlibContext) {
|
||||||
@@ -198,8 +198,8 @@ public:
|
|||||||
res->getHttpResponseData()->~HttpResponseData();
|
res->getHttpResponseData()->~HttpResponseData();
|
||||||
|
|
||||||
/* 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_new_socket_context_adopt_socket(SSL,
|
WebSocket<SSL, true> *webSocket = (WebSocket<SSL, true> *) us_socket_context_adopt_socket(SSL,
|
||||||
(us_new_socket_context_t *) webSocketContext, (us_new_socket_t *) res, sizeof(WebSocketData) + sizeof(UserData));
|
(us_socket_context_t *) webSocketContext, (us_socket_t *) res, sizeof(WebSocketData) + sizeof(UserData));
|
||||||
|
|
||||||
/* Update corked socket in case we got a new one (assuming we always are corked in handlers). */
|
/* Update corked socket in case we got a new one (assuming we always are corked in handlers). */
|
||||||
webSocket->cork();
|
webSocket->cork();
|
||||||
@@ -211,7 +211,7 @@ public:
|
|||||||
|
|
||||||
/* Emit open event and start the timeout */
|
/* Emit open event and start the timeout */
|
||||||
if (behavior.open) {
|
if (behavior.open) {
|
||||||
us_new_socket_timeout(SSL, (us_new_socket_t *) webSocket, behavior.idleTimeout);
|
us_socket_timeout(SSL, (us_socket_t *) webSocket, behavior.idleTimeout);
|
||||||
behavior.open(webSocket, req);
|
behavior.open(webSocket, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Host, port, callback */
|
/* Host, port, callback */
|
||||||
TemplatedApp &&listen(std::string host, int port, fu2::unique_function<void(us_listen_socket *)> &&handler) {
|
TemplatedApp &&listen(std::string host, int port, fu2::unique_function<void(us_listen_socket_t *)> &&handler) {
|
||||||
if (!host.length()) {
|
if (!host.length()) {
|
||||||
return listen(port, std::move(handler));
|
return listen(port, std::move(handler));
|
||||||
}
|
}
|
||||||
@@ -287,7 +287,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Host, port, options, callback */
|
/* Host, port, options, callback */
|
||||||
TemplatedApp &&listen(std::string host, int port, int options, fu2::unique_function<void(us_listen_socket *)> &&handler) {
|
TemplatedApp &&listen(std::string host, int port, int options, fu2::unique_function<void(us_listen_socket_t *)> &&handler) {
|
||||||
if (!host.length()) {
|
if (!host.length()) {
|
||||||
return listen(port, options, std::move(handler));
|
return listen(port, options, std::move(handler));
|
||||||
}
|
}
|
||||||
@@ -296,13 +296,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Port, callback */
|
/* Port, callback */
|
||||||
TemplatedApp &&listen(int port, fu2::unique_function<void(us_listen_socket *)> &&handler) {
|
TemplatedApp &&listen(int port, fu2::unique_function<void(us_listen_socket_t *)> &&handler) {
|
||||||
handler(httpContext->listen(nullptr, port, 0));
|
handler(httpContext->listen(nullptr, port, 0));
|
||||||
return std::move(*this);
|
return std::move(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Port, options, callback */
|
/* Port, options, callback */
|
||||||
TemplatedApp &&listen(int port, int options, fu2::unique_function<void(us_listen_socket *)> &&handler) {
|
TemplatedApp &&listen(int port, int options, fu2::unique_function<void(us_listen_socket_t *)> &&handler) {
|
||||||
handler(httpContext->listen(nullptr, port, options));
|
handler(httpContext->listen(nullptr, port, options));
|
||||||
return std::move(*this);
|
return std::move(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -36,27 +36,27 @@ struct AsyncSocket {
|
|||||||
protected:
|
protected:
|
||||||
/* Get loop data for socket */
|
/* Get loop data for socket */
|
||||||
LoopData *getLoopData() {
|
LoopData *getLoopData() {
|
||||||
return (LoopData *) us_loop_ext(us_new_socket_context_loop(SSL, us_new_socket_context(SSL, (us_new_socket_t *) this)));
|
return (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get socket extension */
|
/* Get socket extension */
|
||||||
AsyncSocketData<SSL> *getAsyncSocketData() {
|
AsyncSocketData<SSL> *getAsyncSocketData() {
|
||||||
return (AsyncSocketData<SSL> *) us_new_socket_ext(SSL, (us_new_socket_t *) this);
|
return (AsyncSocketData<SSL> *) us_socket_ext(SSL, (us_socket_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Socket timeout */
|
/* Socket timeout */
|
||||||
void timeout(unsigned int seconds) {
|
void timeout(unsigned int seconds) {
|
||||||
us_new_socket_timeout(SSL, (us_new_socket_t *) this, seconds);
|
us_socket_timeout(SSL, (us_socket_t *) this, seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shutdown socket without any automatic drainage */
|
/* Shutdown socket without any automatic drainage */
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
us_new_socket_shutdown(SSL, (us_new_socket_t *) this);
|
us_socket_shutdown(SSL, (us_socket_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Immediately close socket */
|
/* Immediately close socket */
|
||||||
us_new_socket_t *close() {
|
us_socket_t *close() {
|
||||||
return us_new_socket_close(SSL, (us_new_socket_t *) this);
|
return us_socket_close(SSL, (us_socket_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cork this socket. Only one socket may ever be corked per-loop at any given time */
|
/* Cork this socket. Only one socket may ever be corked per-loop at any given time */
|
||||||
@@ -98,7 +98,7 @@ protected:
|
|||||||
std::string_view getRemoteAddress() {
|
std::string_view getRemoteAddress() {
|
||||||
static thread_local char buf[16];
|
static thread_local char buf[16];
|
||||||
int ipLength = 16;
|
int ipLength = 16;
|
||||||
us_new_socket_remote_address(SSL, (us_new_socket_t *) this, buf, &ipLength);
|
us_socket_remote_address(SSL, (us_socket_t *) this, buf, &ipLength);
|
||||||
return std::string_view(buf, ipLength);
|
return std::string_view(buf, ipLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ protected:
|
|||||||
* writable (or we are in a state that implies polling for writable). */
|
* writable (or we are in a state that implies polling for writable). */
|
||||||
std::pair<int, bool> write(const char *src, int length, bool optionally = false, int nextLength = 0) {
|
std::pair<int, bool> write(const char *src, int length, bool optionally = false, int nextLength = 0) {
|
||||||
/* Fake success if closed, simple fix to allow uncork of closed socket to succeed */
|
/* Fake success if closed, simple fix to allow uncork of closed socket to succeed */
|
||||||
if (us_new_socket_is_closed(SSL, (us_new_socket_t *) this)) {
|
if (us_socket_is_closed(SSL, (us_socket_t *) this)) {
|
||||||
return {length, false};
|
return {length, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ protected:
|
|||||||
/* We are limited if we have a per-socket buffer */
|
/* We are limited if we have a per-socket buffer */
|
||||||
if (asyncSocketData->buffer.length()) {
|
if (asyncSocketData->buffer.length()) {
|
||||||
/* Write off as much as we can */
|
/* Write off as much as we can */
|
||||||
int written = us_new_socket_write(SSL, (us_new_socket_t *) this, asyncSocketData->buffer.data(), asyncSocketData->buffer.length(), /*nextLength != 0 | */length);
|
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), asyncSocketData->buffer.length(), /*nextLength != 0 | */length);
|
||||||
|
|
||||||
/* On failure return, otherwise continue down the function */
|
/* On failure return, otherwise continue down the function */
|
||||||
if (written < asyncSocketData->buffer.length()) {
|
if (written < asyncSocketData->buffer.length()) {
|
||||||
@@ -165,7 +165,7 @@ protected:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We are not corked */
|
/* We are not corked */
|
||||||
int written = us_new_socket_write(SSL, (us_new_socket_t *) this, src, length, nextLength != 0);
|
int written = us_socket_write(SSL, (us_socket_t *) this, src, length, nextLength != 0);
|
||||||
|
|
||||||
/* Did we fail? */
|
/* Did we fail? */
|
||||||
if (written < length) {
|
if (written < length) {
|
||||||
|
|||||||
+38
-38
@@ -40,31 +40,31 @@ private:
|
|||||||
/* Maximum delay allowed until an HTTP connection is terminated due to outstanding request or rejected data (slow loris protection) */
|
/* Maximum delay allowed until an HTTP connection is terminated due to outstanding request or rejected data (slow loris protection) */
|
||||||
static const int HTTP_IDLE_TIMEOUT_S = 10;
|
static const int HTTP_IDLE_TIMEOUT_S = 10;
|
||||||
|
|
||||||
us_new_socket_context_t *getSocketContext() {
|
us_socket_context_t *getSocketContext() {
|
||||||
return (us_new_socket_context_t *) this;
|
return (us_socket_context_t *) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static us_new_socket_context_t *getSocketContext(us_new_socket_t *s) {
|
static us_socket_context_t *getSocketContext(us_socket_t *s) {
|
||||||
return (us_new_socket_context_t *) us_new_socket_context(SSL, s);
|
return (us_socket_context_t *) us_socket_context(SSL, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpContextData<SSL> *getSocketContextData() {
|
HttpContextData<SSL> *getSocketContextData() {
|
||||||
return (HttpContextData<SSL> *) us_new_socket_context_ext(SSL, getSocketContext());
|
return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
static HttpContextData<SSL> *getSocketContextDataS(us_new_socket_t *s) {
|
static HttpContextData<SSL> *getSocketContextDataS(us_socket_t *s) {
|
||||||
return (HttpContextData<SSL> *) us_new_socket_context_ext(SSL, getSocketContext(s));
|
return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init the HttpContext by registering libusockets event handlers */
|
/* Init the HttpContext by registering libusockets event handlers */
|
||||||
HttpContext<SSL> *init() {
|
HttpContext<SSL> *init() {
|
||||||
/* Handle socket connections */
|
/* Handle socket connections */
|
||||||
us_new_socket_context_on_open(SSL, getSocketContext(), [](us_new_socket_t *s, int is_client, char *ip, int ip_length) {
|
us_socket_context_on_open(SSL, getSocketContext(), [](us_socket_t *s, int is_client, char *ip, int ip_length) {
|
||||||
/* Any connected socket should timeout until it has a request */
|
/* Any connected socket should timeout until it has a request */
|
||||||
us_new_socket_timeout(SSL, s, HTTP_IDLE_TIMEOUT_S);
|
us_socket_timeout(SSL, s, HTTP_IDLE_TIMEOUT_S);
|
||||||
|
|
||||||
/* Init socket ext */
|
/* Init socket ext */
|
||||||
new (us_new_socket_ext(SSL, s)) HttpResponseData<SSL>;
|
new (us_socket_ext(SSL, s)) HttpResponseData<SSL>;
|
||||||
|
|
||||||
/* Call filter */
|
/* Call filter */
|
||||||
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
|
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
|
||||||
@@ -76,9 +76,9 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle socket disconnections */
|
/* Handle socket disconnections */
|
||||||
us_new_socket_context_on_close(SSL, getSocketContext(), [](us_new_socket_t *s) {
|
us_socket_context_on_close(SSL, getSocketContext(), [](us_socket_t *s) {
|
||||||
/* Get socket ext */
|
/* Get socket ext */
|
||||||
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_new_socket_ext(SSL, s);
|
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
|
||||||
|
|
||||||
/* Call filter */
|
/* Call filter */
|
||||||
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
|
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
|
||||||
@@ -98,7 +98,7 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle HTTP data streams */
|
/* Handle HTTP data streams */
|
||||||
us_new_socket_context_on_data(SSL, getSocketContext(), [](us_new_socket_t *s, char *data, int length) {
|
us_socket_context_on_data(SSL, getSocketContext(), [](us_socket_t *s, char *data, int length) {
|
||||||
|
|
||||||
// total overhead is about 210k down to 180k
|
// total overhead is about 210k down to 180k
|
||||||
// ~210k req/sec is the original perf with write in data
|
// ~210k req/sec is the original perf with write in data
|
||||||
@@ -109,11 +109,11 @@ private:
|
|||||||
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
|
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
|
||||||
|
|
||||||
/* Do not accept any data while in shutdown state */
|
/* Do not accept any data while in shutdown state */
|
||||||
if (us_new_socket_is_shut_down(SSL, (us_new_socket_t *) s)) {
|
if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_new_socket_ext(SSL, s);
|
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
|
||||||
|
|
||||||
/* Cork this socket */
|
/* Cork this socket */
|
||||||
((AsyncSocket<SSL> *) s)->cork();
|
((AsyncSocket<SSL> *) s)->cork();
|
||||||
@@ -125,15 +125,15 @@ private:
|
|||||||
void *returnedSocket = httpResponseData->consumePostPadded(data, length, s, [httpContextData](void *s, uWS::HttpRequest *httpRequest) -> void * {
|
void *returnedSocket = httpResponseData->consumePostPadded(data, length, s, [httpContextData](void *s, uWS::HttpRequest *httpRequest) -> void * {
|
||||||
/* For every request we reset the timeout and hang until user makes action */
|
/* For every request we reset the timeout and hang until user makes action */
|
||||||
/* Warning: if we are in shutdown state, resetting the timer is a security issue! */
|
/* Warning: if we are in shutdown state, resetting the timer is a security issue! */
|
||||||
us_new_socket_timeout(SSL, (us_new_socket_t *) s, 0);
|
us_socket_timeout(SSL, (us_socket_t *) s, 0);
|
||||||
|
|
||||||
/* Reset httpResponse */
|
/* Reset httpResponse */
|
||||||
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_new_socket_ext(SSL, (us_new_socket_t *) s);
|
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, (us_socket_t *) s);
|
||||||
httpResponseData->offset = 0;
|
httpResponseData->offset = 0;
|
||||||
|
|
||||||
/* Are we not ready for another request yet? Terminate the connection. */
|
/* Are we not ready for another request yet? Terminate the connection. */
|
||||||
if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
|
if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
|
||||||
us_new_socket_close(SSL, (us_new_socket_t *) s);
|
us_socket_close(SSL, (us_socket_t *) s);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ private:
|
|||||||
/* If first pass failed, we try and match by "any" method */
|
/* If first pass failed, we try and match by "any" method */
|
||||||
if (!httpContextData->router.route("*", httpRequest->getUrl(), routerData)) {
|
if (!httpContextData->router.route("*", httpRequest->getUrl(), routerData)) {
|
||||||
/* If second pass fail, we have to force close this socket as we have no handler for it */
|
/* If second pass fail, we have to force close this socket as we have no handler for it */
|
||||||
us_new_socket_close(SSL, (us_new_socket_t *) s);
|
us_socket_close(SSL, (us_socket_t *) s);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,12 +158,12 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Was the socket closed? */
|
/* Was the socket closed? */
|
||||||
if (us_new_socket_is_closed(SSL, (struct us_new_socket_t *) s)) {
|
if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We absolutely have to terminate parsing if shutdown */
|
/* We absolutely have to terminate parsing if shutdown */
|
||||||
if (us_new_socket_is_shut_down(SSL, (us_new_socket_t *) s)) {
|
if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ private:
|
|||||||
|
|
||||||
/* If we have not responded and we have a data handler, we need to timeout to enfore client sending the data */
|
/* If we have not responded and we have a data handler, we need to timeout to enfore client sending the data */
|
||||||
if (!((HttpResponse<SSL> *) s)->hasResponded() && httpResponseData->inStream) {
|
if (!((HttpResponse<SSL> *) s)->hasResponded() && httpResponseData->inStream) {
|
||||||
us_new_socket_timeout(SSL, (us_new_socket_t *) s, HTTP_IDLE_TIMEOUT_S);
|
us_socket_timeout(SSL, (us_socket_t *) s, HTTP_IDLE_TIMEOUT_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Continue parsing */
|
/* Continue parsing */
|
||||||
@@ -188,25 +188,25 @@ private:
|
|||||||
|
|
||||||
/* Getting a chunk of data while having a data handler should reset timeout (todo: if last, short timeout, if not last, bigger timeout) */
|
/* Getting a chunk of data while having a data handler should reset timeout (todo: if last, short timeout, if not last, bigger timeout) */
|
||||||
/* Really, we only need to reset timeout to the larger delay if we are not fin */
|
/* Really, we only need to reset timeout to the larger delay if we are not fin */
|
||||||
us_new_socket_timeout(SSL, (struct us_new_socket_t *) user, HTTP_IDLE_TIMEOUT_S);
|
us_socket_timeout(SSL, (struct us_socket_t *) user, HTTP_IDLE_TIMEOUT_S);
|
||||||
|
|
||||||
/* We might respond in the handler, so do not change timeout after this */
|
/* We might respond in the handler, so do not change timeout after this */
|
||||||
httpResponseData->inStream(data, fin);
|
httpResponseData->inStream(data, fin);
|
||||||
|
|
||||||
/* Was the socket closed? */
|
/* Was the socket closed? */
|
||||||
if (us_new_socket_is_closed(SSL, (struct us_new_socket_t *) user)) {
|
if (us_socket_is_closed(SSL, (struct us_socket_t *) user)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We absolutely have to terminate parsing if shutdown */
|
/* We absolutely have to terminate parsing if shutdown */
|
||||||
if (us_new_socket_is_shut_down(SSL, (us_new_socket_t *) user)) {
|
if (us_socket_is_shut_down(SSL, (us_socket_t *) user)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}, [](void *user) {
|
}, [](void *user) {
|
||||||
/* Close any socket on HTTP errors */
|
/* Close any socket on HTTP errors */
|
||||||
us_new_socket_close(SSL, (us_new_socket_t *) user);
|
us_socket_close(SSL, (us_socket_t *) user);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ private:
|
|||||||
((AsyncSocket<SSL> *) s)->timeout(HTTP_IDLE_TIMEOUT_S);
|
((AsyncSocket<SSL> *) s)->timeout(HTTP_IDLE_TIMEOUT_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (us_new_socket_t *) returnedSocket;
|
return (us_socket_t *) returnedSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we upgraded, check here (differ between nullptr close and nullptr upgrade) */
|
/* If we upgraded, check here (differ between nullptr close and nullptr upgrade) */
|
||||||
@@ -234,7 +234,7 @@ private:
|
|||||||
httpContextData->upgradedWebSocket = nullptr;
|
httpContextData->upgradedWebSocket = nullptr;
|
||||||
|
|
||||||
/* Return the new upgraded websocket */
|
/* Return the new upgraded websocket */
|
||||||
return (us_new_socket_t *) asyncSocket;
|
return (us_socket_t *) asyncSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We cannot return nullptr to the underlying stack in any case */
|
/* We cannot return nullptr to the underlying stack in any case */
|
||||||
@@ -242,7 +242,7 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
|
/* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
|
||||||
us_new_socket_context_on_writable(SSL, getSocketContext(), [](us_new_socket_t *s) {
|
us_socket_context_on_writable(SSL, getSocketContext(), [](us_socket_t *s) {
|
||||||
|
|
||||||
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
||||||
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) asyncSocket->getAsyncSocketData();
|
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) asyncSocket->getAsyncSocketData();
|
||||||
@@ -250,7 +250,7 @@ private:
|
|||||||
/* Ask the developer to write data and return success (true) or failure (false), OR skip sending anything and return success (true). */
|
/* Ask the developer to write data and return success (true) or failure (false), OR skip sending anything and return success (true). */
|
||||||
if (httpResponseData->onWritable) {
|
if (httpResponseData->onWritable) {
|
||||||
/* We are now writable, so hang timeout again, the user does not have to do anything so we should hang until end or tryEnd rearms timeout */
|
/* We are now writable, so hang timeout again, the user does not have to do anything so we should hang until end or tryEnd rearms timeout */
|
||||||
us_new_socket_timeout(SSL, s, 0);
|
us_socket_timeout(SSL, s, 0);
|
||||||
|
|
||||||
/* We expect the developer to return whether or not write was successful (true).
|
/* We expect the developer to return whether or not write was successful (true).
|
||||||
* If write was never called, the developer should still return true so that we may drain. */
|
* If write was never called, the developer should still return true so that we may drain. */
|
||||||
@@ -277,7 +277,7 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle FIN, HTTP does not support half-closed sockets, so simply close */
|
/* Handle FIN, HTTP does not support half-closed sockets, so simply close */
|
||||||
us_new_socket_context_on_end(SSL, getSocketContext(), [](us_new_socket_t *s) {
|
us_socket_context_on_end(SSL, getSocketContext(), [](us_socket_t *s) {
|
||||||
|
|
||||||
/* We do not care for half closed sockets */
|
/* We do not care for half closed sockets */
|
||||||
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
||||||
@@ -286,7 +286,7 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle socket timeouts, simply close them so to not confuse client with FIN */
|
/* Handle socket timeouts, simply close them so to not confuse client with FIN */
|
||||||
us_new_socket_context_on_timeout(SSL, getSocketContext(), [](us_new_socket_t *s) {
|
us_socket_context_on_timeout(SSL, getSocketContext(), [](us_socket_t *s) {
|
||||||
|
|
||||||
/* Force close rather than gracefully shutdown and risk confusing the client with a complete download */
|
/* Force close rather than gracefully shutdown and risk confusing the client with a complete download */
|
||||||
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
||||||
@@ -306,17 +306,17 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/* Construct a new HttpContext using specified loop */
|
/* Construct a new HttpContext using specified loop */
|
||||||
static HttpContext *create(Loop *loop, us_new_socket_context_options_t options = {}) {
|
static HttpContext *create(Loop *loop, us_socket_context_options_t options = {}) {
|
||||||
HttpContext *httpContext;
|
HttpContext *httpContext;
|
||||||
|
|
||||||
httpContext = (HttpContext *) us_new_create_socket_context(SSL, (us_loop *) loop, sizeof(HttpContextData<SSL>), options);
|
httpContext = (HttpContext *) us_create_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData<SSL>), options);
|
||||||
|
|
||||||
if (!httpContext) {
|
if (!httpContext) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init socket context data */
|
/* Init socket context data */
|
||||||
new ((HttpContextData<SSL> *) us_new_socket_context_ext(SSL, (us_new_socket_context_t *) httpContext)) HttpContextData<SSL>();
|
new ((HttpContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) httpContext)) HttpContextData<SSL>();
|
||||||
return httpContext->init();
|
return httpContext->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ public:
|
|||||||
httpContextData->~HttpContextData<SSL>();
|
httpContextData->~HttpContextData<SSL>();
|
||||||
|
|
||||||
/* Free the socket context in whole */
|
/* Free the socket context in whole */
|
||||||
us_new_socket_context_free(SSL, getSocketContext());
|
us_socket_context_free(SSL, getSocketContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter(fu2::unique_function<void(HttpResponse<SSL> *, int)> &&filterHandler) {
|
void filter(fu2::unique_function<void(HttpResponse<SSL> *, int)> &&filterHandler) {
|
||||||
@@ -352,8 +352,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Listen to port using this HttpContext */
|
/* Listen to port using this HttpContext */
|
||||||
us_listen_socket *listen(const char *host, int port, int options) {
|
us_listen_socket_t *listen(const char *host, int port, int options) {
|
||||||
return us_new_socket_context_listen(SSL, getSocketContext(), host, port, options, sizeof(HttpResponseData<SSL>));
|
return us_socket_context_listen(SSL, getSocketContext(), host, port, options, sizeof(HttpResponseData<SSL>));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+18
-19
@@ -21,12 +21,12 @@
|
|||||||
/* The loop is lazily created per-thread and run with uWS::run() */
|
/* The loop is lazily created per-thread and run with uWS::run() */
|
||||||
|
|
||||||
#include "LoopData.h"
|
#include "LoopData.h"
|
||||||
#include <libusockets_new.h>
|
#include <libusockets.h>
|
||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
struct Loop {
|
struct Loop {
|
||||||
private:
|
private:
|
||||||
static void wakeupCb(us_loop *loop) {
|
static void wakeupCb(us_loop_t *loop) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(loop);
|
LoopData *loopData = (LoopData *) us_loop_ext(loop);
|
||||||
|
|
||||||
/* Swap current deferQueue */
|
/* Swap current deferQueue */
|
||||||
@@ -42,7 +42,7 @@ private:
|
|||||||
loopData->deferQueues[oldDeferQueue].clear();
|
loopData->deferQueues[oldDeferQueue].clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void preCb(us_loop *loop) {
|
static void preCb(us_loop_t *loop) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(loop);
|
LoopData *loopData = (LoopData *) us_loop_ext(loop);
|
||||||
|
|
||||||
if (loopData->preHandler) {
|
if (loopData->preHandler) {
|
||||||
@@ -55,7 +55,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void postCb(us_loop *loop) {
|
static void postCb(us_loop_t *loop) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(loop);
|
LoopData *loopData = (LoopData *) us_loop_ext(loop);
|
||||||
|
|
||||||
/* We should move over to using only these */
|
/* We should move over to using only these */
|
||||||
@@ -72,13 +72,12 @@ private:
|
|||||||
~Loop() = default;
|
~Loop() = default;
|
||||||
|
|
||||||
Loop *init() {
|
Loop *init() {
|
||||||
new (us_loop_ext((us_loop *) this)) LoopData;
|
new (us_loop_ext((us_loop_t *) this)) LoopData;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Todo: should take void ptr */
|
static Loop *create(void *hint) {
|
||||||
static Loop *create(bool defaultLoop) {
|
return ((Loop *) us_create_loop(hint, wakeupCb, preCb, postCb, sizeof(LoopData)))->init();
|
||||||
return ((Loop *) us_create_loop(defaultLoop, wakeupCb, preCb, postCb, sizeof(LoopData)))->init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -90,10 +89,10 @@ public:
|
|||||||
/* If we are given a native loop pointer we pass that to uSockets and let it deal with it */
|
/* If we are given a native loop pointer we pass that to uSockets and let it deal with it */
|
||||||
if (existingNativeLoop) {
|
if (existingNativeLoop) {
|
||||||
/* Todo: here we want to pass the pointer, not a boolean */
|
/* Todo: here we want to pass the pointer, not a boolean */
|
||||||
lazyLoop = create(true);
|
lazyLoop = create(existingNativeLoop);
|
||||||
/* We cannot register automatic free here, must be manually done */
|
/* We cannot register automatic free here, must be manually done */
|
||||||
} else {
|
} else {
|
||||||
lazyLoop = create(false);
|
lazyLoop = create(nullptr);
|
||||||
std::atexit([]() {
|
std::atexit([]() {
|
||||||
Loop::get()->free();
|
Loop::get()->free();
|
||||||
});
|
});
|
||||||
@@ -105,53 +104,53 @@ public:
|
|||||||
|
|
||||||
/* Freeing the default loop should be done once */
|
/* Freeing the default loop should be done once */
|
||||||
void free() {
|
void free() {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext((us_loop *) this);
|
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
|
||||||
loopData->~LoopData();
|
loopData->~LoopData();
|
||||||
/* uSockets will track whether this loop is owned by us or a borrowed alien loop */
|
/* uSockets will track whether this loop is owned by us or a borrowed alien loop */
|
||||||
us_loop_free((us_loop *) this);
|
us_loop_free((us_loop_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want to have multiple of these */
|
/* We want to have multiple of these */
|
||||||
void addPostHandler(fu2::unique_function<void(Loop *)> &&handler) {
|
void addPostHandler(fu2::unique_function<void(Loop *)> &&handler) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext((us_loop *) this);
|
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
|
||||||
|
|
||||||
loopData->postHandlers.emplace_back(std::move(handler));
|
loopData->postHandlers.emplace_back(std::move(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set postCb callback */
|
/* Set postCb callback */
|
||||||
void setPostHandler(fu2::unique_function<void(Loop *)> &&handler) {
|
void setPostHandler(fu2::unique_function<void(Loop *)> &&handler) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext((us_loop *) this);
|
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
|
||||||
|
|
||||||
loopData->postHandler = std::move(handler);
|
loopData->postHandler = std::move(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPreHandler(fu2::unique_function<void(Loop *)> &&handler) {
|
void setPreHandler(fu2::unique_function<void(Loop *)> &&handler) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext((us_loop *) this);
|
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
|
||||||
|
|
||||||
loopData->preHandler = std::move(handler);
|
loopData->preHandler = std::move(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Defer this callback on Loop's thread of execution */
|
/* Defer this callback on Loop's thread of execution */
|
||||||
void defer(fu2::unique_function<void()> &&cb) {
|
void defer(fu2::unique_function<void()> &&cb) {
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext((us_loop *) this);
|
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
|
||||||
|
|
||||||
//if (std::thread::get_id() == ) // todo: add fast path for same thread id
|
//if (std::thread::get_id() == ) // todo: add fast path for same thread id
|
||||||
loopData->deferMutex.lock();
|
loopData->deferMutex.lock();
|
||||||
loopData->deferQueues[loopData->currentDeferQueue].emplace_back(std::move(cb));
|
loopData->deferQueues[loopData->currentDeferQueue].emplace_back(std::move(cb));
|
||||||
loopData->deferMutex.unlock();
|
loopData->deferMutex.unlock();
|
||||||
|
|
||||||
us_wakeup_loop((us_loop *) this);
|
us_wakeup_loop((us_loop_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actively block and run this loop */
|
/* Actively block and run this loop */
|
||||||
void run() {
|
void run() {
|
||||||
us_loop_run((us_loop *) this);
|
us_loop_run((us_loop_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Passively integrate with the underlying default loop */
|
/* Passively integrate with the underlying default loop */
|
||||||
/* Used to seamlessly integrate with third parties such as Node.js */
|
/* Used to seamlessly integrate with third parties such as Node.js */
|
||||||
void integrate() {
|
void integrate() {
|
||||||
us_loop_integrate((us_loop *) this);
|
us_loop_integrate((us_loop_t *) this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -34,14 +34,14 @@ private:
|
|||||||
typedef AsyncSocket<SSL> Super;
|
typedef AsyncSocket<SSL> Super;
|
||||||
|
|
||||||
void *init(bool perMessageDeflate, bool slidingCompression, std::string &&backpressure) {
|
void *init(bool perMessageDeflate, bool slidingCompression, std::string &&backpressure) {
|
||||||
new (us_new_socket_ext(SSL, (us_new_socket_t *) this)) WebSocketData(perMessageDeflate, slidingCompression, std::move(backpressure));
|
new (us_socket_ext(SSL, (us_socket_t *) this)) WebSocketData(perMessageDeflate, slidingCompression, std::move(backpressure));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* Returns pointer to the per socket user data */
|
/* Returns pointer to the per socket user data */
|
||||||
void *getUserData() {
|
void *getUserData() {
|
||||||
WebSocketData *webSocketData = (WebSocketData *) us_new_socket_ext(SSL, (us_new_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 (webSocketData + 1);
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ public:
|
|||||||
/* Send websocket close frame, emit close event, send FIN if successful */
|
/* Send websocket close frame, emit close event, send FIN if successful */
|
||||||
void end(int code, std::string_view message = {}) {
|
void end(int code, std::string_view message = {}) {
|
||||||
/* Check if we already called this one */
|
/* Check if we already called this one */
|
||||||
WebSocketData *webSocketData = (WebSocketData *) us_new_socket_ext(SSL, (us_new_socket_t *) this);
|
WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this);
|
||||||
if (webSocketData->isShuttingDown) {
|
if (webSocketData->isShuttingDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -120,8 +120,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Emit close event */
|
/* Emit close event */
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
|
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
||||||
(us_new_socket_context_t *) us_new_socket_context(SSL, (us_new_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
if (webSocketContextData->closeHandler) {
|
if (webSocketContextData->closeHandler) {
|
||||||
webSocketContextData->closeHandler(this, code, message);
|
webSocketContextData->closeHandler(this, code, message);
|
||||||
@@ -133,8 +133,8 @@ public:
|
|||||||
|
|
||||||
/* Subscribe to a topic according to MQTT rules and syntax */
|
/* Subscribe to a topic according to MQTT rules and syntax */
|
||||||
void subscribe(std::string_view topic) {
|
void subscribe(std::string_view topic) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
|
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
||||||
(us_new_socket_context_t *) us_new_socket_context(SSL, (us_new_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Fix this up */
|
/* Fix this up */
|
||||||
@@ -145,8 +145,8 @@ public:
|
|||||||
|
|
||||||
/* Publish a message to a topic according to MQTT rules and syntax */
|
/* Publish a message to a topic according to MQTT rules and syntax */
|
||||||
void publish(std::string_view topic, std::string_view message) {
|
void publish(std::string_view topic, std::string_view message) {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
|
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL,
|
||||||
(us_new_socket_context_t *) us_new_socket_context(SSL, (us_new_socket_t *) this)
|
(us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* We frame the message right here and only pass raw bytes to the pub/subber */
|
/* We frame the message right here and only pass raw bytes to the pub/subber */
|
||||||
|
|||||||
+33
-33
@@ -32,17 +32,17 @@ struct WebSocketContext {
|
|||||||
private:
|
private:
|
||||||
WebSocketContext() = delete;
|
WebSocketContext() = delete;
|
||||||
|
|
||||||
us_new_socket_context_t *getSocketContext() {
|
us_socket_context_t *getSocketContext() {
|
||||||
return (us_new_socket_context_t *) this;
|
return (us_socket_context_t *) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketContextData<SSL> *getExt() {
|
WebSocketContextData<SSL> *getExt() {
|
||||||
return (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, (us_new_socket_context_t *) this);
|
return (WebSocketContextData<SSL> *) 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 */
|
||||||
static bool setCompressed(uWS::WebSocketState<isServer> *wState, void *s) {
|
static bool setCompressed(uWS::WebSocketState<isServer> *wState, void *s) {
|
||||||
WebSocketData *webSocketData = (WebSocketData *) us_new_socket_ext(SSL, (us_new_socket_t *) s);
|
WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
|
||||||
|
|
||||||
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
|
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
|
||||||
webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
|
webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
|
||||||
@@ -53,14 +53,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void forceClose(uWS::WebSocketState<isServer> *wState, void *s) {
|
static void forceClose(uWS::WebSocketState<isServer> *wState, void *s) {
|
||||||
us_new_socket_close(SSL, (us_new_socket_t *) s);
|
us_socket_close(SSL, (us_socket_t *) s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true on breakage */
|
/* Returns true on breakage */
|
||||||
static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, uWS::WebSocketState<isServer> *webSocketState, void *s) {
|
static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, uWS::WebSocketState<isServer> *webSocketState, void *s) {
|
||||||
/* WebSocketData and WebSocketContextData */
|
/* WebSocketData and WebSocketContextData */
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
|
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
WebSocketData *webSocketData = (WebSocketData *) us_new_socket_ext(SSL, (us_new_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? */
|
||||||
if (opCode < 3) {
|
if (opCode < 3) {
|
||||||
@@ -71,7 +71,7 @@ private:
|
|||||||
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
|
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
|
||||||
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
||||||
|
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(us_new_socket_context_loop(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s)));
|
LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
|
||||||
std::string_view inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength);
|
std::string_view inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength);
|
||||||
if (!inflatedFrame.length()) {
|
if (!inflatedFrame.length()) {
|
||||||
forceClose(webSocketState, s);
|
forceClose(webSocketState, s);
|
||||||
@@ -91,7 +91,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), (uWS::OpCode) opCode);
|
webSocketContextData->messageHandler((WebSocket<SSL, isServer> *) s, std::string_view(data, length), (uWS::OpCode) opCode);
|
||||||
if (us_new_socket_is_closed(SSL, (us_new_socket_t *) s) || webSocketData->isShuttingDown) {
|
if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,8 +114,8 @@ private:
|
|||||||
webSocketData->fragmentBuffer.append("....");
|
webSocketData->fragmentBuffer.append("....");
|
||||||
|
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(
|
LoopData *loopData = (LoopData *) us_loop_ext(
|
||||||
us_new_socket_context_loop(SSL,
|
us_socket_context_loop(SSL,
|
||||||
us_new_socket_context(SSL, (us_new_socket_t *) s)
|
us_socket_context(SSL, (us_socket_t *) s)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -144,7 +144,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), (uWS::OpCode) opCode);
|
webSocketContextData->messageHandler((WebSocket<SSL, isServer> *) s, std::string_view(data, length), (uWS::OpCode) opCode);
|
||||||
if (us_new_socket_is_closed(SSL, (us_new_socket_t *) s) || webSocketData->isShuttingDown) {
|
if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool refusePayloadLength(uint64_t length, uWS::WebSocketState<isServer> *wState, void *s) {
|
static bool refusePayloadLength(uint64_t length, uWS::WebSocketState<isServer> *wState, void *s) {
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL> *) 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;
|
||||||
@@ -224,13 +224,13 @@ private:
|
|||||||
* any backpressure from HTTP state kept. */
|
* any backpressure from HTTP state kept. */
|
||||||
|
|
||||||
/* Handle socket disconnections */
|
/* Handle socket disconnections */
|
||||||
us_new_socket_context_on_close(SSL, getSocketContext(), [](auto *s) {
|
us_socket_context_on_close(SSL, getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
/* For whatever reason, if we already have emitted close event, do not emit it again */
|
/* For whatever reason, if we already have emitted close event, do not emit it again */
|
||||||
WebSocketData *webSocketData = (WebSocketData *) (us_new_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_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL> *) 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, {});
|
webSocketContextData->closeHandler((WebSocket<SSL, true> *) s, 1006, {});
|
||||||
@@ -247,10 +247,10 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle WebSocket data streams */
|
/* Handle WebSocket data streams */
|
||||||
us_new_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
|
us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
|
||||||
|
|
||||||
/* We need the websocket data */
|
/* We need the websocket data */
|
||||||
WebSocketData *webSocketData = (WebSocketData *) (us_new_socket_ext(SSL, s));
|
WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
|
||||||
|
|
||||||
/* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
|
/* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
|
||||||
* We only care for the TCP FIN really, not emitting any message after closing is key */
|
* We only care for the TCP FIN really, not emitting any message after closing is key */
|
||||||
@@ -258,7 +258,7 @@ private:
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL> *) 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 */
|
||||||
@@ -286,15 +286,15 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
|
/* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
|
||||||
us_new_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
|
us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
/* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
|
/* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
|
||||||
if (us_new_socket_is_shut_down(SSL, (us_new_socket_t *) s)) {
|
if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
||||||
WebSocketData *webSocketData = (WebSocketData *)(us_new_socket_ext(SSL, s));
|
WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
|
||||||
|
|
||||||
/* We store old backpressure since it is unclear whether write drained anything */
|
/* We store old backpressure since it is unclear whether write drained anything */
|
||||||
int backpressure = asyncSocket->getBufferedAmount();
|
int backpressure = asyncSocket->getBufferedAmount();
|
||||||
@@ -304,7 +304,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) */
|
||||||
if (backpressure < asyncSocket->getBufferedAmount()) {
|
if (backpressure < asyncSocket->getBufferedAmount()) {
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
|
||||||
asyncSocket->timeout(webSocketContextData->idleTimeout);
|
asyncSocket->timeout(webSocketContextData->idleTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ private:
|
|||||||
}
|
}
|
||||||
} else if (backpressure > asyncSocket->getBufferedAmount()) {
|
} else if (backpressure > asyncSocket->getBufferedAmount()) {
|
||||||
/* Only call drain if we actually drained backpressure */
|
/* Only call drain if we actually drained backpressure */
|
||||||
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
|
auto *webSocketContextData = (WebSocketContextData<SSL> *) 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> *) s);
|
||||||
}
|
}
|
||||||
@@ -328,19 +328,19 @@ private:
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Handle FIN, HTTP does not support half-closed sockets, so simply close */
|
/* Handle FIN, HTTP does not support half-closed sockets, so simply close */
|
||||||
us_new_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
|
us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
/* If we get a fin, we just close I guess */
|
/* If we get a fin, we just close I guess */
|
||||||
us_new_socket_close(SSL, (us_new_socket_t *) s);
|
us_socket_close(SSL, (us_socket_t *) s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Handle socket timeouts, simply close them so to not confuse client with FIN */
|
/* Handle socket timeouts, simply close them so to not confuse client with FIN */
|
||||||
us_new_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
|
us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
/* Timeout is very simple; we just close it */
|
/* Timeout is very simple; we just close it */
|
||||||
us_new_socket_close(SSL, (us_new_socket_t *) s);
|
us_socket_close(SSL, (us_socket_t *) s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
@@ -349,22 +349,22 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, (us_new_socket_context_t *) this);
|
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
|
||||||
webSocketContextData->~WebSocketContextData();
|
webSocketContextData->~WebSocketContextData();
|
||||||
|
|
||||||
us_new_socket_context_free(SSL, (us_new_socket_context_t *) this);
|
us_socket_context_free(SSL, (us_socket_context_t *) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
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_new_socket_context_t *parentSocketContext) {
|
static WebSocketContext *create(Loop *loop, us_socket_context_t *parentSocketContext) {
|
||||||
WebSocketContext *webSocketContext = (WebSocketContext *) us_new_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL>));
|
WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL>));
|
||||||
if (!webSocketContext) {
|
if (!webSocketContext) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init socket context data */
|
/* Init socket context data */
|
||||||
new ((WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, (us_new_socket_context_t *)webSocketContext)) WebSocketContextData<SSL>;
|
new ((WebSocketContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL>;
|
||||||
return webSocketContext->init();
|
return webSocketContext->init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
Submodule uSockets updated: f1cae03ecd...1fa56f7f6f
Reference in New Issue
Block a user