diff --git a/15.pro b/15.pro index 3f8dca8..a894ce8 100644 --- a/15.pro +++ b/15.pro @@ -18,5 +18,5 @@ HEADERS += \ src/Http.h INCLUDEPATH += uSockets/src src -QMAKE_CXXFLAGS += -fsanitize=address -LIBS += -lasan +#QMAKE_CXXFLAGS += -fsanitize=address +#LIBS += -lasan diff --git a/main.cpp b/main.cpp index b642a79..30fc6ce 100644 --- a/main.cpp +++ b/main.cpp @@ -1,21 +1,45 @@ // uWS.h #include "Hub.h" #include +#include + +//char largeBuf[] = "HTTP/1.1 200 OK\r\nContent-Length: 512\r\n\r\n"; +//int largeHttpBufSize = sizeof(largeBuf) + 512 - 1; + +char largeBuf[] = "HTTP/1.1 200 OK\r\nContent-Length: 52428800\r\n\r\n"; +int largeHttpBufSize = sizeof(largeBuf) + 52428800 - 1; + +char *largeHttpBuf; int main() { + std::cout << "HttpSocket size: " << sizeof(HttpSocket) << std::endl; + + largeHttpBuf = (char *) malloc(largeHttpBufSize); + memcpy(largeHttpBuf, largeBuf, sizeof(largeBuf) - 1); + Hub h; + h.onHttpConnection([](HttpSocket *s) { + //std::cout << "HTTP connection" << std::endl; + }); + // req = ?, res = HttpSocket - h.onHttpRequest([](auto req, auto res, char *data, unsigned int length) { + h.onHttpRequest([](HttpSocket *s, auto req, char *data, unsigned int length) { - std::cout << "Got data: " << std::string(data, length) << std::endl; + //std::cout << "Got data: " << std::string(data, length) << std::endl; - // res.writeStatus(); - // res.writeHeader(); - // res.write(); + // s->writeStatus(); + // s->writeHeader(); - res->write(); + // if url == / then stream index.htm + s->stream(largeHttpBufSize, [](int offset) { + return std::make_pair(largeHttpBuf + offset, largeHttpBufSize - offset); + }); + }); + + h.onHttpDisconnection([](HttpSocket *s) { + //std::cout << "HTTP disconnection" << std::endl; }); h.listen(nullptr, 3000, 0); diff --git a/src/Http.cpp b/src/Http.cpp index daa4b15..82cbd0f 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -4,30 +4,55 @@ #include void HttpContext::httpBegin(us_socket *s) { - // yep - std::cout << "Accepted a connection" << std::endl; + Hub::Data *hubData = (Hub::Data *) us_loop_userdata(s->context->loop); + + //std::cout << "BeginHTTP: " << s << std::endl; + + // should not touch the socket? + new (s) HttpSocket(); + + // tester + ((HttpSocket *) s)->outStream = nullptr; + + hubData->onHttpConnection((HttpSocket *) s); +} + +void HttpContext::httpEnd(us_socket *s) { + Hub::Data *hubData = (Hub::Data *) us_loop_userdata(s->context->loop); + + hubData->onHttpDisconnection((HttpSocket *) s); } void HttpContext::httpData(us_socket *s, void *data, int size) { Hub::Data *hubData = (Hub::Data *) us_loop_userdata(s->context->loop); - - hubData->onHttpRequest(nullptr, nullptr, (char *) data, size); + hubData->onHttpRequest((HttpSocket *) s, nullptr, (char *) data, size); } -void HttpContext::httpEnd(us_socket *s) { - // yep - std::cout << "Disconnection of a connection" << std::endl; +void HttpContext::httpOut(us_socket *s) { + HttpSocket *httpSocket = (HttpSocket *) s; + + std::pair chunk = httpSocket->outStream(httpSocket->offset); + httpSocket->offset += us_socket_write(s, chunk.first, chunk.second); } -HttpContext::HttpContext(us_loop *loop) { - context = us_create_socket_context(loop, sizeof(us_socket_context)); - - context->on_accepted = httpBegin; - context->on_data = httpData; - context->on_end = httpEnd; +HttpContext::HttpContext() { + context.on_accepted = httpBegin; + context.on_data = httpData; + context.on_end = httpEnd; + context.on_writable = httpOut; } void HttpContext::listen(const char *host, int port, int options) { - us_socket_context_listen(context, host, port, options, sizeof(us_socket)); + us_socket_context_listen(&context, host, port, options, sizeof(HttpSocket)); +} + +// HttpSocket +void HttpSocket::stream(int length, decltype(outStream) stream) { + outStream = stream; + offset = 0; + + // try stream + std::pair chunk = outStream(offset); + offset = us_socket_write(&s, chunk.first, chunk.second); } diff --git a/src/Http.h b/src/Http.h index 2d412af..1c26f4d 100644 --- a/src/Http.h +++ b/src/Http.h @@ -2,31 +2,38 @@ #define HTTP_H #include "libusockets.h" +#include struct HttpRequest { }; -struct HttpResponse { +struct HttpSocket { + us_socket s; + int offset = 0; - void write() { + HttpSocket() { } + std::function(int)> outStream; + void stream(int length, decltype(outStream) stream); }; // basically a HttpServer struct HttpContext { - us_socket_context *context; - struct Data { + us_socket_context context; + /*struct Data { - } *data; + } *data;*/ static void httpBegin(us_socket *s); + // httpIn static void httpData(us_socket *s, void *data, int size); + static void httpOut(us_socket *s); static void httpEnd(us_socket *s); - HttpContext(us_loop *loop); + HttpContext(); void listen(const char *host, int port, int options); }; diff --git a/src/Hub.cpp b/src/Hub.cpp index d480923..c6df810 100644 --- a/src/Hub.cpp +++ b/src/Hub.cpp @@ -7,11 +7,15 @@ void Hub::wakeupCb(us_loop *loop) { Hub::Hub() { loop = us_create_loop(wakeupCb, sizeof(Data)); - new (data = (Data *) us_loop_userdata(loop)) Data(loop); + new (data = (Data *) us_loop_userdata(loop)) Data(); + + // this could lie in Data constructor + data->httpContext = (HttpContext *) us_create_socket_context(loop, sizeof(HttpContext)); + new (data->httpContext) HttpContext(); } void Hub::listen(const char *host, int port, int options) { - data->httpContext.listen(host, port, options); + data->httpContext->listen(host, port, options); } void Hub::run() { diff --git a/src/Hub.h b/src/Hub.h index 0606064..36d4089 100644 --- a/src/Hub.h +++ b/src/Hub.h @@ -10,15 +10,23 @@ struct Hub { us_loop *loop; struct Data { - Data(us_loop *loop) : httpContext(loop) { + Data() { } - HttpContext httpContext; - std::function onHttpRequest; + HttpContext *httpContext; + std::function onHttpConnection; + std::function onHttpDisconnection; + std::function onHttpRequest; } *data; static void wakeupCb(us_loop *loop); + void onHttpConnection(decltype(Data::onHttpConnection) handler) { + data->onHttpConnection = handler; + } + void onHttpDisconnection(decltype(Data::onHttpDisconnection) handler) { + data->onHttpDisconnection = handler; + } void onHttpRequest(decltype(Data::onHttpRequest) handler) { data->onHttpRequest = handler; }