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

Committer:
andrewboyson
Date:
Fri Jan 27 19:58:51 2017 +0000
Revision:
2:849103b5a16d
Parent:
1:5f70c361db20
Child:
3:ab6fd66d172c
DHCP working and most options decoded; TCP and HTTP working.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 2:849103b5a16d 1 #include "mbed.h"
andrewboyson 2:849103b5a16d 2 #include "favicon.h"
andrewboyson 2:849103b5a16d 3 #include "css.h"
andrewboyson 2:849103b5a16d 4 #include "arp.h"
andrewboyson 2:849103b5a16d 5 #include "time.h"
andrewboyson 2:849103b5a16d 6
andrewboyson 2:849103b5a16d 7 #define DO_NOT_FOUND 0
andrewboyson 2:849103b5a16d 8 #define DO_CSS 1
andrewboyson 2:849103b5a16d 9 #define DO_FAVICON 2
andrewboyson 2:849103b5a16d 10 #define DO_HTML 3
andrewboyson 2:849103b5a16d 11
andrewboyson 2:849103b5a16d 12 #define HTTP_DATE_LENGTH 30
andrewboyson 2:849103b5a16d 13
andrewboyson 2:849103b5a16d 14 static char* addNavItem(char* pText, int highlight, char* href, char* title)
andrewboyson 2:849103b5a16d 15 {
andrewboyson 2:849103b5a16d 16 char *p;
andrewboyson 2:849103b5a16d 17 p = "<li "; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 18 if (highlight) p = "class='this'";
andrewboyson 2:849103b5a16d 19 else p = " ";
andrewboyson 2:849103b5a16d 20 while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 21 p = "><a href='"; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 22 p = href; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 23 p = "'>"; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 24 p = title; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 25 p = "</a></li>\r\n"; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 26
andrewboyson 2:849103b5a16d 27 return pText;
andrewboyson 2:849103b5a16d 28 }
andrewboyson 2:849103b5a16d 29 enum pages
andrewboyson 2:849103b5a16d 30 {
andrewboyson 2:849103b5a16d 31 HOME_PAGE,
andrewboyson 2:849103b5a16d 32 PROGRAM_PAGE,
andrewboyson 2:849103b5a16d 33 HEATING_PAGE,
andrewboyson 2:849103b5a16d 34 BOILER_PAGE,
andrewboyson 2:849103b5a16d 35 SYSTEM_PAGE,
andrewboyson 2:849103b5a16d 36 LOG_PAGE
andrewboyson 2:849103b5a16d 37 };
andrewboyson 2:849103b5a16d 38 static void addNav(char* pText, int page)
andrewboyson 2:849103b5a16d 39 {
andrewboyson 2:849103b5a16d 40 char* p;
andrewboyson 2:849103b5a16d 41 p = "<nav><ul>\r\n"; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 42 pText = addNavItem(pText, page == HOME_PAGE, "/", "Home");
andrewboyson 2:849103b5a16d 43 pText = addNavItem(pText, page == PROGRAM_PAGE, "/program", "Program");
andrewboyson 2:849103b5a16d 44 pText = addNavItem(pText, page == HEATING_PAGE, "/heating", "Heating");
andrewboyson 2:849103b5a16d 45 pText = addNavItem(pText, page == BOILER_PAGE, "/boiler", "Boiler");
andrewboyson 2:849103b5a16d 46 pText = addNavItem(pText, page == SYSTEM_PAGE, "/system", "System");
andrewboyson 2:849103b5a16d 47 pText = addNavItem(pText, page == LOG_PAGE, "/log", "Log");
andrewboyson 2:849103b5a16d 48 p = "</ul></nav>\r\n"; while (*p) *pText++ = *p++;
andrewboyson 2:849103b5a16d 49 *pText = 0;
andrewboyson 2:849103b5a16d 50 }
andrewboyson 2:849103b5a16d 51
andrewboyson 2:849103b5a16d 52
andrewboyson 2:849103b5a16d 53 static void dateHeaderFromTm(struct tm* ptm, char* ptext)
andrewboyson 2:849103b5a16d 54 {
andrewboyson 2:849103b5a16d 55 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
andrewboyson 2:849103b5a16d 56 }
andrewboyson 2:849103b5a16d 57 static void dateHeaderFromNow(char* pText)
andrewboyson 2:849103b5a16d 58 {
andrewboyson 2:849103b5a16d 59 struct tm tm;
andrewboyson 2:849103b5a16d 60 TimeToTmUtc(time(NULL), &tm);
andrewboyson 2:849103b5a16d 61 dateHeaderFromTm(&tm, pText);
andrewboyson 2:849103b5a16d 62 }
andrewboyson 2:849103b5a16d 63 static void dateHeaderFromDateTime(const char* date, const char *ptime, char* ptext)
andrewboyson 2:849103b5a16d 64 {
andrewboyson 2:849103b5a16d 65 struct tm tm;
andrewboyson 2:849103b5a16d 66 TimeAsciiDateTimeToTm(date, ptime, &tm);
andrewboyson 2:849103b5a16d 67 dateHeaderFromTm(&tm, ptext);
andrewboyson 2:849103b5a16d 68 }
andrewboyson 2:849103b5a16d 69
andrewboyson 2:849103b5a16d 70
andrewboyson 1:5f70c361db20 71
andrewboyson 2:849103b5a16d 72 static void splitRequest(char* p, char** ppMethod, char** ppPath, char** ppQuery)
andrewboyson 2:849103b5a16d 73 {
andrewboyson 2:849103b5a16d 74 *ppMethod = NULL;
andrewboyson 2:849103b5a16d 75 *ppPath = NULL;
andrewboyson 2:849103b5a16d 76 *ppQuery = NULL;
andrewboyson 2:849103b5a16d 77
andrewboyson 2:849103b5a16d 78 while (*p == ' ') //Move past any leading spaces
andrewboyson 2:849103b5a16d 79 {
andrewboyson 2:849103b5a16d 80 if (*p == 0) return;
andrewboyson 2:849103b5a16d 81 p++;
andrewboyson 2:849103b5a16d 82 }
andrewboyson 2:849103b5a16d 83 *ppMethod = p; //Record the start of the method (GET or POST)
andrewboyson 2:849103b5a16d 84
andrewboyson 2:849103b5a16d 85 while (*p != ' ') //Move past the method
andrewboyson 2:849103b5a16d 86 {
andrewboyson 2:849103b5a16d 87 if (*p == 0) return;
andrewboyson 2:849103b5a16d 88 p++;
andrewboyson 2:849103b5a16d 89 }
andrewboyson 2:849103b5a16d 90 *p = 0; //Terminate the method
andrewboyson 2:849103b5a16d 91 p++; //Start at next character
andrewboyson 2:849103b5a16d 92
andrewboyson 2:849103b5a16d 93 while (*p == ' ') //Move past any spaces
andrewboyson 2:849103b5a16d 94 {
andrewboyson 2:849103b5a16d 95 if (*p == 0) return;
andrewboyson 2:849103b5a16d 96 p++;
andrewboyson 2:849103b5a16d 97 }
andrewboyson 2:849103b5a16d 98 *ppPath = p; //Record the start of the path
andrewboyson 2:849103b5a16d 99
andrewboyson 2:849103b5a16d 100 while (*p != ' ') //Move past the path and query
andrewboyson 2:849103b5a16d 101 {
andrewboyson 2:849103b5a16d 102 if (*p == 0) return;
andrewboyson 2:849103b5a16d 103 if (*p == '?')
andrewboyson 2:849103b5a16d 104 {
andrewboyson 2:849103b5a16d 105 *p = 0; //Terminate the path
andrewboyson 2:849103b5a16d 106 *ppQuery = p + 1; //Record the start of the query
andrewboyson 2:849103b5a16d 107 }
andrewboyson 2:849103b5a16d 108 p++;
andrewboyson 2:849103b5a16d 109 }
andrewboyson 2:849103b5a16d 110 *p = 0; //Terminate the path or query
andrewboyson 2:849103b5a16d 111 }
andrewboyson 2:849103b5a16d 112
andrewboyson 2:849103b5a16d 113 int HttpRequest(int position, int len, char *pData)
andrewboyson 2:849103b5a16d 114 {
andrewboyson 2:849103b5a16d 115 char* pMethod;
andrewboyson 2:849103b5a16d 116 char* pPath;
andrewboyson 2:849103b5a16d 117 char* pQuery;
andrewboyson 2:849103b5a16d 118
andrewboyson 2:849103b5a16d 119 splitRequest(pData, &pMethod, &pPath, &pQuery);
andrewboyson 2:849103b5a16d 120
andrewboyson 2:849103b5a16d 121 int todo = DO_NOT_FOUND;
andrewboyson 2:849103b5a16d 122 if (strcmp(pPath, "/" ) == 0) todo = DO_HTML;
andrewboyson 2:849103b5a16d 123 if (strcmp(pPath, "/favicon.ico") == 0) todo = DO_FAVICON;
andrewboyson 2:849103b5a16d 124 if (strcmp(pPath, "/gps.css" ) == 0) todo = DO_CSS;
andrewboyson 2:849103b5a16d 125
andrewboyson 2:849103b5a16d 126 return todo;
andrewboyson 2:849103b5a16d 127 }
andrewboyson 2:849103b5a16d 128 int sendNotFound(int position, int mss, char* pData)
andrewboyson 1:5f70c361db20 129 {
andrewboyson 2:849103b5a16d 130 printf("Sending 404 Not Found\r\n");
andrewboyson 2:849103b5a16d 131 char *pHttp = "HTTP/1.1 404 Not Found\r\n"
andrewboyson 2:849103b5a16d 132 "\r\n";
andrewboyson 2:849103b5a16d 133 int lenHttp = strlen(pHttp);
andrewboyson 2:849103b5a16d 134 char* p = pData;
andrewboyson 2:849103b5a16d 135 for (int i = position; i < position + mss; i++)
andrewboyson 2:849103b5a16d 136 {
andrewboyson 2:849103b5a16d 137 if (i < lenHttp ) *p++ = pHttp[i];
andrewboyson 2:849103b5a16d 138 else break;
andrewboyson 2:849103b5a16d 139 }
andrewboyson 2:849103b5a16d 140 return p - pData;
andrewboyson 1:5f70c361db20 141 }
andrewboyson 2:849103b5a16d 142 int sendHtml(int position, int mss, char* pData)
andrewboyson 1:5f70c361db20 143 {
andrewboyson 2:849103b5a16d 144 const char *pA = "HTTP/1.1 200 OK\r\n"
andrewboyson 2:849103b5a16d 145 "Content-Type: text/html; charset=UTF-8\r\n"
andrewboyson 2:849103b5a16d 146 "Connection: close\r\n"
andrewboyson 2:849103b5a16d 147 "Cache-control: no-cache\r\n"
andrewboyson 2:849103b5a16d 148 "Date: ";
andrewboyson 2:849103b5a16d 149
andrewboyson 2:849103b5a16d 150 char pB[HTTP_DATE_LENGTH];
andrewboyson 2:849103b5a16d 151 dateHeaderFromNow(pB);
andrewboyson 2:849103b5a16d 152
andrewboyson 2:849103b5a16d 153 const char* pC = "\r\n"
andrewboyson 2:849103b5a16d 154 "\r\n"
andrewboyson 2:849103b5a16d 155 "<html>\r\n"
andrewboyson 2:849103b5a16d 156 "<head>\r\n"
andrewboyson 2:849103b5a16d 157 " <meta name='viewport' content='width=device-width, initial-scale=1'>\r\n"
andrewboyson 2:849103b5a16d 158 " <link rel='icon' href='/favicon.ico' type='image/x-icon'/>\r\n"
andrewboyson 2:849103b5a16d 159 " <link rel='stylesheet' href='/gps.css' type='text/css' />\r\n"
andrewboyson 2:849103b5a16d 160 " <title>GPS Clock</title>\r\n"
andrewboyson 2:849103b5a16d 161 "</head>\r\n"
andrewboyson 2:849103b5a16d 162 "<body>\r\n";
andrewboyson 2:849103b5a16d 163
andrewboyson 2:849103b5a16d 164 char pD[400];
andrewboyson 2:849103b5a16d 165 addNav(pD, HOME_PAGE);
andrewboyson 2:849103b5a16d 166
andrewboyson 2:849103b5a16d 167 const char* pE = "\r\n"
andrewboyson 2:849103b5a16d 168 "<h1>GPS Clock</h1>\r\n"
andrewboyson 2:849103b5a16d 169 "<h2>ARP</h2>\r\n"
andrewboyson 2:849103b5a16d 170 "<code>";
andrewboyson 2:849103b5a16d 171
andrewboyson 2:849103b5a16d 172 char pF[400];
andrewboyson 2:849103b5a16d 173 ArpAsString(400, pF);
andrewboyson 2:849103b5a16d 174
andrewboyson 2:849103b5a16d 175 const char* pG = "</code>\r\n"
andrewboyson 2:849103b5a16d 176 "</body>\r\n"
andrewboyson 2:849103b5a16d 177 "</html>\r\n";
andrewboyson 2:849103b5a16d 178
andrewboyson 2:849103b5a16d 179 int lA = strlen(pA);
andrewboyson 2:849103b5a16d 180 int lB = lA + HTTP_DATE_LENGTH;
andrewboyson 2:849103b5a16d 181 int lC = lB + strlen(pC);
andrewboyson 2:849103b5a16d 182 int lD = lC + strlen(pD);
andrewboyson 2:849103b5a16d 183 int lE = lD + strlen(pE);
andrewboyson 2:849103b5a16d 184 int lF = lE + strlen(pF);
andrewboyson 2:849103b5a16d 185 int lG = lF + strlen(pG);
andrewboyson 2:849103b5a16d 186
andrewboyson 2:849103b5a16d 187 char* p = pData;
andrewboyson 2:849103b5a16d 188 for (int i = position; i < position + mss; i++)
andrewboyson 2:849103b5a16d 189 {
andrewboyson 2:849103b5a16d 190 if (i < lA) *p++ = pA[i];
andrewboyson 2:849103b5a16d 191 else if (i < lB) *p++ = pB[i - lA];
andrewboyson 2:849103b5a16d 192 else if (i < lC) *p++ = pC[i - lB];
andrewboyson 2:849103b5a16d 193 else if (i < lD) *p++ = pD[i - lC];
andrewboyson 2:849103b5a16d 194 else if (i < lE) *p++ = pE[i - lD];
andrewboyson 2:849103b5a16d 195 else if (i < lF) *p++ = pF[i - lE];
andrewboyson 2:849103b5a16d 196 else if (i < lG) *p++ = pG[i - lF];
andrewboyson 2:849103b5a16d 197 else break;
andrewboyson 2:849103b5a16d 198 }
andrewboyson 2:849103b5a16d 199 return p - pData;
andrewboyson 2:849103b5a16d 200 }
andrewboyson 2:849103b5a16d 201 int sendCss(int position, int mss, char* pData)
andrewboyson 2:849103b5a16d 202 {
andrewboyson 2:849103b5a16d 203 const char *pA = "HTTP/1.1 200 OK\r\n"
andrewboyson 2:849103b5a16d 204 "Content-Type: text/css; charset=UTF-8\r\n"
andrewboyson 2:849103b5a16d 205 "Connection: close\r\n"
andrewboyson 2:849103b5a16d 206 "Cache-Control: max-age=3600\r\n"
andrewboyson 2:849103b5a16d 207 "Date: ";
andrewboyson 2:849103b5a16d 208
andrewboyson 2:849103b5a16d 209 char pB[HTTP_DATE_LENGTH];
andrewboyson 2:849103b5a16d 210 dateHeaderFromNow(pB);
andrewboyson 2:849103b5a16d 211
andrewboyson 2:849103b5a16d 212 const char *pC = "\r\n"
andrewboyson 2:849103b5a16d 213 "Last-Modified: ";
andrewboyson 2:849103b5a16d 214
andrewboyson 2:849103b5a16d 215 char pD[HTTP_DATE_LENGTH];
andrewboyson 2:849103b5a16d 216 dateHeaderFromDateTime(CssDate, CssTime, pD);
andrewboyson 1:5f70c361db20 217
andrewboyson 2:849103b5a16d 218 const char *pE = "\r\n\r\n";
andrewboyson 2:849103b5a16d 219
andrewboyson 2:849103b5a16d 220 const char *pF = Css;
andrewboyson 2:849103b5a16d 221
andrewboyson 2:849103b5a16d 222 int lA = strlen(pA);
andrewboyson 2:849103b5a16d 223 int lB = lA + HTTP_DATE_LENGTH;
andrewboyson 2:849103b5a16d 224 int lC = lB + strlen(pC);
andrewboyson 2:849103b5a16d 225 int lD = lC + HTTP_DATE_LENGTH;
andrewboyson 2:849103b5a16d 226 int lE = lD + strlen(pE);
andrewboyson 2:849103b5a16d 227 int lF = lE + strlen(pF);
andrewboyson 2:849103b5a16d 228
andrewboyson 2:849103b5a16d 229 char* p = pData;
andrewboyson 2:849103b5a16d 230 for (int i = position; i < position + mss; i++)
andrewboyson 2:849103b5a16d 231 {
andrewboyson 2:849103b5a16d 232 if (i < lA) *p++ = pA[i];
andrewboyson 2:849103b5a16d 233 else if (i < lB) *p++ = pB[i - lA];
andrewboyson 2:849103b5a16d 234 else if (i < lC) *p++ = pC[i - lB];
andrewboyson 2:849103b5a16d 235 else if (i < lD) *p++ = pD[i - lC];
andrewboyson 2:849103b5a16d 236 else if (i < lE) *p++ = pE[i - lD];
andrewboyson 2:849103b5a16d 237 else if (i < lF) *p++ = pF[i - lE];
andrewboyson 2:849103b5a16d 238 else break;
andrewboyson 2:849103b5a16d 239 }
andrewboyson 2:849103b5a16d 240 return p - pData;
andrewboyson 1:5f70c361db20 241 }
andrewboyson 2:849103b5a16d 242 int sendFavicon(int position, int mss, char* pData)
andrewboyson 2:849103b5a16d 243 {
andrewboyson 2:849103b5a16d 244 const char* pA = "HTTP/1.1 200 OK\r\n"
andrewboyson 2:849103b5a16d 245 "Content-Type: image/x-icon\r\n"
andrewboyson 2:849103b5a16d 246 "Connection: close\r\n"
andrewboyson 2:849103b5a16d 247 "Cache-Control: max-age=3600\r\n"
andrewboyson 2:849103b5a16d 248 "Date: ";
andrewboyson 2:849103b5a16d 249
andrewboyson 2:849103b5a16d 250 char pB[HTTP_DATE_LENGTH];
andrewboyson 2:849103b5a16d 251 dateHeaderFromNow(pB);
andrewboyson 2:849103b5a16d 252
andrewboyson 2:849103b5a16d 253 const char *pC = "\r\n"
andrewboyson 2:849103b5a16d 254 "Last-Modified: ";
andrewboyson 2:849103b5a16d 255
andrewboyson 2:849103b5a16d 256 char pD[HTTP_DATE_LENGTH];
andrewboyson 2:849103b5a16d 257 dateHeaderFromDateTime(FaviconDate, FaviconTime, pD);
andrewboyson 2:849103b5a16d 258
andrewboyson 2:849103b5a16d 259 const char *pE = "\r\n\r\n";
andrewboyson 2:849103b5a16d 260
andrewboyson 2:849103b5a16d 261 const char *pF = Favicon;
andrewboyson 2:849103b5a16d 262
andrewboyson 2:849103b5a16d 263 int lA = strlen(pA);
andrewboyson 2:849103b5a16d 264 int lB = lA + HTTP_DATE_LENGTH;
andrewboyson 2:849103b5a16d 265 int lC = lB + strlen(pC);
andrewboyson 2:849103b5a16d 266 int lD = lC + HTTP_DATE_LENGTH;
andrewboyson 2:849103b5a16d 267 int lE = lD + strlen(pE);
andrewboyson 2:849103b5a16d 268 int lF = lE + FaviconSize;
andrewboyson 2:849103b5a16d 269
andrewboyson 2:849103b5a16d 270 char* p = pData;
andrewboyson 2:849103b5a16d 271 for (int i = position; i < position + mss; i++)
andrewboyson 2:849103b5a16d 272 {
andrewboyson 2:849103b5a16d 273 if (i < lA) *p++ = pA[i];
andrewboyson 2:849103b5a16d 274 else if (i < lB) *p++ = pB[i - lA];
andrewboyson 2:849103b5a16d 275 else if (i < lC) *p++ = pC[i - lB];
andrewboyson 2:849103b5a16d 276 else if (i < lD) *p++ = pD[i - lC];
andrewboyson 2:849103b5a16d 277 else if (i < lE) *p++ = pE[i - lD];
andrewboyson 2:849103b5a16d 278 else if (i < lF) *p++ = pF[i - lE];
andrewboyson 2:849103b5a16d 279 else break;
andrewboyson 2:849103b5a16d 280 }
andrewboyson 2:849103b5a16d 281 return p - pData;
andrewboyson 2:849103b5a16d 282 }
andrewboyson 2:849103b5a16d 283 int HttpResponse(int position, int mss, char *pData, int todo)
andrewboyson 2:849103b5a16d 284 {
andrewboyson 2:849103b5a16d 285 switch (todo)
andrewboyson 2:849103b5a16d 286 {
andrewboyson 2:849103b5a16d 287 case DO_NOT_FOUND: return sendNotFound(position, mss, pData);
andrewboyson 2:849103b5a16d 288 case DO_HTML: return sendHtml (position, mss, pData);
andrewboyson 2:849103b5a16d 289 case DO_CSS: return sendCss (position, mss, pData);
andrewboyson 2:849103b5a16d 290 case DO_FAVICON: return sendFavicon (position, mss, pData);
andrewboyson 2:849103b5a16d 291 }
andrewboyson 2:849103b5a16d 292 return 0;
andrewboyson 2:849103b5a16d 293 }