From 549c97363c8b31f9a92c65590e1f10d7961baaa5 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Mon, 10 Sep 2018 22:47:41 +0200 Subject: [PATCH] Hook things up more --- 15.pro | 3 +- main.cpp | 4 +- src/new_design/HttpContext.h | 137 +++++++++++++++++++++++++++----- src/new_design/StaticDispatch.h | 24 ++++++ 4 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 src/new_design/StaticDispatch.h diff --git a/15.pro b/15.pro index b31baf4..93ae2be 100644 --- a/15.pro +++ b/15.pro @@ -27,7 +27,8 @@ HEADERS += \ src/new_design/HttpContext.h \ src/new_design/HttpContextData.h \ src/new_design/HttpResponseData.h \ - src/new_design/HttpResponse.h + src/new_design/HttpResponse.h \ + src/new_design/StaticDispatch.h INCLUDEPATH += uSockets/src src #QMAKE_CXXFLAGS += -fsanitize=address diff --git a/main.cpp b/main.cpp index 3897329..f3bf5da 100644 --- a/main.cpp +++ b/main.cpp @@ -72,7 +72,9 @@ int main(int argc, char **argv) { }); - httpContext->listen(); + httpContext->listen(nullptr, 3000, 0); + + loop.run(); httpContext->free(); diff --git a/src/new_design/HttpContext.h b/src/new_design/HttpContext.h index eaf283d..caa4606 100644 --- a/src/new_design/HttpContext.h +++ b/src/new_design/HttpContext.h @@ -23,38 +23,140 @@ namespace uWS { // would it be okay to depend on the context? -// we depend on libusockets -#include +// this basically should mean: libusockets wrapper +#include "StaticDispatch.h" template -struct HttpContext { +struct HttpContext : StaticDispatch { + using SOCKET_CONTEXT_TYPE = typename StaticDispatch::SOCKET_CONTEXT_TYPE; + using SOCKET_TYPE = typename StaticDispatch::SOCKET_TYPE; + using StaticDispatch::static_dispatch; + + static const int HTTP_IDLE_TIMEOUT_S = 10; private: HttpContext() = delete; // helper to get the socket context - us_socket_context *getSocketContext() { - return (us_socket_context *) this; + SOCKET_CONTEXT_TYPE *getSocketContext() { + return (SOCKET_CONTEXT_TYPE *) this; + } + + static SOCKET_CONTEXT_TYPE *getSocketContext(SOCKET_TYPE *s) { + return (SOCKET_CONTEXT_TYPE *) us_socket_get_context(s); } HttpContextData *getSocketContextData() { - return (HttpContextData *) us_socket_context_ext(getSocketContext()); + return (HttpContextData *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(getSocketContext()); + } + + static HttpContextData *getSocketContextData(SOCKET_TYPE *s) { + return (HttpContextData *) static_dispatch(us_ssl_socket_context_ext, us_socket_context_ext)(getSocketContext(s)); } public: + HttpContext *init() { + //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)(getSocketContext(), [](auto *s, int is_client) { + HttpContextData *httpContextData = getSocketContextData(s); + + std::cout << "Opened http connection" << std::endl; + + 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; +*/ + return s; + }); + + static_dispatch(us_ssl_socket_context_on_close, us_socket_context_on_close)(getSocketContext(), [](auto *s) { + HttpContextData *httpContextData = getSocketContextData(s); + + //((HTTP_SOCKET_DATA_TYPE *) static_dispatch(us_ssl_socket_ext, us_socket_ext)(s))->~HTTP_SOCKET_DATA_TYPE(); + + return s; + }); + + static_dispatch(us_ssl_socket_context_on_data, us_socket_context_on_data)(getSocketContext(), [](auto *s, char *data, int length) { + HttpContextData *httpContextData = getSocketContextData(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); + + + // here we should totally parse and route this all on our own, no involving the HttpResponse at all! + + std::cout << "Got data!" << std::endl; + + //Data *httpData = (Data *) static_dispatch(us_ssl_socket_ext, us_socket_ext)((SOCKET_TYPE *) this); + + // we can reach the HttpResponseData which holds the parser, so let's just run the data through it from here (no onData) bullshit in the httpsocket! + + // todo: this is where the HttpSocket binds together HttpParser and HttpRouter into one + /*httpData->httpParser.consumePostPadded(data, length, this, [&onHttpRequest](void *user, HttpRequest *httpRequest) { + onHttpRequest((HttpSocket *) user, httpRequest); + }, [httpData](void *user, std::string_view data) { + if (httpData->inStream) { + httpData->inStream(data); + } + }, [](void *user) { + std::cout << "INVALID HTTP!" << std::endl; + });*/ + + return s; + }); + + static_dispatch(us_ssl_socket_context_on_writable, us_socket_context_on_writable)(getSocketContext(), [](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); + + + // why? WE should emit this event via the socket data that we access! + ((HttpSocket *) s)->onWritable(); + + return s; + }); + + static_dispatch(us_ssl_socket_context_on_end, us_socket_context_on_end)(getSocketContext(), [](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)(getSocketContext(), [](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; + + }); + + return this; + } + static HttpContext *create(us_loop *loop) { - // todo: inplace initialize the data struct! + HttpContext *httpContext = (HttpContext *) us_create_socket_context(loop, sizeof(HttpContextData)); - // todo: actually register handlers on the socket context with the behavior of HTTP! (take from HttpApp.h) - - return (HttpContext *) us_create_socket_context(loop, sizeof(HttpContextData)); + return httpContext->init(); } void free() { - us_socket_context_free((us_socket_context *) this); + static_dispatch(us_ssl_socket_context_free, us_socket_context_free)(getSocketContext()); } void onGet(std::string_view pattern, std::function *)> handler) { @@ -65,17 +167,8 @@ public: data->handler = handler; } - void listen() { - // simulate routing and parsing a request - - HttpContextData *data = getSocketContextData(); - - // we need to pass an actual socket! not nullptr! - - // simulare - data->handler(nullptr); - - + void listen(const char *host, int port, int options) { + static_dispatch(us_ssl_socket_context_listen, us_socket_context_listen)(getSocketContext(), host, port, options, sizeof(HttpContextData)); } }; diff --git a/src/new_design/StaticDispatch.h b/src/new_design/StaticDispatch.h new file mode 100644 index 0000000..db889f2 --- /dev/null +++ b/src/new_design/StaticDispatch.h @@ -0,0 +1,24 @@ +#ifndef STATICDISPATCH_H +#define STATICDISPATCH_H + +// this headers is basically a statically dispatched libusockets wrapper base + +#include +#include + +template +struct StaticDispatch { + 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; +}; + +#endif // STATICDISPATCH_H