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.
Fork of SW_HTTPServer by
Diff: SW_HTTPServer.cpp
- Revision:
- 8:262583f054f6
- Parent:
- 7:99ad7a67f05e
- Child:
- 9:2ea342765c9d
--- a/SW_HTTPServer.cpp Thu Jun 27 17:08:25 2013 +0000 +++ b/SW_HTTPServer.cpp Mon Jul 01 04:36:54 2013 +0000 @@ -14,17 +14,17 @@ #include "SW_HTTPServer.h" #include "Utility.h" -#define DEBUG +//#define DEBUG const char * DEFAULT_FILENAME = "index.htm"; -// Header information to always send -const char hdr_httpver[] = "HTTP/1.1"; // typically HTTP/1.0 or HTTP/1.1 -const char hdr_age[] = "Max-age: 0\r\n"; // expires right away (must be \r\n terminated) -const char hdr_server[] = "Server: Smart_Server v0.1\r\n"; // Server (must be \r\n terminated) -const char hdr_dnt[] = "DNT: 1\r\n"; // Do Not Track -const char hdr_close[] = "Connection: close\r\n"; // tell the client to close the connection (must be \r\n terminated) -const char nl[] = "\r\n"; // final \r\n for the termination of the header +// Header information to always send (must be \r\n terminated) +const char hdr_httpver[] = "HTTP/1.0"; // typically HTTP/1.0 or HTTP/1.1 +const char hdr_age[] = "Max-age: 0\r\n"; // expires right away +const char hdr_server[] = "Server: Smart_Server v0.1\r\n"; // Server +const char hdr_dnt[] = "DNT: 1\r\n"; // Do Not Track +const char hdr_close[] = "Connection: close\r\n"; // tell the client to close the connection +const char nl[] = "\r\n"; // final \r\n for the termination of the header static const struct { char *ext; @@ -45,6 +45,21 @@ {0,0} }; +#ifdef DEBUG +static void * MyMalloc(int x, int y) +{ + std::printf("[%04d] malloc(%d)\r\n", y, x); + return malloc(x); +} +#define mymalloc(x) MyMalloc(x, __LINE__) +#define myfree(x) \ + pc->printf("[%04d] free(%02x %02x %02x %02x ...\r\n", __LINE__, *x, *(x+1), *(x+2), *(x+3)); \ + free(x); +#else +#define mymalloc(x) malloc(x) +#define myfree(x) free(x) +#endif + HTTPServer::HTTPServer( Wifly * _wf, int port, @@ -77,16 +92,23 @@ server = new TCPSocketServer(); server->bind(port); server->listen(); - server->set_blocking(false, 0); - client.set_blocking(false, 0); - server->accept(client); +// server->set_blocking(false, 0); +// client.set_blocking(false, 0); +// server->accept(client); ResetPerformanceData(); timer.start(); } HTTPServer::~HTTPServer() { - free(webroot); + int i; + + for (i=0; i<handlercount; i++) + myfree(handlers[i].path); + myfree(headerbuffer); + myfree(handlers); + myfree(params); + myfree(webroot); webroot = NULL; } @@ -98,7 +120,7 @@ bool HTTPServer::RegisterHandler(const char * path, Handler callback) { if (handlercount < maxdynamicpages && path && callback) { - handlers[handlercount].path = (char *)malloc(strlen(path)+1); + handlers[handlercount].path = (char *)mymalloc(strlen(path)+1); memcpy(handlers[handlercount].path, path, strlen(path)+1); handlers[handlercount].callback = callback; handlercount++; @@ -128,33 +150,39 @@ Reset } state; static state op = Idle; - static state lastOp = Reset; static char * bPtr = headerbuffer; int n; static int t_ref; // reference point for the timer - #ifdef DEBUG +#ifdef DEBUG + static state lastOp = Reset; if (lastOp != op) { - pc->printf("%d", op); + char *states[] = {"Idle", "Receiving", "Sending", "WaitingToClose", "Reset"}; + pc->printf("Poll: %s\r\n", states[op]); lastOp = op; } - #endif +#endif switch(op) { default: // not expected to arrive here op = Idle; break; + case Idle: timer.reset(); bPtr = headerbuffer; - if (0 == client.receive(bPtr, 0)) { // server->accept(client) == 0) { + if (0 == server->accept(client)) { // client.receive(bPtr, 0)) { // server->accept(client) == 0) { op = Receiving; t_ref = timer.read_us(); +#ifdef DEBUG + pc->printf("Accept at %d\r\n", t_ref); +#endif } break; + case Receiving: n = client.receive(bPtr, headerbuffersize - (bPtr - headerbuffer)); if (n < 0) { - ; // pc->printf("*** client.receive error: %d\r\n", n); + pc->printf("*** client.receive() => %d\r\n", n); } else if (n) { bPtr[n] = '\0'; if (ParseHeader(headerbuffer)) { @@ -164,6 +192,7 @@ bPtr += n; } break; + case Sending: SendResponse(); op = WaitingToClose; @@ -207,7 +236,7 @@ fp = fopen(filename,"rb"); if (fp) { // can open it - char *fbuffer = (char *)malloc(FILESEND_BUF_SIZE); + char *fbuffer = (char *)mymalloc(FILESEND_BUF_SIZE); int bytes; if (fbuffer) { @@ -217,7 +246,7 @@ send(fbuffer, bytes); bytes = fread(fbuffer,sizeof(char),FILESEND_BUF_SIZE,fp); } - free(fbuffer); + myfree(fbuffer); } else { header(500, "Server Error", "Pragma: err - insufficient memory\r\n"); } @@ -383,19 +412,23 @@ char * get = strstr(haystack, needle); // what if not at the front? if (get) { // Seems to be a valid "...GET /QueryString HTTP/1.1" + // or "...<needle>param..." qs = get + strlen(needle); // in case the needle didn't have space delimiters while (*qs == ' ') qs++; // /QueryString\0HTTP/1.1\0\0 if (*string) // recycle old string when working a new one - free(*string); - container = (char *)malloc(strlen(qs)); + myfree(*string); + container = (char *)mymalloc(strlen(qs)); if (container) { strcpy(container, qs); eqs = strchr(container, ' '); if (eqs) *eqs = '\0'; *string = container; +#ifdef DEBUG + pc->printf("Extract(%s) = %s\r\n", needle, container); +#endif ret = true; } else { *string = NULL; // something bad happened... no memory @@ -406,13 +439,13 @@ char * HTTPServer::rewriteWithDefaultFile(char * queryString) { - char * temp = (char *)malloc(strlen(queryString) + strlen(DEFAULT_FILENAME) + 1); + char * temp = (char *)mymalloc(strlen(queryString) + strlen(DEFAULT_FILENAME) + 1); if (temp) { *temp = '\0'; strcpy(temp, queryString); strcat(temp, DEFAULT_FILENAME); - free(queryString); + myfree(queryString); return temp; } else { return queryString; @@ -421,7 +454,7 @@ char * HTTPServer::rewritePrependWebroot(char * queryString) { - char * temp = (char *)malloc(strlen(webroot) + strlen(queryString) + 1); + char * temp = (char *)mymalloc(strlen(webroot) + strlen(queryString) + 1); if (temp) { *temp = '\0'; @@ -429,7 +462,7 @@ if (temp[strlen(temp)-1] == '/' && *queryString == '/') temp[strlen(temp)-1] = '\0'; strcat(temp, queryString); - free(queryString); + myfree(queryString); return temp; } else { return queryString; @@ -453,10 +486,16 @@ void HTTPServer::SendResponse() { +#ifdef DEBUG + pc->printf("SendResponse(%s) [%d]\r\n", queryType, __LINE__); +#endif if (strcmp(queryType, "GET") == 0 || strcmp(queryType, "POST") == 0) { if (!(queryString[0] == '.' && queryString[1] == '.')) { const char * fType; +#ifdef DEBUG + pc->printf(" SendResponse() [%d]\r\n", __LINE__); +#endif if (!CheckDynamicHandlers()) { // Otherwise, this queryString must be trying to reference a static file if (queryString[strlen(queryString)-1] == '/') { @@ -481,27 +520,27 @@ header(400, "Bad Request", "Pragma: err - Unsupported query type\r\n"); } if (queryType) { - free(queryType); + myfree(queryType); queryType = NULL; } if (queryString) { - free(queryString); + myfree(queryString); queryString = NULL; } if (hostString) { - free(hostString); + myfree(hostString); hostString = NULL; } if (contentLength) { - free(contentLength); + myfree(contentLength); contentLength = NULL; } if (contentType) { - free(contentType); + myfree(contentType); contentType = NULL; } if (postQueryString) { - free(postQueryString); + myfree(postQueryString); postQueryString = NULL; } } @@ -517,15 +556,13 @@ // when it is done. wifly->setConnectionState(true); // Buffer could have partial, but the double \r\n is the key - // *OPEN*QueryType QueryString HTTP/1.1.... - // QueryType:= GET - // *OPEN*GET /QueryString HTTP/1.1\r\n - // *OPEN*GET /QueryString HTTP/1.1\r\nHeader stuf - // *OPEN*GET /QueryString HTTP/1.1\r\nHeader stuff...\r\n\r\n + // GET /QueryString HTTP/1.1\r\n + // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Con + // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n dblCR = strstr(buffer,"\r\n\r\n"); if (dblCR) { // Have to scan from the beginning in case split on \r -#if 0 - pc->printf("\r\n\r\nThe Header:\r\n%s\r\n\r\n", buffer); +#ifdef DEBUG + pc->printf("==\r\n%s==\r\n", buffer); #endif char * soRec = buffer; // start of the next record of text char * eoRec = strchr(soRec, '\n'); // search for end of a record @@ -537,10 +574,24 @@ *eoRec = '\0'; if (*(eoRec-1) == '\r') *(eoRec-1) = '\0'; - if (!Extract(soRec, "*OPEN*", &queryType)) - Extract(soRec, "*CLOS*", &queryType); - if (queryType) - Extract(soRec, queryType, &queryString); + #ifdef DEBUG + pc->printf("rec {%s}\r\n", soRec); + #endif + // Inspect the supported query types (GET, POST) and ignore (HEAD, PUT, OPTION, DELETE, TRACE, CONNECT] + // This is very clumsy + if (strstr(soRec, "GET ") == soRec) { + Extract(soRec, "GET", &queryString); + if (queryString) { + queryType = (char *)mymalloc(strlen("GET")+1); + strcpy(queryType, "GET"); + } + } else if (strstr(soRec, "POST ") == soRec) { + Extract(soRec, "POST", &queryString); + if (queryString) { + queryType = (char *)mymalloc(strlen("POST")+1); + strcpy(queryType, "POST"); + } + } Extract(soRec, "Host: ", &hostString); Extract(soRec, "Content-Length: ", &contentLength); Extract(soRec, "Content-Type: ", &contentType); @@ -549,7 +600,9 @@ } if (queryString) { // We have enough to try to reply - //pc->printf("create reply queryType{%s}, queryString{%s}\r\n", queryType, queryString); + #ifdef DEBUG + pc->printf("create reply queryType{%s}, queryString{%s}\r\n", "GET", queryString); + #endif // parse params - if any // /file.htm?name1=value1&name2=value2... // /file.htm?name1&name2=value2... @@ -563,7 +616,7 @@ //for (int i=0; i<paramcount; i++) // pc->printf("param %d '%s'='%s'\r\n", i, params[i].name, params[i].value); } else { - pc->printf("not found\r\n"); + pc->printf("ERROR: queryString not found\r\n"); } advanceState = true; buffer[0] = 0; @@ -593,7 +646,7 @@ if (regHandled && acceptIt) { // If so, we'll make space for it - postQueryString = (char *)malloc(postBytes + 1); + postQueryString = (char *)mymalloc(postBytes + 1); if (postQueryString) { char * offset; int len; @@ -618,7 +671,7 @@ } else { // Simply copy it to the bitbucket int bytesToDump = postBytes; - char * bitbucket = (char *)malloc(201); + char * bitbucket = (char *)mymalloc(201); dblCR += 4; while (*dblCR && *dblCR <= ' ') dblCR++; @@ -628,7 +681,7 @@ n = client.receive(bitbucket, n); bytesToDump -= n; } - free(bitbucket); + myfree(bitbucket); } } }