diff --git a/15.pro b/15.pro index 93ae2be..67a612a 100644 --- a/15.pro +++ b/15.pro @@ -15,15 +15,12 @@ SOURCES += \ HEADERS += \ src/new_design/HttpRouter.h \ src/Loop.h \ - src/App.h \ src/http/HttpSocket.h \ src/new_design/HttpParser.h \ src/websocket/libwshandshake.hpp \ src/websocket/WebSocketProtocol.h \ src/websocket/WebSocket.h \ - src/Socket.h \ src/websocket/WebSocketApp.h \ - src/http/HttpApp.h \ src/new_design/HttpContext.h \ src/new_design/HttpContextData.h \ src/new_design/HttpResponseData.h \ diff --git a/main.cpp b/main.cpp index b08eccf..e553dfb 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,6 @@ -#include "App.h" - #include #include +#include std::string buffer; int connections = 0; @@ -16,6 +15,7 @@ void respond(T *s) { #define USE_SSL #include +#include std::string_view getFile(std::string_view file) { static std::map cache; @@ -54,7 +54,7 @@ int main(int argc, char **argv) { uWS::Loop loop; - HttpContext *httpContext = HttpContext::create(loop.loop); + uWS::HttpContext *httpContext = uWS::HttpContext::create(loop.loop); // req, res? httpContext->onGet("/", [](auto *res, auto *req) { // maybe use the terminology of HttpRequest for both? @@ -74,6 +74,12 @@ int main(int argc, char **argv) { }); + httpContext->onGet("/yolo", [](auto *res, auto *req) { + std::cout << "URL (/yolo route): <" << req->getUrl() << ">" << std::endl; + std::cout << "Query: <" << req->getQuery() << ">" << std::endl; + std::cout << "User-Agent: <" << req->getHeader("user-agent") << ">" << std::endl; + }); + httpContext->listen(nullptr, 3000, 0); loop.run(); @@ -86,7 +92,7 @@ int main(int argc, char **argv) { // 50 mb for huge - buffer.resize(52428800); + /* buffer.resize(52428800); //uWS::init(); //uWS::Loop loop(); @@ -119,13 +125,13 @@ int main(int argc, char **argv) { std::cout << "WebSocket connected to /wsApi" << std::endl; - }).onMessage([](auto *ws, auto message/*, auto opCode*/) { + }).onMessage([](auto *ws, auto message) { std::cout << "WebSocket data: " << message << std::endl; //ws->send(message, opCode); - }).onClose([](/*auto *ws, int code, auto message*/) { + }).onClose([]() { //std::cout << "WebSocket disconnected from /wsApi" << std::endl; diff --git a/src/App.h b/src/App.h deleted file mode 100644 index 8cd0cb7..0000000 --- a/src/App.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef CONTEXT_H -#define CONTEXT_H - -#include "libusockets.h" -#include "websocket/WebSocketApp.h" -#include "Loop.h" -#include - -namespace uWS { - -class SSLOptions { -public: - us_ssl_socket_context_options options = {}; - - SSLOptions() { - - } - - SSLOptions &keyFileName(std::string fileName) { - options.key_file_name = fileName.c_str(); - return *this; - } - - SSLOptions &certFileName(std::string fileName) { - options.cert_file_name = fileName.c_str(); - return *this; - } - - SSLOptions &passphrase(std::string passphrase) { - options.passphrase = passphrase.c_str(); - return *this; - } -}; - -class App : public WebSocketApp { - -public: - App() : WebSocketApp(us_create_socket_context(defaultLoop.loop, sizeof(Data))) { - - } -}; - -class SSLApp : public WebSocketApp { - -public: - SSLApp(SSLOptions &sslOptions) : WebSocketApp(us_create_ssl_socket_context(defaultLoop.loop, sizeof(Data), sslOptions.options)) { - - } -}; - -} - -#endif // CONTEXT_H diff --git a/src/Socket.h b/src/Socket.h deleted file mode 100644 index 03b4eba..0000000 --- a/src/Socket.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef SOCKET_H -#define SOCKET_H - -#include "libusockets.h" -#include - -template -struct Socket { - - template - static constexpr typename std::conditional::type *static_dispatch(A *a, B *b) { - if constexpr(SSL) { - return a; - } else { - return b; - } - } - - typedef typename std::conditional::type SOCKET_TYPE; - typedef typename std::conditional::type SOCKET_CONTEXT_TYPE; - - - void *getSocketContextExt() { - SOCKET_CONTEXT_TYPE *socketContext = static_dispatch(us_ssl_socket_get_context, us_socket_get_context)((SOCKET_TYPE *) this); - - return static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(socketContext); - } - -}; - -#endif // SOCKET_H diff --git a/src/http/HttpApp.h b/src/http/HttpApp.h deleted file mode 100644 index 79bea78..0000000 --- a/src/http/HttpApp.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef HTTPAPP_H -#define HTTPAPP_H - -// todo: move all this logic to HttpContext - -#include -#include "Loop.h" -#include "HttpSocket.h" -#include "../new_design/HttpRouter.h" -#include "websocket/libwshandshake.hpp" -#include "websocket/WebSocket.h" - -template -class HttpApp { - -protected: - - static const unsigned int HTTP_IDLE_TIMEOUT_S = 10; - - template - static constexpr typename std::conditional::type *static_dispatch(A *a, B *b) { - if constexpr(SSL) { - return a; - } else { - return b; - } - } - - typedef typename std::conditional::type SOCKET_TYPE; - typedef typename std::conditional::type SOCKET_CONTEXT_TYPE; - typedef typename HttpSocket::Data HTTP_SOCKET_DATA_TYPE; - - // todo_ rename to HttpContextData - struct Data { - Data() { - - // default http handler is a router - onHttpRequest = [this](auto *s, HttpRequest *req) { - UserData user = {s, req}; - r.route("GET", 3, req->getUrl().data(), req->getUrl().length(), &user); - }; - - } - - struct UserData { - HttpSocket *httpSocket; - HttpRequest *httpRequest; - }; - - HttpRouter r; - - std::function *)> onHttpConnection; - std::function *)> onHttpDisconnection; - std::function *, HttpRequest *)> onHttpRequest; - } *data; - - // server protocols - SOCKET_CONTEXT_TYPE *httpServerContext; - - HttpApp(SOCKET_CONTEXT_TYPE *httpServerContext) : httpServerContext(httpServerContext) { - new (data = (Data *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(httpServerContext)) Data(); - - static_dispatch(us_ssl_socket_context_on_open, us_socket_context_on_open)(httpServerContext, [](auto *s, int is_client) { - Data *appData = (Data *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(static_dispatch(us_ssl_socket_get_context, us_socket_get_context)(s)); - - static_dispatch(us_ssl_socket_timeout, us_socket_timeout)(s, HTTP_IDLE_TIMEOUT_S); - - new (static_dispatch(us_ssl_socket_ext, us_socket_ext)(s)) HTTP_SOCKET_DATA_TYPE; - - if (appData->onHttpConnection) { - appData->onHttpConnection((HttpSocket *) s); - } - - return s; - }); - - static_dispatch(us_ssl_socket_context_on_close, us_socket_context_on_close)(httpServerContext, [](auto *s) { - Data *appData = (Data *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(static_dispatch(us_ssl_socket_get_context, us_socket_get_context)(s)); - - ((HTTP_SOCKET_DATA_TYPE *) static_dispatch(us_ssl_socket_ext, us_socket_ext)(s))->~HTTP_SOCKET_DATA_TYPE(); - - if (appData->onHttpDisconnection) { - appData->onHttpDisconnection((HttpSocket *) s); - } - - return s; - }); - - static_dispatch(us_ssl_socket_context_on_data, us_socket_context_on_data)(httpServerContext, [](auto *s, char *data, int length) { - Data *appData = (Data *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(static_dispatch(us_ssl_socket_get_context, us_socket_get_context)(s)); - - // warning: should NOT reset timer on any data, ONLY reset data on full HTTP requests! - // warning: if we are in shutdown state, resetting the timer is a security issue! - static_dispatch(us_ssl_socket_timeout, us_socket_timeout)(s, HTTP_IDLE_TIMEOUT_S); - - // onHttpRequest should probably be hard-coded to HttpRouter - ((HttpSocket *) s)->onData(data, length, appData->onHttpRequest); - - // compared to routing directly - //typename Data::UserData user = {(HttpSocket *) s, nullptr}; - //appData->r.route("GET", 3, "/", 1, &user); - - return s; - }); - - static_dispatch(us_ssl_socket_context_on_writable, us_socket_context_on_writable)(httpServerContext, [](auto *s) { - - // what if the client - - // I think it's fair to never mind this one -> if we keep writing data after shutting down then that's an issue for us - static_dispatch(us_ssl_socket_timeout, us_socket_timeout)(s, HTTP_IDLE_TIMEOUT_S); - - ((HttpSocket *) s)->onWritable(); - - return s; - }); - - static_dispatch(us_ssl_socket_context_on_end, us_socket_context_on_end)(httpServerContext, [](auto *s) { - std::cout << "Socket was half-closed!" << std::endl; - - return s; - }); - - static_dispatch(us_ssl_socket_context_on_timeout, us_socket_context_on_timeout)(httpServerContext, [](auto *s) { - - if (static_dispatch(us_ssl_socket_is_shut_down, us_socket_is_shut_down)(s)) { - std::cout << "Forcefully closing socket since shutdown was not answered in time" << std::endl; - static_dispatch(us_ssl_socket_close, us_socket_close)(s); - } else { - std::cout << "Shutting down socket now" << std::endl; - static_dispatch(us_ssl_socket_timeout, us_socket_timeout)(s, HTTP_IDLE_TIMEOUT_S); - static_dispatch(us_ssl_socket_shutdown, us_socket_shutdown)(s); - } - - return s; - - }); - } - -public: - - // for server - void listen(const char *host, int port, int options) { - static_dispatch(us_ssl_socket_context_listen, us_socket_context_listen)(httpServerContext, host, port, options, sizeof(typename HttpSocket::Data)); - } - - HttpApp &onPost(std::string pattern, std::function *, HttpRequest *, std::vector *)> handler) { - data->r.add("POST", pattern.c_str(), [handler](typename Data::UserData *user, auto *args) { - handler(user->httpSocket, user->httpRequest, args); - }); - - return *this; - } - - CHILD &onGet(std::string pattern, std::function *, HttpRequest *, std::vector *)> handler) { - data->r.add("GET", pattern.c_str(), [handler](typename Data::UserData *user, auto *args) { - handler(user->httpSocket, user->httpRequest, args); - }); - - return *(CHILD *) this; - } - - // why even bother with these? - HttpApp &onHttpConnection(std::function *)> handler) { - data->onHttpConnection = handler; - - return *this; - } - - HttpApp &onHttpDisconnection(std::function *)> handler) { - data->onHttpDisconnection = handler; - - return *this; - } - - ~HttpApp() { - } -}; - -#endif // HTTPAPP_H diff --git a/src/http/HttpSocket.h b/src/http/HttpSocket.h index c42e5fe..29fdd30 100644 --- a/src/http/HttpSocket.h +++ b/src/http/HttpSocket.h @@ -1,4 +1,4 @@ -#ifndef HTTP_H +#ifdef HTTP_H #define HTTP_H #include "Socket.h" @@ -39,7 +39,7 @@ struct HttpSocket : Socket { // httpheaders should only have 1 stream in and 1 stream out, but we can have helper wrappers struct Data { - HttpParser httpParser; + uWS::HttpParser httpParser; std::function inStream; @@ -144,7 +144,7 @@ struct HttpSocket : Socket { static_dispatch(us_ssl_socket_write, us_socket_write)((SOCKET_TYPE *) this, chunk.data(), chunk.length(), 0); } - void onData(char *data, int length, std::function *, HttpRequest *)> &onHttpRequest) { + void onData(char *data, int length, std::function *, uWS::HttpRequest *)> &onHttpRequest) { Data *httpData = (Data *) static_dispatch(us_ssl_socket_ext, us_socket_ext)((SOCKET_TYPE *) this); // todo: this is where the HttpSocket binds together HttpParser and HttpRouter into one diff --git a/src/new_design/HttpContext.h b/src/new_design/HttpContext.h index 835820a..fa133c8 100644 --- a/src/new_design/HttpContext.h +++ b/src/new_design/HttpContext.h @@ -1,31 +1,16 @@ #ifndef HTTPCONTEXT_H #define HTTPCONTEXT_H -// a more Cish implementaion +#include "Loop.h" +#include "HttpContextData.h" +#include "HttpResponseData.h" +#include "StaticDispatch.h" #include #include -// we depend on loop I guess -// yes, the loop does not depend on us -#include "Loop.h" - -// we of course depend on our own data type -#include "HttpContextData.h" -#include "HttpResponseData.h" - -// we should opaqeuly depend on HttpResponse namespace uWS { - template - struct HttpResponse; -} - -// we parse everything only in the context? - -// would it be okay to depend on the context? - -// this basically should mean: libusockets wrapper -#include "StaticDispatch.h" +template struct HttpResponse; template struct HttpContext : StaticDispatch { @@ -85,14 +70,16 @@ public: HttpContextData *httpContextData = getSocketContextData(s); HttpResponseData *httpResponseData = (HttpResponseData *) static_dispatch(us_ssl_socket_ext, us_socket_ext)(s); - httpResponseData->consumePostPadded(data, length, s, [httpContextData](void *s, HttpRequest *httpRequest) { + httpResponseData->consumePostPadded(data, length, s, [httpContextData](void *s, uWS::HttpRequest *httpRequest) { // warning: if we are in shutdown state, resetting the timer is a security issue! static_dispatch(us_ssl_socket_timeout, us_socket_timeout)((SOCKET_TYPE *) s, HTTP_IDLE_TIMEOUT_S); - // todo: route this according to our router - - httpContextData->handler((uWS::HttpResponse *) s, httpRequest); + // route it! + typename uWS::HttpContextData::UserData userData = { + (HttpResponse *) s, httpRequest + }; + httpContextData->router.route("get", 3, httpRequest->getUrl().data(), httpRequest->getUrl().length(), &userData); }, [httpResponseData](void *user, std::string_view data) { if (httpResponseData->readHandler) { @@ -116,7 +103,7 @@ public: // why? WE should emit this event via the socket data that we access! - ((HttpSocket *) s)->onWritable(); + //((HttpSocket *) s)->onWritable(); return s; }); @@ -158,12 +145,15 @@ public: static_dispatch(us_ssl_socket_context_free, us_socket_context_free)(getSocketContext()); } - void onGet(std::string_view pattern, std::function *, HttpRequest *)> handler) { + void onGet(std::string pattern, std::function *, uWS::HttpRequest *)> handler) { HttpContextData *data = getSocketContextData(); // add things to the router - data->handler = handler; + data->router.add("get", pattern.c_str(), [handler](typename HttpContextData::UserData *user, auto *args) { + handler(user->httpResponse, user->httpRequest); + }); + } void listen(const char *host, int port, int options) { @@ -172,4 +162,6 @@ public: }; +} + #endif // HTTPCONTEXT_H diff --git a/src/new_design/HttpContextData.h b/src/new_design/HttpContextData.h index 8b05c22..92fa650 100644 --- a/src/new_design/HttpContextData.h +++ b/src/new_design/HttpContextData.h @@ -1,17 +1,13 @@ #ifndef HTTPCONTEXTDATA_H #define HTTPCONTEXTDATA_H -// we depend on these -#include "HttpParser.h" #include "HttpRouter.h" #include namespace uWS { -template -struct HttpResponse; -} - +template struct HttpResponse; +struct HttpRequest; template struct HttpContextData { @@ -20,15 +16,15 @@ private: public: - struct HttpRouterUserData { - + struct UserData { + HttpResponse *httpResponse; + HttpRequest *httpRequest; }; - HttpRouter httpRouter; - - // placeholder handler for response - std::function *, HttpRequest *)> handler; + HttpRouter router; }; +} + #endif // HTTPCONTEXTDATA_H diff --git a/src/new_design/HttpParser.h b/src/new_design/HttpParser.h index d80650e..bed7f5a 100644 --- a/src/new_design/HttpParser.h +++ b/src/new_design/HttpParser.h @@ -5,6 +5,8 @@ #include #include +namespace uWS { + class HttpRequest { friend class HttpParser; @@ -202,4 +204,6 @@ public: } }; +} + #endif // HTTPPARSER_H diff --git a/src/new_design/HttpResponseData.h b/src/new_design/HttpResponseData.h index f65baf5..6f1f78e 100644 --- a/src/new_design/HttpResponseData.h +++ b/src/new_design/HttpResponseData.h @@ -6,6 +6,8 @@ #include "HttpParser.h" #include +namespace uWS { + template struct HttpResponseData : HttpParser { @@ -13,4 +15,6 @@ struct HttpResponseData : HttpParser { }; +} + #endif // HTTPRESPONSEDATA_H diff --git a/src/new_design/HttpRouter.h b/src/new_design/HttpRouter.h index 0eaa764..a50e547 100644 --- a/src/new_design/HttpRouter.h +++ b/src/new_design/HttpRouter.h @@ -10,6 +10,8 @@ #include #include +namespace uWS { + template class HttpRouter { private: @@ -168,4 +170,6 @@ public: } }; +} + #endif // HTTPROUTER_HPP diff --git a/src/websocket/WebSocketApp.h b/src/websocket/WebSocketApp.h index 261974a..4292a4e 100644 --- a/src/websocket/WebSocketApp.h +++ b/src/websocket/WebSocketApp.h @@ -1,4 +1,4 @@ -#ifndef WEBSOCKETAPP_H +#ifdef WEBSOCKETAPP_H #define WEBSOCKETAPP_H #include "http/HttpApp.h"