![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Backing up an unused program in case of future need
Diff: server.cpp
- Revision:
- 1:94282484baae
- Parent:
- 0:09f915e6f9f6
- Child:
- 2:06fa34661f19
--- a/server.cpp Wed Apr 13 09:21:02 2016 +0000 +++ b/server.cpp Fri Apr 15 09:03:54 2016 +0000 @@ -4,11 +4,20 @@ #include "log.h" #include "time.h" #include "wifi.h" -#define BUFFER_SIZE 1024 +#define RECV_BUFFER_SIZE 1024 +#define SEND_BUFFER_SIZE 256 #define SERVER_PORT 80 -static char recvbuffer[BUFFER_SIZE]; -static char sendbuffer[BUFFER_SIZE]; +static char recvbuffer[RECV_BUFFER_SIZE]; +static char sendbuffer[SEND_BUFFER_SIZE]; + +#define WHAT_NOT_FOUND 0 +#define WHAT_BAD_REQUEST 1 +#define WHAT_BAD_METHOD 2 +#define WHAT_LED 3 +#define WHAT_LOG 4 +static int whatToSendToId[4]; +static int lineToSendToId[4]; //0 == do nothing; -1 == close void ServerInit(void) //Make sure this is only called after any other ids are reserved. { @@ -17,84 +26,299 @@ if (!EspIpdReserved[id]) { EspIpdBuffer[id] = recvbuffer; - EspIpdBufferLen[id] = BUFFER_SIZE; + EspIpdBufferLen[id] = RECV_BUFFER_SIZE; + } + whatToSendToId[id] = 0; + lineToSendToId[id] = 0; + } +} + +static int addChunk(int prevlen, char *text) +{ + strncpy(sendbuffer + prevlen, text, SEND_BUFFER_SIZE - prevlen); + int len = prevlen + strlen(text); + return len < SEND_BUFFER_SIZE ? len : SEND_BUFFER_SIZE; +} +static int fillChunk(char * text) +{ + strncpy(sendbuffer, text, SEND_BUFFER_SIZE); + int len = strlen(text); + return len < SEND_BUFFER_SIZE ? len : SEND_BUFFER_SIZE; +} +static int fillNotFound(int id) +{ + int len = fillChunk("HTTP/1.0 404 Not Found\r\n\r\n"); + lineToSendToId[id] = -1; + return len; +} +static int fillBadRequest(int id) +{ + int len = fillChunk("HTTP/1.0 400 Bad Request\r\n\r\n"); + lineToSendToId[id] = -1; + return len; +} +static int fillBadMethod(int id) +{ + int len = fillChunk("HTTP/1.0 405 Method Not Allowed\r\nAllow: GET\r\n\r\n"); + lineToSendToId[id] = -1; + return len; +} +static int fillLogChunk() //Returns length. If length is less than the buffer size then that was the last chunk to send: that could mean a length of zero. +{ + static int enumerationStarted = false; + if (!enumerationStarted) + { + LogEnumerateStart(); + enumerationStarted = true; + } + char* p = sendbuffer; + while (p < sendbuffer + SEND_BUFFER_SIZE) + { + int c = LogEnumerate(); + if (c == EOF) + { + enumerationStarted = false; + break; } + *p++ = c; + } + return p - sendbuffer; +} +static char* header = + "HTTP/1.0 200 OK\r\n" + "Content-Type: text/html; charset=ISO-8859-1\r\n" + "\r\n" + "<!DOCTYPE html>\r\n" + "<html>\r\n" + "<head>\r\n" + "<title>IoT mbed</title>\r\n" + "</head>\r\n" + "<body>\r\n"; + +static int fillLog(int id) +{ + int len = 0; + + switch (lineToSendToId[id]) + { + case 1: len = fillChunk(header); lineToSendToId[id] += 1; break; + case 2: len = fillChunk("<code><pre>"); lineToSendToId[id] += 1; break; + case 3: len = fillLogChunk(); if (len < SEND_BUFFER_SIZE) lineToSendToId[id] += 1; break; //only increments after the last chunk + case 4: len = fillChunk( + "</pre></code>\r\n" + "</body>\r\n" + "</html>\r\n"); + lineToSendToId[id] = -1; + break; + } + return len; +} + +static int fillLed(int id) +{ + int len; + switch (lineToSendToId[id]) + { + case 1: + len = fillChunk(header); + lineToSendToId[id] += 1; + break; + case 2: + len = fillChunk( + "<form action='/' method='get'>\r\n" + "<input type='hidden' name='ledonoff'>\r\n"); + lineToSendToId[id] += 1; + break; + case 3: + len = fillChunk("Led <input type='checkbox' name='led' value='on'"); + if (Led1) len = addChunk(len, " checked='checked'"); + len = addChunk(len, ">\r\n"); + lineToSendToId[id] += 1; + break; + case 4: + len = fillChunk( + "<input type='submit' value='Set'><br/>\r\n" + "</form>\r\n" + "</body>\r\n" + "</html>\r\n"); + lineToSendToId[id] = -1; + break; + } + return len; +} +static int fillSendBuffer(int id) +{ + switch(whatToSendToId[id]) + { + case WHAT_NOT_FOUND: return fillNotFound(id); + case WHAT_BAD_REQUEST: return fillBadRequest(id); + case WHAT_BAD_METHOD: return fillBadMethod(id); + case WHAT_LOG: return fillLog(id); + case WHAT_LED: return fillLed(id); + default: + LogF("No such 'whatToSendToId' %s", whatToSendToId[id]); + return -1; } } -int ServerStatus = AT_NONE; -int ServerMain(void) +static int splitRequest(char** ppMethod, char** ppPath, char** ppQuery, int *pLenMethod, int *pLenPath, int *pLenQuery) //returns 1 if malformed request; 0 if ok { + char* p = recvbuffer; + char* pE = recvbuffer + RECV_BUFFER_SIZE; + + *ppMethod = NULL; + *ppPath = NULL; + *ppQuery = NULL; + *pLenMethod = 0; + *pLenPath = 0; + *pLenQuery = 0; - if (!AtBusy() && WifiStarted() && ServerStatus != AT_SUCCESS) AtStartServer(SERVER_PORT, &ServerStatus); - - static int needToSendId = -1; - static int needToCloseId = -1; + while (*p == ' ') //Loop to non space + { + if (p == pE) return -1; + if (*p < ' ') return -1; + if (*p >= 0x7f) return -1; + p++; + } + *ppMethod = p; //Record the start of the method GET or POST + + while (*p != ' ') //Loop to a space + { + if (p == pE) return -1; + if (*p < ' ') return -1; + if (*p >= 0x7f) return -1; + p++; + } + *pLenMethod = p - *ppMethod; //Record the length of the method GET or POST - if (EspDataAvailable == ESP_AVAILABLE && !EspIpdReserved[EspIpdId]) + + while (*p == ' ') //Loop to non space + { + if (p == pE) return -1; + if (*p < ' ') return -1; + if (*p >= 0x7f) return -1; + p++; + } + *ppPath = p; //Record the start of the file part of the url + + while (*p != ' ') //Loop to space + { + if (p == pE) return -1; + if (*p < ' ') return -1; + if (*p >= 0x7f) return -1; + if (*p == '?') *ppQuery = p + 1; + p++; + } + + if (*ppQuery) //Calulate length of the file and query parts { - needToSendId = EspIpdId; - char method[10]; - char url[20]; - char file[20]; - char query[20]; - sscanf(recvbuffer, "%s %s ", method, url); - sscanf(url, "%[^?]?%s", file, query); - if (strcmp(file, "/favicon.ico") == 0) - strcpy(sendbuffer, "HTTP/1.0 404 Not Found\r\n\r\n"); - else if (strcmp(file, "/log") == 0) + *pLenPath = *ppQuery - *ppPath - 1; + *pLenQuery = p - *ppQuery; + } + else + { + *pLenPath = p - *ppPath; + *pLenQuery = 0; + } + + return 0; +} +int compare(char* mem, int len, char* str) //Returns true if same and false if not +{ + if (strlen(str) != len) return false; + if (memcmp(mem, str, len)) return false; + return true; +} +static int recvMain() +{ + //Wait for data to be available oneshot + if (EspDataAvailable != ESP_AVAILABLE) return 0; + + //Ignore ids that have been reserved elsewhere (ie NTP) + if (EspIpdReserved[EspIpdId]) return 0; + + //Set up the next line to send to be the first + lineToSendToId[EspIpdId] = 1; + + char* pMethod; + char* pPath; + char* pQuery; + int lenMethod; + int lenQuery; + int lenPath; + int r = splitRequest(&pMethod, &pPath, &pQuery, &lenMethod, &lenPath, &lenQuery); + if (r) + { + whatToSendToId[EspIpdId] = WHAT_BAD_REQUEST; + return 0; + } + + if (!compare(pMethod, lenMethod, "GET")) + { + whatToSendToId[EspIpdId] = WHAT_BAD_METHOD; + return 0; + } + + if (compare(pPath, lenPath, "/")) + { + if (pQuery) { - strcpy(sendbuffer, "HTTP/1.0 200 OK\r\n"); - strcat(sendbuffer, "\r\n"); - strcat(sendbuffer, "<html>\r\n"); - strcat(sendbuffer, "<body>\r\n"); - strcat(sendbuffer, "<code><pre>"); - LogEnumerateStart(); - char* p = sendbuffer; - while(*p) p++; //Move to the end of string - while (1) - { - int c = LogEnumerate(); - if (c == EOF) break; - *p++ = c; - } - *p = 0; //Add back the end of string - strcat(sendbuffer, "</pre></code>"); - strcat(sendbuffer, "</body>\r\n"); - strcat(sendbuffer, "</html>\r\n"); + if (compare(pQuery, lenQuery, "ledonoff=&led=on")) Led1 = 1; + if (compare(pQuery, lenQuery, "ledonoff=" )) Led1 = 0; } - else + whatToSendToId[EspIpdId] = WHAT_LED; + return 0; + } + + if (compare(pPath, lenPath, "/log")) + { + whatToSendToId[EspIpdId] = WHAT_LOG; + return 0; + } + + whatToSendToId[EspIpdId] = WHAT_NOT_FOUND; + return 0; +} +static int sendMain() +{ + //Do nothing if a command is already in progress + if (AtBusy()) return 0; + + //Send data. Do each id in turn to avoid interleaved calls to fillers like LogEnumerate which are not reentrant. + for(int id = 0; id < 4; id++) + { + if (lineToSendToId[id] > 0) { - if (strcmp(query, "ledonoff=&led=on") == 0) Led1 = 1; - if (strcmp(query, "ledonoff=" ) == 0) Led1 = 0; - strcpy(sendbuffer, "HTTP/1.0 200 OK\r\n"); - strcat(sendbuffer, "\r\n"); - strcat(sendbuffer, "<html>\r\n"); - strcat(sendbuffer, "<body>\r\n"); - strcat(sendbuffer, "<form action='/' method='get'>\r\n"); - strcat(sendbuffer, "<input type='hidden' name='ledonoff'>\r\n"); - if (Led1) strcat(sendbuffer, "Led <input type='checkbox' name='led' value='on' checked='checked'>\r\n"); - else strcat(sendbuffer, "Led <input type='checkbox' name='led' value='on'>\r\n"); - strcat(sendbuffer, "<input type='submit' value='Set'><br/>\r\n"); - strcat(sendbuffer, "</form>\r\n"); - strcat(sendbuffer, "</body>\r\n"); - strcat(sendbuffer, "</html>\r\n"); -// sprintf(sendbuffer, "Received a %s request for %s and query %s\r\n", method, file, query); + int length = fillSendBuffer(id); + if (length < 0) return -1; + if (length > 0) AtSendData(id, length, sendbuffer, NULL); + } + else if (lineToSendToId[id] < 0) + { + AtClose(id, NULL); + lineToSendToId[id] = 0; } } - if (!AtBusy() && needToSendId >= 0) - { - AtSendData(needToSendId, strlen(sendbuffer), sendbuffer, NULL); - needToCloseId = needToSendId; - needToSendId = -1; - } + return 0; +} +int startMain() +{ + //Do nothing if a command is already in progress + if (AtBusy()) return 0; + + //Do nothing until WiFi is running + if (!WifiStarted()) return 0; - if (!AtBusy() && needToCloseId >= 0) - { - AtClose(needToCloseId, NULL); - needToCloseId = -1; - } - + //Start the server if not started + static int startServerReply = AT_NONE; + if (startServerReply != AT_SUCCESS) AtStartServer(SERVER_PORT, &startServerReply); + return 0; +} +int ServerMain() +{ + if (startMain()) return -1; + if ( recvMain()) return -1; + if ( sendMain()) return -1; return 0; } \ No newline at end of file