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
http.cpp
- Committer:
- andrewboyson
- Date:
- 2017-01-27
- Revision:
- 2:849103b5a16d
- Parent:
- 1:5f70c361db20
- Child:
- 3:ab6fd66d172c
File content as of revision 2:849103b5a16d:
#include "mbed.h" #include "favicon.h" #include "css.h" #include "arp.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; } 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) { struct tm tm; TimeToTmUtc(time(NULL), &tm); dateHeaderFromTm(&tm, pText); } static void dateHeaderFromDateTime(const char* date, const char *ptime, char* ptext) { struct tm tm; TimeAsciiDateTimeToTm(date, ptime, &tm); dateHeaderFromTm(&tm, ptext); } static void splitRequest(char* p, char** ppMethod, char** ppPath, char** ppQuery) { *ppMethod = NULL; *ppPath = NULL; *ppQuery = NULL; while (*p == ' ') //Move past any leading spaces { if (*p == 0) return; p++; } *ppMethod = p; //Record the start of the method (GET or POST) while (*p != ' ') //Move past the method { if (*p == 0) return; p++; } *p = 0; //Terminate the method p++; //Start at next character while (*p == ' ') //Move past any spaces { if (*p == 0) return; p++; } *ppPath = p; //Record the start of the path while (*p != ' ') //Move past the path and query { if (*p == 0) return; if (*p == '?') { *p = 0; //Terminate the path *ppQuery = p + 1; //Record the start of the query } p++; } *p = 0; //Terminate the path or query } int HttpRequest(int position, int len, char *pData) { char* pMethod; char* pPath; char* pQuery; splitRequest(pData, &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++) { 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; } 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; } 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; }