Add a few more events

This commit is contained in:
Alex Hultman
2018-12-21 04:31:37 +01:00
parent 4a2cd93a22
commit 3fa0fbc5fa
7 changed files with 91 additions and 49 deletions
+24 -18
View File
@@ -1,29 +1,35 @@
#include "App.h" #include "App.h"
int main() { int main() {
/* ws->getUserData returns one of these */
struct PerSocketData {
};
/* Very simple WebSocket echo server */ /* Very simple WebSocket echo server */
uWS::App().ws<void>("/*", { uWS::App().ws<PerSocketData>("/*", {
/*.compression = */true, /* Settings */
/*.maxPayloadLength*/ .compression = true,
.maxPayloadLength = 16 * 1024,
/*.open = */[](auto *ws, auto *req) { /* Handlers */
.open = [](auto *ws, auto *req) {
}, },
/*.message = */[](auto *ws, std::string_view message, uWS::OpCode opCode) { .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
ws->send(message, opCode); ws->send(message, opCode);
},
.drain = [](auto *ws) {
/* Check getBufferedAmount here */
},
.ping = [](auto *ws) {
},
.pong = [](auto *ws) {
},
.close = [](auto *ws, int code, std::string_view message) {
} }
/*.drain = []() {
},
.ping = []() {
},
.pong = []() {
},
.close = []() {
}*/
}).listen(9001, [](auto *token) { }).listen(9001, [](auto *token) {
if (token) { if (token) {
std::cout << "Listening on port " << 9001 << std::endl; std::cout << "Listening on port " << 9001 << std::endl;
+29 -22
View File
@@ -6,7 +6,7 @@
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct PerSocketData { struct PerSocketData {
int hello;
}; };
/*const char *key_file_name; /*const char *key_file_name;
@@ -14,34 +14,41 @@ int main(int argc, char **argv) {
const char *passphrase; const char *passphrase;
const char *dh_params_file_name;*/ const char *dh_params_file_name;*/
uWS::SSLApp({ uWS::App(/*SSLApp({
"/home/alexhultman/key.pem", "/home/alexhultman/key.pem",
"/home/alexhultman/cert.pem", "/home/alexhultman/cert.pem",
"1234" "1234"
}).get("/hello", [](auto *res, auto *req) { }*/).get("/hello", [](auto *res, auto *req) {
res->end("Hello HTTP!"); res->end("Hello HTTP!");
}).ws<void>("/*", { }).ws<PerSocketData>("/*", {
/*.compression = */true, /* Settings */
/*.maxPayloadLength*/ .compression = true,
.maxPayloadLength = 16 * 1024,
/*.open = */[](auto *ws, auto *req) { /* Handlers */
.open = [](auto *ws, auto *req) {
std::cout << "WebSocket connected" << std::endl;
/* Access per socket data */
/*PerSocketData *perSocketData = */ws->getUserData();
/*perSocketData->hello = 13;*/
}, },
/*.message = */[](auto *ws, std::string_view message, uWS::OpCode opCode) { .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
ws->send(message, opCode); ws->send(message, opCode);
},
.drain = [](auto *ws) {
std::cout << "Drainage: " << ws->getBufferedAmount() << std::endl;
},
.ping = [](auto *ws) {
std::cout << "Ping" << std::endl;
},
.pong = [](auto *ws) {
std::cout << "Pong" << std::endl;
},
.close = [](auto *ws, int code, std::string_view message) {
std::cout << "WebSocket disconnected: " << code << "[" << message << "]" << std::endl;
/* Access per socket data */
//PerSocketData *perSocketData = ws->getUserData<PerSocketData>();
//std::cout << "OK per socket data: " << (perSocketData->hello == 13) << std::endl;
} }
/*.drain = []() {
},
.ping = []() {
},
.pong = []() {
},
.close = []() {
}*/
}).listen(9001, [](auto *token) { }).listen(9001, [](auto *token) {
if (token) { if (token) {
std::cout << "Listening on port " << 3000 << std::endl; std::cout << "Listening on port " << 3000 << std::endl;
+7 -2
View File
@@ -54,8 +54,13 @@ public:
struct WebSocketBehavior { struct WebSocketBehavior {
bool compression = false; bool compression = false;
int maxPayloadLength = 16 * 1024;
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> *)> ping = nullptr;
std::function<void(uWS::WebSocket<SSL, true> *)> pong = nullptr;
std::function<void(uWS::WebSocket<SSL, true> *, int, std::string_view)> close = nullptr;
}; };
template <class UserData> template <class UserData>
@@ -75,6 +80,8 @@ public:
/* Copy all handlers */ /* Copy all handlers */
webSocketContext->getExt()->messageHandler = behavior.message; webSocketContext->getExt()->messageHandler = behavior.message;
webSocketContext->getExt()->drainHandler = behavior.drain;
webSocketContext->getExt()->closeHandler = behavior.close;
return get(pattern, [webSocketContext, this, behavior](auto *res, auto *req) { return 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 */
@@ -125,8 +132,6 @@ public:
behavior.open(webSocket, req); behavior.open(webSocket, req);
} }
std::cout << "oh hey!" << std::endl;
} else { } else {
/* For now we do not support having HTTP and websocket routes on the same URL */ /* For now we do not support having HTTP and websocket routes on the same URL */
res->close(); res->close();
+7
View File
@@ -95,6 +95,13 @@ protected:
} }
} }
/* Returns the user space backpressure. */
int getBufferedAmount() {
AsyncSocketData<SSL> *asyncSocketData = (AsyncSocketData<SSL> *) getExt();
return asyncSocketData->buffer.size();
}
/* Write in three levels of prioritization: cork-buffer, syscall, socket-buffer. Always drain if possible. /* Write in three levels of prioritization: cork-buffer, syscall, socket-buffer. Always drain if possible.
* Returns pair of bytes written (anywhere) and wheter or not this call resulted in the polling for * Returns pair of bytes written (anywhere) and wheter or not this call resulted in the polling for
* writable (or we are in a state that implies polling for writable). */ * writable (or we are in a state that implies polling for writable). */
+11
View File
@@ -39,6 +39,17 @@ private:
} }
public: public:
/* Returns pointer to the per socket user data */
//template <typename K>
void *getUserData() {
WebSocketData *webSocketData = (WebSocketData *) static_dispatch(us_ssl_socket_ext, us_socket_ext)((SOCKET_TYPE *) this);
return nullptr;
}
/* See AsyncSocket */
using Super::getBufferedAmount;
/* Send or buffer a WebSocket frame, compressed or not. Returns false on increased user space backpressure. */ /* Send or buffer a WebSocket frame, compressed or not. Returns false on increased user space backpressure. */
bool send(std::string_view message, uWS::OpCode opCode = uWS::OpCode::BINARY, bool compress = false) { bool send(std::string_view message, uWS::OpCode opCode = uWS::OpCode::BINARY, bool compress = false) {
/* Transform the message to compressed domain if requested */ /* Transform the message to compressed domain if requested */
+10 -6
View File
@@ -47,7 +47,7 @@ private:
static bool setCompressed(uWS::WebSocketState<isServer> *wState, void *s) { static bool setCompressed(uWS::WebSocketState<isServer> *wState, void *s) {
//WebSocketData *webSocketData = (WebSocketData *) us_socket_ext((us_socket *) s); //WebSocketData *webSocketData = (WebSocketData *) us_socket_ext((us_socket *) s);
std::cout << "set compressed" << std::endl; //std::cout << "set compressed" << std::endl;
WebSocketData *webSocketData = (WebSocketData *) static_dispatch(us_ssl_socket_ext, us_socket_ext)((SOCKET_TYPE *) s); WebSocketData *webSocketData = (WebSocketData *) static_dispatch(us_ssl_socket_ext, us_socket_ext)((SOCKET_TYPE *) s);
@@ -264,14 +264,13 @@ private:
std::cout << "close!" << std::endl; std::cout << "close!" << std::endl;
return s; return s;
}); });
/* 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) {
//std::cout << "websocket data" << std::endl;
/* 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();
@@ -279,13 +278,14 @@ private:
/* We need the websocket data */ /* We need the websocket data */
WebSocketData *wsState = (WebSocketData *) (static_dispatch(us_ssl_socket_ext, us_socket_ext)(s)); WebSocketData *wsState = (WebSocketData *) (static_dispatch(us_ssl_socket_ext, us_socket_ext)(s));
// this parser requires almost no time -> 215k req/sec of 215k possible /* This parser has virtually no overhead */
uWS::WebSocketProtocol<isServer, WebSocketContext<SSL, isServer>>::consume(data, length, wsState, s); uWS::WebSocketProtocol<isServer, WebSocketContext<SSL, isServer>>::consume(data, length, wsState, s);
// todo: check for failures here just like for HTTP // todo: check for failures here just like for HTTP
webSocket->uncork(); webSocket->uncork();
// I guess we need to check drain here
// are we shutdown? // are we shutdown?
if (wsState->isShuttingDown) { if (wsState->isShuttingDown) {
webSocket->shutdown(); webSocket->shutdown();
@@ -306,6 +306,10 @@ private:
// check for failures and shutdown just like in data event // check for failures and shutdown just like in data event
webSocket->write(nullptr, 0); // drainage - also check for shutdown! webSocket->write(nullptr, 0); // drainage - also check for shutdown!
// call drain here
return s; return s;
}); });
+3 -1
View File
@@ -28,8 +28,10 @@ template <bool, bool> struct WebSocket;
template <bool SSL> template <bool SSL>
struct WebSocketContextData { struct WebSocketContextData {
/* The callbacks for this context */
std::function<void(WebSocket<SSL, true> *, std::string_view, uWS::OpCode)> messageHandler; std::function<void(WebSocket<SSL, true> *, std::string_view, uWS::OpCode)> messageHandler;
std::function<void(uWS::WebSocket<SSL, true> *)> drainHandler;
std::function<void(uWS::WebSocket<SSL, true> *, int, std::string_view)> closeHandler;
}; };
} }