A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Revision:
3:ab6fd66d172c
Parent:
2:849103b5a16d
Child:
4:31fa7d50722c
--- a/http.cpp	Fri Jan 27 19:58:51 2017 +0000
+++ b/http.cpp	Sat Jan 28 19:10:30 2017 +0000
@@ -1,73 +1,45 @@
 #include    "mbed.h"
-#include "favicon.h"
-#include     "css.h"
-#include     "arp.h"
+#include    "http.h"
 #include    "time.h"
-
-#define DO_NOT_FOUND 0
-#define DO_CSS       1
-#define DO_FAVICON   2
-#define DO_HTML      3
-
-#define HTTP_DATE_LENGTH 30
-
-static char* addNavItem(char* pText, int highlight, char* href, char* title)
-{
-    char *p;
-    p = "<li ";          while (*p) *pText++ = *p++;
-    if (highlight) p = "class='this'";
-    else           p = "            ";
-                         while (*p) *pText++ = *p++;
-    p = "><a href='";    while (*p) *pText++ = *p++;
-    p = href;            while (*p) *pText++ = *p++;
-    p = "'>";            while (*p) *pText++ = *p++;
-    p = title;           while (*p) *pText++ = *p++;
-    p = "</a></li>\r\n"; while (*p) *pText++ = *p++;
-    
-    return pText;
-}
-enum pages
-{
-       HOME_PAGE,
-    PROGRAM_PAGE,
-    HEATING_PAGE,
-     BOILER_PAGE,
-     SYSTEM_PAGE,
-        LOG_PAGE
-};
-static void addNav(char* pText, int page)
-{
-    char* p;
-    p = "<nav><ul>\r\n";  while (*p) *pText++ = *p++;
-    pText = addNavItem(pText, page ==    HOME_PAGE, "/",        "Home");
-    pText = addNavItem(pText, page == PROGRAM_PAGE, "/program", "Program");
-    pText = addNavItem(pText, page == HEATING_PAGE, "/heating", "Heating");
-    pText = addNavItem(pText, page ==  BOILER_PAGE, "/boiler",  "Boiler");
-    pText = addNavItem(pText, page ==  SYSTEM_PAGE, "/system",  "System");
-    pText = addNavItem(pText, page ==     LOG_PAGE, "/log",     "Log");
-    p = "</ul></nav>\r\n";  while (*p) *pText++ = *p++;
-    *pText = 0;
-}
-
+#include  "server.h"
 
 static void dateHeaderFromTm(struct tm* ptm, char* ptext)
 {
     size_t size = strftime(ptext, HTTP_DATE_LENGTH, "%a, %d %b %Y %H:%M:%S GMT", ptm);//Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
 }
-static void dateHeaderFromNow(char* pText)
+void HttpDateHeaderFromNow(char* pText)
 {
     struct tm tm;
     TimeToTmUtc(time(NULL), &tm);
     dateHeaderFromTm(&tm, pText);
 }
-static void dateHeaderFromDateTime(const char* date, const char *ptime, char* ptext)
+void HttpDateHeaderFromDateTime(const char* date, const char *ptime, char* ptext)
 {
     struct tm tm;
     TimeAsciiDateTimeToTm(date, ptime, &tm);
     dateHeaderFromTm(&tm, ptext);
 }
 
-
+static char* getNextLine(char* p, char* pE) //Terminates this line and returns the start of the next line or NULL if none
+{
+    while (true)
+    {
+        if (p == pE)             //There are no more lines
+        {
+            *p = 0;              //terminate the line
+            return NULL;   
+        }
+        if (*p == 0) return NULL;//There are no more lines
+        if (*p == '\n')
+        {
+            *p = 0;              //make the line a c string
+            return p + 1;        //return the start of the next line
+        }
+        if (*p < ' ')    *p = 0; //terminate the line at any invalid characters
+        if (*p >= 0x7f)  *p = 0; //terminate the line at any invalid characters
+        p++;
+    }
+}
 
 static void splitRequest(char* p, char** ppMethod, char** ppPath, char** ppQuery)
 {        
@@ -109,185 +81,52 @@
     }
     *p = 0;                   //Terminate the path or query
 }
+static void splitHeader(char* p, char** ppName, char** ppValue)
+{
+    *ppName    = p;                     //Record the start of the name
+    *ppValue   = NULL;
 
+    while (*p != ':')                   //Loop to an ':'
+    {
+        if (!*p) return;
+        p++;
+    }
+    *p = 0;                             //Terminate the name by replacing the ':' with a NUL char
+    p++;
+    while (*p == ' ')                   //Move past any spaces
+    {
+        if (*p == 0) return;
+        p++;
+    }
+    *ppValue = p;                       //Record the start of the value
+}
 int HttpRequest(int position, int len, char *pData)
-{    
+{   
     char* pMethod;
     char* pPath;
     char* pQuery;
 
-    splitRequest(pData, &pMethod, &pPath, &pQuery);
+    char* pEnd = pData + len;
+    char* pThis = pData;    
+    char* pNext = getNextLine(pThis, pEnd);
+    splitRequest(pThis, &pMethod, &pPath, &pQuery);
 
-    int todo = DO_NOT_FOUND;
-    if (strcmp(pPath, "/"           ) == 0) todo = DO_HTML;
-    if (strcmp(pPath, "/favicon.ico") == 0) todo = DO_FAVICON;
-    if (strcmp(pPath, "/gps.css"    ) == 0) todo = DO_CSS;
-    
-    return todo;
-}
-int sendNotFound(int position, int mss, char* pData)
-{
-    printf("Sending 404 Not Found\r\n"); 
-    char *pHttp =   "HTTP/1.1 404 Not Found\r\n"
-                    "\r\n";
-    int lenHttp =   strlen(pHttp);
-    char* p = pData;
-    for (int i = position; i < position + mss; i++)
+    char* pLastModified;
+    while(pNext)
     {
-        if      (i < lenHttp          ) *p++ = pHttp[i];
-        else                            break;
-    }
-    return p - pData;
-}
-int sendHtml(int position, int mss, char* pData)
-{
-    const char *pA =   "HTTP/1.1 200 OK\r\n"
-                        "Content-Type: text/html; charset=UTF-8\r\n"
-                        "Connection: close\r\n"
-                        "Cache-control: no-cache\r\n"
-                        "Date: ";
-                        
-    char pB[HTTP_DATE_LENGTH];
-    dateHeaderFromNow(pB);
- 
-    const char* pC =    "\r\n"
-                        "\r\n"
-                        "<html>\r\n"
-                        "<head>\r\n"
-                        "   <meta name='viewport' content='width=device-width, initial-scale=1'>\r\n"
-                        "   <link rel='icon'       href='/favicon.ico' type='image/x-icon'/>\r\n"
-                        "   <link rel='stylesheet' href='/gps.css'     type='text/css'    />\r\n"
-                        "   <title>GPS Clock</title>\r\n"
-                        "</head>\r\n"
-                        "<body>\r\n";
-
-    char pD[400];
-    addNav(pD, HOME_PAGE);
-    
-    const char* pE =    "\r\n"
-                        "<h1>GPS Clock</h1>\r\n"
-                        "<h2>ARP</h2>\r\n"
-                        "<code>";
-                        
-    char pF[400];
-    ArpAsString(400, pF);
-    
-    const char* pG =    "</code>\r\n"
-                        "</body>\r\n"
-                        "</html>\r\n";
-                        
-    int lA =      strlen(pA);
-    int lB = lA + HTTP_DATE_LENGTH;
-    int lC = lB + strlen(pC);
-    int lD = lC + strlen(pD);
-    int lE = lD + strlen(pE);
-    int lF = lE + strlen(pF);
-    int lG = lF + strlen(pG);
-    
-    char* p = pData;
-    for (int i = position; i < position + mss; i++)
-    {
-        if      (i < lA) *p++ = pA[i];
-        else if (i < lB) *p++ = pB[i - lA];
-        else if (i < lC) *p++ = pC[i - lB];
-        else if (i < lD) *p++ = pD[i - lC];
-        else if (i < lE) *p++ = pE[i - lD];
-        else if (i < lF) *p++ = pF[i - lE];
-        else if (i < lG) *p++ = pG[i - lF];
-        else break;
+        pThis = pNext;
+        pNext = getNextLine(pThis, pEnd);
+        if (*pThis == 0) break;     //This line is empty ie no more headers
+        char* pName;
+        char* pValue;
+        splitHeader(pThis, &pName, &pValue);
+        if (strcmp(pName, "If-Modified-Since") == 0) pLastModified = pValue;
     }
-    return p - pData;
-}
-int sendCss(int position, int mss, char* pData)
-{
-    const char *pA =    "HTTP/1.1 200 OK\r\n"
-                        "Content-Type: text/css; charset=UTF-8\r\n"
-                        "Connection: close\r\n"
-                        "Cache-Control: max-age=3600\r\n"
-                        "Date: ";
     
-    char pB[HTTP_DATE_LENGTH];
-    dateHeaderFromNow(pB);
-    
-    const char *pC =    "\r\n"
-                        "Last-Modified: ";
-    
-    char pD[HTTP_DATE_LENGTH];
-    dateHeaderFromDateTime(CssDate, CssTime, pD);
-    
-    const char *pE =    "\r\n\r\n";
-    
-    const char *pF = Css;
-    
-    int lA =      strlen(pA);
-    int lB = lA + HTTP_DATE_LENGTH;
-    int lC = lB + strlen(pC);
-    int lD = lC + HTTP_DATE_LENGTH;
-    int lE = lD + strlen(pE);
-    int lF = lE + strlen(pF);
-    
-    char* p = pData;
-    for (int i = position; i < position + mss; i++)
-    {
-        if      (i < lA) *p++ = pA[i];
-        else if (i < lB) *p++ = pB[i - lA];
-        else if (i < lC) *p++ = pC[i - lB];
-        else if (i < lD) *p++ = pD[i - lC];
-        else if (i < lE) *p++ = pE[i - lD];
-        else if (i < lF) *p++ = pF[i - lE];
-        else break;
-    }
-    return p - pData;
-}
-int sendFavicon(int position, int mss, char* pData)
-{
-    const char* pA =   "HTTP/1.1 200 OK\r\n"
-                        "Content-Type: image/x-icon\r\n"
-                        "Connection: close\r\n"
-                        "Cache-Control: max-age=3600\r\n"
-                        "Date: ";
-                        
-    char pB[HTTP_DATE_LENGTH];
-    dateHeaderFromNow(pB);
-    
-    const char *pC =    "\r\n"
-                        "Last-Modified: ";
-    
-    char pD[HTTP_DATE_LENGTH];
-    dateHeaderFromDateTime(FaviconDate, FaviconTime, pD);
-    
-    const char *pE =    "\r\n\r\n";
-    
-    const char *pF = Favicon;
-    
-    int lA =      strlen(pA);
-    int lB = lA + HTTP_DATE_LENGTH;
-    int lC = lB + strlen(pC);
-    int lD = lC + HTTP_DATE_LENGTH;
-    int lE = lD + strlen(pE);
-    int lF = lE + FaviconSize;
-    
-    char* p = pData;
-    for (int i = position; i < position + mss; i++)
-    {
-        if      (i < lA) *p++ = pA[i];
-        else if (i < lB) *p++ = pB[i - lA];
-        else if (i < lC) *p++ = pC[i - lB];
-        else if (i < lD) *p++ = pD[i - lC];
-        else if (i < lE) *p++ = pE[i - lD];
-        else if (i < lF) *p++ = pF[i - lE];
-        else break;
-    }
-    return p - pData;
+    return ServerRequest(pPath, pLastModified);
 }
 int HttpResponse(int position, int mss, char *pData, int todo)
 {
-    switch (todo)
-    {
-        case DO_NOT_FOUND: return sendNotFound(position, mss, pData); 
-        case DO_HTML:      return sendHtml    (position, mss, pData);
-        case DO_CSS:       return sendCss     (position, mss, pData);
-        case DO_FAVICON:   return sendFavicon (position, mss, pData);
-    }
-    return 0;
+    return ServerResponse(position, mss, pData, todo);
 }
+