From 0cbccaf08e6aed5bcab83d12d251f2b10fe16df7 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Sun, 24 Jun 2018 01:27:40 +0200 Subject: [PATCH] Actually put headers, content-length and status in response --- main.cpp | 32 +++++++++++---------- src/App.h | 2 +- src/Http.h | 82 +++++++++++++++++++++++++++++++++++------------------- src/Loop.h | 9 +++--- src/uWS.h | 2 +- 5 files changed, 77 insertions(+), 50 deletions(-) diff --git a/main.cpp b/main.cpp index 32e0b96..950d059 100644 --- a/main.cpp +++ b/main.cpp @@ -1,31 +1,33 @@ -// this is roughly the interfaces I plan for (with changes and additional helpers added with time) -// much speaks for a header-only or header-mostly implementation now that uSockets is properly isolating its internal headers +#include "uWS.h" -#include "App.h" -#include "HttpRouter.h" +std::string buffer; + +//#define USE_SSL int main() { - std::cout << "HttpSocket size: " << sizeof(HttpSocket::Data) << std::endl; - char *buffer = new char[512]; + buffer = "Why hello there!"; - uWS::SSLApp c(uWS::SSLOptions() + //uWS::init(); + //uWS::Loop loop(); + +#ifdef USE_SSL + uWS::SSLApp app(uWS::SSLOptions() .keyFileName("/home/alexhultman/uWebSockets/misc/ssl/key.pem") .certFileName("/home/alexhultman/uWebSockets/misc/ssl/cert.pem") .passphrase("1234")); - //uWS::App c; +#else + uWS::App app; +#endif - c.onGet("/", [buffer](auto *s, HttpRequest *req, auto *args) { + app.onGet("/", [](auto *s, auto *req, auto *args) { - s->writeStatus(200)->writeHeader("Hello", "World")->end(buffer, 512); + s->writeStatus("200 OK")->writeHeader("Hello", "World")->end(buffer); - }).onGet("/wrong", [buffer](auto *s, HttpRequest *req, auto *args) { - - std::cout << "Wrong way!" << std::endl; - - }).onWebSocket([]() { + }).onWebSocket("/wsApi", []() { }).listen("localhost", 3000, 0); uWS::run(); + // loop.run(); } diff --git a/src/App.h b/src/App.h index 7bfbbd3..eb699bb 100644 --- a/src/App.h +++ b/src/App.h @@ -125,7 +125,7 @@ public: } // for client and server - AppBase &onWebSocket(std::function handler) { + AppBase &onWebSocket(std::string pattern, std::function handler) { return *this; } diff --git a/src/Http.h b/src/Http.h index 4c2dece..4485e9d 100644 --- a/src/Http.h +++ b/src/Http.h @@ -2,6 +2,7 @@ #define HTTP_H #include "libusockets.h" +#include "Loop.h" #include #include @@ -88,50 +89,75 @@ struct HttpSocket { std::function(int)> outStream; }; - // cork is stored in hub - char *getCorkBuffer() { - // context -> hub -> cork buffer + // only this one should be used! + void writeToCorkBuffer(const char *src, int length) { + uWS::Loop::Data *loopData = (uWS::Loop::Data *) us_loop_ext(us_socket_context_loop(us_socket_get_context((us_socket *) this))); - us_socket *s = (us_socket *) this; - - // get the loop from the context! - //return us_socket_context_loop(us_socket_get_context(s)); - - - return corkBuffer; + memcpy(loopData->corkBuffer + loopData->corkOffset, src, length); + loopData->corkOffset += length; } - HttpSocket *writeStatus(int status) { - char *corkBuffer = getCorkBuffer(); + // sprintf is super slow, this one is a lot faster + int u32toa_naive(uint32_t value, char *dst) { + char temp[10]; + char *p = temp; + do { + *p++ = char(value % 10) + '0'; + value /= 10; + } while (value > 0); - char largeBuf[] = "HTTP/1.1 200 OK\r\nContent-Length: 512\r\n\r\n"; + int ret = p - temp; - memcpy(corkBuffer + corkOffset, largeBuf, sizeof(largeBuf) - 1); - corkOffset += sizeof(largeBuf) - 1; + do { + *dst++ = *--p; + } while (p != temp); - return this; + return ret; } - HttpSocket *writeHeader(char *key, char *value) { - return this; - } + // never rely on this one! + void writeToCorkBufferAndReset(const char *src, int length) { + uWS::Loop::Data *loopData = (uWS::Loop::Data *) us_loop_ext(us_socket_context_loop(us_socket_get_context((us_socket *) this))); - // this depends on SSL! - void end(char *data, int length) { - //us_ssl_socket *s = (us_ssl_socket *) this; + memcpy(loopData->corkBuffer + loopData->corkOffset, "Content-Length: ", 16); + loopData->corkOffset += 16; - char *corkBuffer = getCorkBuffer(); - memcpy(corkBuffer + corkOffset, data, length); - corkOffset += length; + loopData->corkOffset += u32toa_naive(length, loopData->corkBuffer + loopData->corkOffset); + memcpy(loopData->corkBuffer + loopData->corkOffset, "\r\n\r\n", 4); + loopData->corkOffset += 4; + + + memcpy(loopData->corkBuffer + loopData->corkOffset, src, length); + loopData->corkOffset += length; if constexpr(SSL) { - us_ssl_socket_write((us_ssl_socket *) this, corkBuffer, corkOffset); + us_ssl_socket_write((us_ssl_socket *) this, loopData->corkBuffer, loopData->corkOffset); } else { - us_socket_write((us_socket *) this, corkBuffer, corkOffset, 0); + us_socket_write((us_socket *) this, loopData->corkBuffer, loopData->corkOffset, 0); } - corkOffset = 0; + loopData->corkOffset = 0; + } + + HttpSocket *writeStatus(std::string_view status) { + writeToCorkBuffer("HTTP/1.1 ", 9); + writeToCorkBuffer(status.data(), status.length()); + writeToCorkBuffer("\r\n", 2); + return this; + } + + HttpSocket *writeHeader(std::string_view key, std::string_view value) { + writeToCorkBuffer(key.data(), key.length()); + writeToCorkBuffer(": ", 2); + writeToCorkBuffer(value.data(), value.length()); + writeToCorkBuffer("\r\n", 2); + return this; + } + + void end(std::string_view data) { + // end should not explicitly flush the cork buffer! delay to when done with all http data! + writeToCorkBufferAndReset(data.data(), data.length()); } // can't create this! diff --git a/src/Loop.h b/src/Loop.h index eb3ee98..b7785bd 100644 --- a/src/Loop.h +++ b/src/Loop.h @@ -1,7 +1,3 @@ -// should lie in hub and be connected with pre/post callbacks -char *corkBuffer = new char[1024]; -int corkOffset = 0; - #ifndef HUB_H #define HUB_H @@ -16,8 +12,11 @@ struct Loop { us_loop *loop; struct Data { - Data() { + char *corkBuffer = new char[1024]; + int corkOffset = 0; + + Data() { } diff --git a/src/uWS.h b/src/uWS.h index ce67783..d083d12 100644 --- a/src/uWS.h +++ b/src/uWS.h @@ -1,6 +1,6 @@ #ifndef UWS_H #define UWS_H -#include "Loop.h" +#include "App.h" #endif // UWS_H