Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 1:94282484baae, committed 2016-04-15
- Comitter:
- andrewboyson
- Date:
- Fri Apr 15 09:03:54 2016 +0000
- Parent:
- 0:09f915e6f9f6
- Child:
- 2:06fa34661f19
- Commit message:
- Streamed the log in chunks to allow the send buffer to be reduced. That in turn allowed the log buffer to be increased.; Added content type text/html to http responses.
Changed in this revision
--- a/at.cpp Wed Apr 13 09:21:02 2016 +0000
+++ b/at.cpp Fri Apr 15 09:03:54 2016 +0000
@@ -185,6 +185,7 @@
LogCrLf("Esp timed out");
break;
case ESP_OVERFLOW:
+ if (wait_for == WAIT_FOR_ESP_READY) break; //Ignore overflows from the esp's 450 byte boot message
finishAndReset(AT_LINE_OVERFLOW);
LogCrLf("Esp buffer overflow");
break;
--- a/log.cpp Wed Apr 13 09:21:02 2016 +0000
+++ b/log.cpp Fri Apr 15 09:03:54 2016 +0000
@@ -6,7 +6,7 @@
LocalFileSystem local("local");
-#define BUFFER_LENGTH 512
+#define BUFFER_LENGTH 2048
static char buffer[BUFFER_LENGTH];
static char* pPush; //Initialised in init
static char* pPull; //Initialised in init
--- 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
--- a/wifi.cpp Wed Apr 13 09:21:02 2016 +0000
+++ b/wifi.cpp Fri Apr 15 09:03:54 2016 +0000
@@ -142,7 +142,6 @@
}
break;
case AM_STARTED:
- LogEnable(false);
return 0;
default:
LogF("Unknown \'am\' %d", am);