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
Diff: http.cpp
- 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); } +