Implement idleTimeout
This commit is contained in:
+4
-4
@@ -16,7 +16,7 @@ int main(int argc, char **argv) {
|
|||||||
.key_file_name = "/home/alexhultman/key.pem",
|
.key_file_name = "/home/alexhultman/key.pem",
|
||||||
.cert_file_name = "/home/alexhultman/cert.pem",
|
.cert_file_name = "/home/alexhultman/cert.pem",
|
||||||
.passphrase = "1234"
|
.passphrase = "1234"
|
||||||
}).post("/exit", [](auto *res, auto *req) {
|
}).get("/exit", [](auto *res, auto *req) {
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
res->end("Server already closed down!");
|
res->end("Server already closed down!");
|
||||||
@@ -32,7 +32,7 @@ int main(int argc, char **argv) {
|
|||||||
/* Settings */
|
/* Settings */
|
||||||
.compression = uWS::DEDICATED_COMPRESSOR,
|
.compression = uWS::DEDICATED_COMPRESSOR,
|
||||||
.maxPayloadLength = 16 * 1024 * 1024,
|
.maxPayloadLength = 16 * 1024 * 1024,
|
||||||
/* autoPingInterval */
|
.idleTimeout = 10,
|
||||||
/* Handlers */
|
/* Handlers */
|
||||||
.open = [](auto *ws, auto *req) {
|
.open = [](auto *ws, auto *req) {
|
||||||
std::cout << "WebSocket connected" << std::endl;
|
std::cout << "WebSocket connected" << std::endl;
|
||||||
@@ -60,12 +60,12 @@ int main(int argc, char **argv) {
|
|||||||
PerSocketData *perSocketData = (PerSocketData *) ws->getUserData();
|
PerSocketData *perSocketData = (PerSocketData *) ws->getUserData();
|
||||||
std::cout << "OK per socket data: " << (perSocketData->hello == 13) << std::endl;
|
std::cout << "OK per socket data: " << (perSocketData->hello == 13) << std::endl;
|
||||||
}
|
}
|
||||||
})/*.listen(9001, [](auto *token) {
|
}).listen(9001, [](auto *token) {
|
||||||
::token = token;
|
::token = token;
|
||||||
if (token) {
|
if (token) {
|
||||||
std::cout << "Listening on port " << 3000 << std::endl;
|
std::cout << "Listening on port " << 3000 << std::endl;
|
||||||
}
|
}
|
||||||
})*/.run();
|
}).run();
|
||||||
|
|
||||||
|
|
||||||
std::cout << "Everything fine, falling through" << std::endl;
|
std::cout << "Everything fine, falling through" << std::endl;
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ public:
|
|||||||
struct WebSocketBehavior {
|
struct WebSocketBehavior {
|
||||||
CompressOptions compression = DISABLED;
|
CompressOptions compression = DISABLED;
|
||||||
int maxPayloadLength = 16 * 1024;
|
int maxPayloadLength = 16 * 1024;
|
||||||
|
int idleTimeout = 120;
|
||||||
std::function<void(uWS::WebSocket<SSL, true> *, HttpRequest *)> open = nullptr;
|
std::function<void(uWS::WebSocket<SSL, true> *, HttpRequest *)> open = nullptr;
|
||||||
std::function<void(uWS::WebSocket<SSL, true> *, std::string_view, uWS::OpCode)> message = nullptr;
|
std::function<void(uWS::WebSocket<SSL, true> *, std::string_view, uWS::OpCode)> message = nullptr;
|
||||||
std::function<void(uWS::WebSocket<SSL, true> *)> drain = nullptr;
|
std::function<void(uWS::WebSocket<SSL, true> *)> drain = nullptr;
|
||||||
@@ -131,6 +132,7 @@ public:
|
|||||||
|
|
||||||
/* Copy settings */
|
/* Copy settings */
|
||||||
webSocketContext->getExt()->maxPayloadLength = behavior.maxPayloadLength;
|
webSocketContext->getExt()->maxPayloadLength = behavior.maxPayloadLength;
|
||||||
|
webSocketContext->getExt()->idleTimeout = behavior.idleTimeout;
|
||||||
|
|
||||||
return std::move(get(pattern, [webSocketContext, this, behavior](auto *res, auto *req) {
|
return std::move(get(pattern, [webSocketContext, this, behavior](auto *res, auto *req) {
|
||||||
/* If we have this header set, it's a websocket */
|
/* If we have this header set, it's a websocket */
|
||||||
@@ -182,7 +184,8 @@ public:
|
|||||||
/* Add mark, we don't want to end anything */
|
/* Add mark, we don't want to end anything */
|
||||||
res->writeHeader("WebSocket-Server", "uWebSockets")->end();
|
res->writeHeader("WebSocket-Server", "uWebSockets")->end();
|
||||||
|
|
||||||
/* todo: What about HttpResponseData here? */
|
/* bug: memory leak? What about HttpResponseData here? I'm thinking not delete it but destruct it? */
|
||||||
|
/* Esp. if the functions hold dynamic memory like something big */
|
||||||
|
|
||||||
/* 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> *) StaticDispatch<SSL>::static_dispatch(us_ssl_socket_context_adopt_socket, us_socket_context_adopt_socket)(
|
WebSocket<SSL, true> *webSocket = (WebSocket<SSL, true> *) StaticDispatch<SSL>::static_dispatch(us_ssl_socket_context_adopt_socket, us_socket_context_adopt_socket)(
|
||||||
@@ -195,11 +198,14 @@ public:
|
|||||||
webSocket->init(perMessageDeflate, slidingDeflateWindow)
|
webSocket->init(perMessageDeflate, slidingDeflateWindow)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Emit open event */
|
/* Emit open event and start the timeout */
|
||||||
if (behavior.open) {
|
if (behavior.open) {
|
||||||
|
static_dispatch(us_ssl_socket_timeout, us_socket_timeout)((SOCKET_TYPE *) webSocket, behavior.idleTimeout);
|
||||||
behavior.open(webSocket, req);
|
behavior.open(webSocket, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bug: What happens with corking? */
|
||||||
|
|
||||||
/* We do not need to check for any close or shutdown here as we immediately return from get handler */
|
/* We do not need to check for any close or shutdown here as we immediately return from get handler */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ struct alignas(16) HttpContextData {
|
|||||||
private:
|
private:
|
||||||
std::vector<fu2::unique_function<void(HttpResponse<SSL> *, int)>> filterHandlers;
|
std::vector<fu2::unique_function<void(HttpResponse<SSL> *, int)>> filterHandlers;
|
||||||
|
|
||||||
/*HttpContextData(const HttpContextData&) = delete;
|
|
||||||
HttpContextData() {
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
struct RouterData {
|
struct RouterData {
|
||||||
HttpResponse<SSL> *httpResponse;
|
HttpResponse<SSL> *httpResponse;
|
||||||
HttpRequest *httpRequest;
|
HttpRequest *httpRequest;
|
||||||
|
|||||||
+19
-13
@@ -233,6 +233,8 @@ private:
|
|||||||
|
|
||||||
WebSocketContext<SSL, isServer> *init() {
|
WebSocketContext<SSL, isServer> *init() {
|
||||||
/* Open is never called, we only adopt sockets */
|
/* Open is never called, we only adopt sockets */
|
||||||
|
/* Always assume timeout is disabled when we are adopted.
|
||||||
|
* HTTP requests should disable timeout anyways */
|
||||||
|
|
||||||
/* Handle socket disconnections */
|
/* Handle socket disconnections */
|
||||||
static_dispatch(us_ssl_socket_context_on_close, us_socket_context_on_close)(getSocketContext(), [](auto *s) {
|
static_dispatch(us_ssl_socket_context_on_close, us_socket_context_on_close)(getSocketContext(), [](auto *s) {
|
||||||
@@ -247,6 +249,19 @@ private:
|
|||||||
|
|
||||||
/* Handle WebSocket data streams */
|
/* Handle WebSocket data streams */
|
||||||
static_dispatch(us_ssl_socket_context_on_data, us_socket_context_on_data)(getSocketContext(), [](auto *s, char *data, int length) {
|
static_dispatch(us_ssl_socket_context_on_data, us_socket_context_on_data)(getSocketContext(), [](auto *s, char *data, int length) {
|
||||||
|
|
||||||
|
/* Everytime we get data, we reset the timeout to our idleTimeout, that's the only timer we have */
|
||||||
|
|
||||||
|
/* If not in websocket shutdown state, for every */
|
||||||
|
|
||||||
|
// hur mycket sabbar denna?
|
||||||
|
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(
|
||||||
|
static_dispatch(us_ssl_socket_get_context, us_socket_get_context)((SOCKET_TYPE *)s)
|
||||||
|
);
|
||||||
|
|
||||||
|
static_dispatch(us_ssl_socket_timeout, us_socket_timeout)((SOCKET_TYPE *) s, webSocketContextData->idleTimeout);
|
||||||
|
|
||||||
|
|
||||||
/* We always cork on data */
|
/* We always cork on data */
|
||||||
AsyncSocket<SSL> *webSocket = (AsyncSocket<SSL> *) s;
|
AsyncSocket<SSL> *webSocket = (AsyncSocket<SSL> *) s;
|
||||||
webSocket->cork();
|
webSocket->cork();
|
||||||
@@ -315,13 +330,8 @@ 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 */
|
||||||
static_dispatch(us_ssl_socket_context_on_end, us_socket_context_on_end)(getSocketContext(), [](auto *s) {
|
static_dispatch(us_ssl_socket_context_on_end, us_socket_context_on_end)(getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
// just like http, websocket does not support half-open sockets so just close here
|
/* If we get a fin, we just close I guess */
|
||||||
|
static_dispatch(us_ssl_socket_close, us_socket_close)((SOCKET_TYPE *) s);
|
||||||
std::cout << "websopcket fin" << std::endl;
|
|
||||||
|
|
||||||
/* We do not care for half closed sockets */
|
|
||||||
//AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
|
||||||
//return asyncSocket->close();
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
@@ -329,12 +339,8 @@ 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 */
|
||||||
static_dispatch(us_ssl_socket_context_on_timeout, us_socket_context_on_timeout)(getSocketContext(), [](auto *s) {
|
static_dispatch(us_ssl_socket_context_on_timeout, us_socket_context_on_timeout)(getSocketContext(), [](auto *s) {
|
||||||
|
|
||||||
std::cout << "websocket timeout" << std::endl;
|
/* Timeout is very simple; we just close it */
|
||||||
|
static_dispatch(us_ssl_socket_close, us_socket_close)((SOCKET_TYPE *) s);
|
||||||
/* Force close rather than gracefully shutdown and risk confusing the client with a complete download */
|
|
||||||
//AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
|
|
||||||
//return asyncSocket->close();
|
|
||||||
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ namespace uWS {
|
|||||||
|
|
||||||
template <bool, bool> struct WebSocket;
|
template <bool, bool> struct WebSocket;
|
||||||
|
|
||||||
|
/* todo: this looks identical to WebSocketBehavior, why not just std::move that entire thing in? */
|
||||||
|
|
||||||
template <bool SSL>
|
template <bool SSL>
|
||||||
struct WebSocketContextData {
|
struct WebSocketContextData {
|
||||||
/* The callbacks for this context */
|
/* The callbacks for this context */
|
||||||
@@ -36,6 +38,7 @@ struct WebSocketContextData {
|
|||||||
|
|
||||||
/* Settings for this context */
|
/* Settings for this context */
|
||||||
size_t maxPayloadLength = 0;
|
size_t maxPayloadLength = 0;
|
||||||
|
int idleTimeout = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user