BVB Source Codes

uWebSockets Show HTTPSocket.h Source code

Return Download uWebSockets: download HTTPSocket.h Source code - Download uWebSockets Source code - Type:.h
  1. #ifndef HTTPSOCKET_UWS_H
  2. #define HTTPSOCKET_UWS_H
  3.  
  4. #include "Socket.h"
  5. #include <string>
  6. // #include <experimental/string_view>
  7.  
  8. namespace uWS {
  9.  
  10. struct Header {
  11.     char *key, *value;
  12.     unsigned int keyLength, valueLength;
  13.  
  14.     operator bool() {
  15.         return key;
  16.     }
  17.  
  18.     // slow without string_view!
  19.     std::string toString() {
  20.         return std::string(value, valueLength);
  21.     }
  22. };
  23.  
  24. enum HttpMethod {
  25.     METHOD_GET,
  26.     METHOD_POST,
  27.     METHOD_PUT,
  28.     METHOD_DELETE,
  29.     METHOD_PATCH,
  30.     METHOD_OPTIONS,
  31.     METHOD_HEAD,
  32.     METHOD_TRACE,
  33.     METHOD_CONNECT,
  34.     METHOD_INVALID
  35. };
  36.  
  37. struct HttpRequest {
  38.     Header *headers;
  39.     Header getHeader(const char *key) {
  40.         return getHeader(key, strlen(key));
  41.     }
  42.  
  43.     HttpRequest(Header *headers = nullptr) : headers(headers) {}
  44.  
  45.     Header getHeader(const char *key, size_t length) {
  46.         if (headers) {
  47.             for (Header *h = headers; *++h; ) {
  48.                 if (h->keyLength == length && !strncmp(h->key, key, length)) {
  49.                     return *h;
  50.                 }
  51.             }
  52.         }
  53.         return {nullptr, nullptr, 0, 0};
  54.     }
  55.  
  56.     Header getUrl() {
  57.         if (headers->key) {
  58.             return *headers;
  59.         }
  60.         return {nullptr, nullptr, 0, 0};
  61.     }
  62.  
  63.     HttpMethod getMethod() {
  64.         if (!headers->key) {
  65.             return METHOD_INVALID;
  66.         }
  67.         switch (headers->keyLength) {
  68.         case 3:
  69.             if (!strncmp(headers->key, "get", 3)) {
  70.                 return METHOD_GET;
  71.             } else if (!strncmp(headers->key, "put", 3)) {
  72.                 return METHOD_PUT;
  73.             }
  74.             break;
  75.         case 4:
  76.             if (!strncmp(headers->key, "post", 4)) {
  77.                 return METHOD_POST;
  78.             } else if (!strncmp(headers->key, "head", 4)) {
  79.                 return METHOD_HEAD;
  80.             }
  81.             break;
  82.         case 5:
  83.             if (!strncmp(headers->key, "patch", 5)) {
  84.                 return METHOD_PATCH;
  85.             } else if (!strncmp(headers->key, "trace", 5)) {
  86.                 return METHOD_TRACE;
  87.             }
  88.             break;
  89.         case 6:
  90.             if (!strncmp(headers->key, "delete", 6)) {
  91.                 return METHOD_DELETE;
  92.             }
  93.             break;
  94.         case 7:
  95.             if (!strncmp(headers->key, "options", 7)) {
  96.                 return METHOD_OPTIONS;
  97.             } else if (!strncmp(headers->key, "connect", 7)) {
  98.                 return METHOD_CONNECT;
  99.             }
  100.             break;
  101.         }
  102.         return METHOD_INVALID;
  103.     }
  104. };
  105.  
  106. struct HttpResponse;
  107.  
  108. template <const bool isServer>
  109. struct WIN32_EXPORT HttpSocket : uS::Socket {
  110.     void *httpUser; // remove this later, setTimeout occupies user for now
  111.     HttpResponse *outstandingResponsesHead = nullptr;
  112.     HttpResponse *outstandingResponsesTail = nullptr;
  113.     HttpResponse *preAllocatedResponse = nullptr;
  114.  
  115.     std::string httpBuffer;
  116.     size_t contentLength = 0;
  117.     bool missedDeadline = false;
  118.  
  119.     HttpSocket(uS::Socket *socket) : uS::Socket(std::move(*socket)) {}
  120.  
  121.     void terminate() {
  122.         onEnd(this);
  123.     }
  124.  
  125.     void upgrade(const char *secKey, const char *extensions,
  126.                  size_t extensionsLength, const char *subprotocol,
  127.                  size_t subprotocolLength, bool *perMessageDeflate);
  128.  
  129. private:
  130.     friend struct uS::Socket;
  131.     friend struct HttpResponse;
  132.     friend struct Hub;
  133.     static uS::Socket *onData(uS::Socket *s, char *data, size_t length);
  134.     static void onEnd(uS::Socket *s);
  135. };
  136.  
  137. struct HttpResponse {
  138.     HttpSocket<true> *httpSocket;
  139.     HttpResponse *next = nullptr;
  140.     void *userData = nullptr;
  141.     void *extraUserData = nullptr;
  142.     HttpSocket<true>::Queue::Message *messageQueue = nullptr;
  143.     bool hasEnded = false;
  144.     bool hasHead = false;
  145.  
  146.     HttpResponse(HttpSocket<true> *httpSocket) : httpSocket(httpSocket) {
  147.  
  148.     }
  149.  
  150.     template <bool isServer>
  151.     static HttpResponse *allocateResponse(HttpSocket<isServer> *httpSocket) {
  152.         if (httpSocket->preAllocatedResponse) {
  153.             HttpResponse *ret = httpSocket->preAllocatedResponse;
  154.             httpSocket->preAllocatedResponse = nullptr;
  155.             return ret;
  156.         } else {
  157.             return new HttpResponse((HttpSocket<true> *) httpSocket);
  158.         }
  159.     }
  160.  
  161.     //template <bool isServer>
  162.     void freeResponse(HttpSocket<true> *httpData) {
  163.         if (httpData->preAllocatedResponse) {
  164.             delete this;
  165.         } else {
  166.             httpData->preAllocatedResponse = this;
  167.         }
  168.     }
  169.  
  170.     void write(const char *message, size_t length = 0,
  171.                void(*callback)(void *httpSocket, void *data, bool cancelled, void *reserved) = nullptr,
  172.                void *callbackData = nullptr) {
  173.  
  174.         struct NoopTransformer {
  175.             static size_t estimate(const char *data, size_t length) {
  176.                 return length;
  177.             }
  178.  
  179.             static size_t transform(const char *src, char *dst, size_t length, int transformData) {
  180.                 memcpy(dst, src, length);
  181.                 return length;
  182.             }
  183.         };
  184.  
  185.         httpSocket->sendTransformed<NoopTransformer>(message, length, callback, callbackData, 0);
  186.         hasHead = true;
  187.     }
  188.  
  189.     // todo: maybe this function should have a fast path for 0 length?
  190.     void end(const char *message = nullptr, size_t length = 0,
  191.              void(*callback)(void *httpResponse, void *data, bool cancelled, void *reserved) = nullptr,
  192.              void *callbackData = nullptr) {
  193.  
  194.         struct TransformData {
  195.             bool hasHead;
  196.         } transformData = {hasHead};
  197.  
  198.         struct HttpTransformer {
  199.  
  200.             // todo: this should get TransformData!
  201.             static size_t estimate(const char *data, size_t length) {
  202.                 return length + 128;
  203.             }
  204.  
  205.             static size_t transform(const char *src, char *dst, size_t length, TransformData transformData) {
  206.                 // todo: sprintf is extremely slow
  207.                 int offset = transformData.hasHead ? 0 : std::sprintf(dst, "HTTP/1.1 200 OK\r\nContent-Length: %u\r\n\r\n", (unsigned int) length);
  208.                 memcpy(dst + offset, src, length);
  209.                 return length + offset;
  210.             }
  211.         };
  212.  
  213.         if (httpSocket->outstandingResponsesHead != this) {
  214.             HttpSocket<true>::Queue::Message *messagePtr = httpSocket->allocMessage(HttpTransformer::estimate(message, length));
  215.             messagePtr->length = HttpTransformer::transform(message, (char *) messagePtr->data, length, transformData);
  216.             messagePtr->callback = callback;
  217.             messagePtr->callbackData = callbackData;
  218.             messagePtr->nextMessage = messageQueue;
  219.             messageQueue = messagePtr;
  220.             hasEnded = true;
  221.         } else {
  222.             httpSocket->sendTransformed<HttpTransformer>(message, length, callback, callbackData, transformData);
  223.             // move head as far as possible
  224.             HttpResponse *head = next;
  225.             while (head) {
  226.                 // empty message queue
  227.                 HttpSocket<true>::Queue::Message *messagePtr = head->messageQueue;
  228.                 while (messagePtr) {
  229.                     HttpSocket<true>::Queue::Message *nextMessage = messagePtr->nextMessage;
  230.  
  231.                     bool wasTransferred;
  232.                     if (httpSocket->write(messagePtr, wasTransferred)) {
  233.                         if (!wasTransferred) {
  234.                             httpSocket->freeMessage(messagePtr);
  235.                             if (callback) {
  236.                                 callback(this, callbackData, false, nullptr);
  237.                             }
  238.                         } else {
  239.                             messagePtr->callback = callback;
  240.                             messagePtr->callbackData = callbackData;
  241.                         }
  242.                     } else {
  243.                         httpSocket->freeMessage(messagePtr);
  244.                         if (callback) {
  245.                             callback(this, callbackData, true, nullptr);
  246.                         }
  247.                         goto updateHead;
  248.                     }
  249.                     messagePtr = nextMessage;
  250.                 }
  251.                 // cannot go beyond unfinished responses
  252.                 if (!head->hasEnded) {
  253.                     break;
  254.                 } else {
  255.                     HttpResponse *next = head->next;
  256.                     head->freeResponse(httpSocket);
  257.                     head = next;
  258.                 }
  259.             }
  260.             updateHead:
  261.             httpSocket->outstandingResponsesHead = head;
  262.             if (!head) {
  263.                 httpSocket->outstandingResponsesTail = nullptr;
  264.             }
  265.  
  266.             freeResponse(httpSocket);
  267.         }
  268.     }
  269.  
  270.     void setUserData(void *userData) {
  271.         this->userData = userData;
  272.     }
  273.  
  274.     void *getUserData() {
  275.         return userData;
  276.     }
  277.  
  278.     HttpSocket<true> *getHttpSocket() {
  279.         return httpSocket;
  280.     }
  281. };
  282.  
  283. }
  284.  
  285. #endif // HTTPSOCKET_UWS_H
  286.  
downloadHTTPSocket.h Source code - Download uWebSockets Source code
Related Source Codes/Software:
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
postal - 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11

 Back to top