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:
- 33:ef165a67ab22
- Parent:
- 32:7ded9bacb546
- Child:
- 34:019212c05980
--- a/SW_HTTPServer.cpp Mon Dec 30 23:03:37 2013 +0000 +++ b/SW_HTTPServer.cpp Fri Jan 03 19:12:22 2014 +0000 @@ -12,12 +12,27 @@ // #include "mbed.h" +#define DEBUG "HTTP" +#include "Utility.h" + #include "SW_HTTPServer.h" // define DEBUG before this -#define DEBUG "httpd" -#include "Utility.h" +#if 0 +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define DBG(x, ...) pc->printf("[DBG %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) pc->printf("[WRN %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) pc->printf("[ERR %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define INFO(x, ...) pc->printf("[INF %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#else +#define DBG(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#define INFO(x, ...) +#endif +#endif -#define CHUNKSIZE 1600 // When receiving and handing partial to the app, this is the chunk size +#define CHUNK_SIZE 1500 // max size of a single chunk (probably limited by Ethernet to 1500) +#define HANG_TIMEOUT_MS 250 // If we're waiting on the host, which may never respond, this is the timeout const char * DEFAULT_FILENAME = "index.htm"; @@ -37,6 +52,7 @@ {".jpg", "Content-Type: image/jpeg\r\n" }, {".jpeg","Content-Type: image/jpeg\r\n" }, {".ico", "Content-Type: image/x-icon\r\n" }, + {".bmp", "Content-Type: image/bmp\r\n" }, {".png", "Content-Type: image/png\r\n" }, {".zip", "Content-Type: image/zip\r\n" }, {".gz", "Content-Type: image/gz\r\n" }, @@ -107,10 +123,12 @@ queryParamCount = 0; handlercount = 0; maxheaderbytes = 0; + INFO("HTTPServer::HTTPServer"); server = new TCPSocketServer(); server->bind(port); server->listen(); server->set_blocking(false, 10); + client.set_blocking(false, 100); //@TODO client is separate from server. any way to combine? ResetPerformanceData(); PerformanceTimer.start(); } @@ -220,7 +238,18 @@ case ReceivingPayload: // After the header, there is a payload that will be handled +#if 1 + n = client.receive(bPtr, headerbuffersize - (bPtr - headerbuffer)); + if (n < 0) { + op = Sending; + INFO("*** client.receive() => %d", n); + } else if (n) { + bPtr[n] = '\0'; + INFO("*** payload size %d", n); + } +#else op = Sending; +#endif break; case Sending: @@ -645,38 +674,45 @@ // @todo need to refactor - if the thing is bigger than the buffer, // then we can receive it a chunk at a time, and hand off // the chunks to the callback. May need callbacks that - // are: START: extract the filename/object name, - // NEXT: a chunk of data, - // END: signals that all chunks were delivered. + // are: DATA_TRANSFER: self-detect to extract the filename/object name, + // DATA_TRANSFER: subsequent chunk of data, + // DATA_TRANSFER_END: signals that last chunk is enclosed. // // If so, we'll make space for it - postQueryString = (char *)mymalloc(CHUNKSIZE); + postQueryString = (char *)mymalloc(CHUNK_SIZE); INFO("Free space %d", Free()); if (postQueryString) { - int ttlReceived = 0; - - INFO("Processing"); - dblCR += 4; // If we slurped up any of the POST, - while (*dblCR && *dblCR <= ' ') - dblCR++; - strcpy(postQueryString, dblCR); // copy that in and then get the rest - while (ttlReceived < postBytes) { - int len; - wait_ms(4); - len = client.receive(postQueryString, CHUNKSIZE); - if (len >=0) { - INFO("Passing %d bytes (%d of %d) in [%s]", len, ttlReceived, postBytes, postQueryString); - ttlReceived += len; + int len; + int ttlCount = 4; // includes the doubleCR in the total count from Content-Length + Timer escapePlan; + bool escape = false; + + escapePlan.start(); + //INFO("Processing"); + while (ttlCount < postBytes && !escape) { + len = client.receive_all(postQueryString, CHUNK_SIZE); + if (len > 0) { + ttlCount += len; + postQueryString[len] = '\0'; // Whether binary or ASCII, this is ok as it's after the data + //INFO("%d bytes is %d of %d: [%s]", len, ttlCount, postBytes, postQueryString); acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, postQueryString, NULL, len); + escapePlan.reset(); } else if (len < 0) { - INFO("*** receive returned %d ***", len); - break; // no more data + INFO("*** connection closed ***"); + break; // no more data, before the plan + } else { // n == 0 + ; + } + if (escapePlan.read_ms() > HANG_TIMEOUT_MS) { + escape = true; + WARN("Escape plan activated."); } } + //INFO("..processing exit"); + acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER_END, NULL, NULL, 0); myfree(postQueryString); - INFO("done."); } else { - ERR("HTTPd: attempt to allocate %d bytes failed.", CHUNKSIZE); + ERR("attempt to allocate %d failed.", CHUNK_SIZE); } } else { // Simply copy it to the bitbucket