HTTP Server upon new mbed Ethernet Interface. Based on original code by Henry Leinen.
Dependencies: EthernetInterface mbed-rtos mbed
Fork of HTTP_server by
Revision 2:dc9184e97328, committed 2013-07-28
- Comitter:
- pabloxid
- Date:
- Sun Jul 28 07:53:35 2013 +0000
- Parent:
- 1:f0c641cd9bad
- Child:
- 3:27b3a889b327
- Commit message:
- Many fixes: It works now
Changed in this revision
--- a/HTTPServer.cpp Fri Jul 26 22:33:47 2013 +0000 +++ b/HTTPServer.cpp Sun Jul 28 07:53:35 2013 +0000 @@ -1,16 +1,6 @@ #include "mbed.h" #include "HTTPServer.h" -#define DEBUG -#include "debug.h" - -#define TIMEOUT 500 -#define OK 0 -#define ERROR -1 -#define EMPTY -2 -#define MIN_LONG 3 - - RequestConfig rq_conf[] = { { "GET", HTTP_RT_GET }, { "POST", HTTP_RT_POST} @@ -32,7 +22,7 @@ INFO("Connected !"); // set into blocking operation - socketServer.set_blocking (true, TIMEOUT); + socketServer.set_blocking (true); path = _path; @@ -50,24 +40,24 @@ return ERROR; } - // a new connection was received - INFO("Client (IP=%s) is connected !\n", cliente->get_address()); + // a new connection was received + INFO("Client (IP=%s) is connected !", cliente->get_address()); msg = new HTTPMsg; // estructura para decodificar y alojar el mensaje - int c = pollConnection (); // esto parsea y llena las cosas contenidas en msg + int c = pollConnection (); // esto parsea y llena las cosas contenidas en msg if (c == OK) { - // Handle the request + // Handle the request + // cliente->set_blocking (true); INFO("Handling request !"); - //cliente->set_blocking (true, TIMEOUT); handleRequest (); } delete msg; delete cliente; - INFO("Leaving polling thread"); + INFO("Leaving polling thread\n"); return c; } @@ -90,14 +80,11 @@ if (received == ERROR) { // Invalid content received, so close the connection INFO("Invalid message received, so sending negative response and closing connection !"); - sprintf (buffer,"HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r",0); - - cliente->send (buffer, strlen (buffer)); - + tcpsend ("HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r", 0); return ERROR; } - /* The request has been received, try receive the body + // The request has been received, try receive the body do { received = receiveLine (); if (received == ERROR) {return ERROR;} @@ -108,12 +95,12 @@ received = 0; break; } else { - // add message body + /* add message body if (parseHeader () != 0) { WARN("Invalid message header received !"); - } + }*/ } - } while (received > 0); */ + } while (received > 0); // INFO("Leaving poll function!"); return received; @@ -137,7 +124,7 @@ // Check that - if no character was currently received - the timeout period is reached. if (c == 0 || c == -1) { // no character was read, so check if operation timed out - if (tm.read_ms() > TIMEOUT) { + if (tm.read_ms() > 2*TIMEOUT) { // Operation timed out INFO("Timeout occured in function 'receiveLine'."); return ERROR; @@ -306,9 +293,9 @@ int HTTPServer::handleGetRequest() { - INFO("Handling Get Request."); + int retval = OK; //success - int retval = OK; //success + INFO("Handling Get Request."); // maping to root path std::string reqPath = path + msg->uri.substr(1); @@ -321,37 +308,38 @@ INFO("Mapping \"%s\" to \"%s\"", msg->uri.c_str(), reqPath.c_str()); - FILE *fp = fopen(reqPath.c_str(), "r"); - if (fp != NULL) { + FILE *file = fopen(reqPath.c_str(), "r"); + if (file != NULL) { - char * pBuffer = NULL; - int sz = 8192; // fixme harcode - while( pBuffer == NULL) { - sz /= 2; - pBuffer = (char*)malloc(sz); - if (sz < 128) // fixme harcode + // asigna toda la memoria dinámica disponible para 'chunk' + char * chunk = NULL; + int chunk_sz = MAX_CHUNK_SIZE; + while(chunk == NULL) { + chunk_sz /= 2; + chunk = (char*) malloc (chunk_sz); + if (chunk_sz < MIN_CHUNK_SIZE) { error ("OutOfMemory"); + } } - // File was found and can be returned - - // first determine the size - fseek(fp, 0, SEEK_END); - long size = ftell(fp); - fseek(fp, 0, SEEK_SET); + // File was found and can be returned; first determine the size + fseek (file, 0, SEEK_END); + int size = ftell (file); + fseek (file, 0, SEEK_SET); - startResponse (200, size); // response: 200 - while (!feof(fp) && !ferror(fp)) { - int cnt = fread (pBuffer, 1, sz , fp); - if (cnt < 0) - cnt = 0; - processResponse (cnt, pBuffer); + startResponse (200, size); // response: 200 = HTTP_Ok + while (!feof(file) && !ferror(file)) { + int count = fread (chunk, 1, chunk_sz , file); + INFO("Processing Response (%d bytes)!", count); + if (cliente->send_all (chunk, count) != count) { + WARN ("Unsent bytes left !"); // TODO: handle filesystem errors + } } INFO("Ending Response !"); - free (pBuffer); - fclose (fp); + free (chunk); + fclose (file); } else { retval = 404; @@ -370,30 +358,21 @@ static const char hdrStandard[] = "DNT: 1\r\n" "MaxAge: 0\r\n" "Connection: Keep-Alive\r\n" - "Content-Type: text/html\r\n" + "Content-Type: text/html\r\n" // TODO: handle file types "Server: mbed embedded\r\n" "Accessible: 1\r\n" "\r\n"; -void HTTPServer::startResponse (int returnCode, long nLen) { - - INFO("Starting response (%ld bytes in total)!", nLen); +void HTTPServer::startResponse (int returnCode, int nLen) { - sprintf (buffer, "HTTP/1.1 %d OK\r\n", returnCode); - cliente->send(buffer, strlen(buffer)); - sprintf (buffer, "Content-Length: %ld\r\n", nLen); // Add 2 chars for the terminating CR+LF - cliente->send(buffer, strlen(buffer)); + INFO("Starting response (%d bytes in total)!", nLen); + + tcpsend ("HTTP/1.1 %d OK\r\n", returnCode); + tcpsend ("Content-Length: %d\r\n", nLen); // Add 2 chars for the terminating CR+LF INFO("Sending standard headers !"); - cliente->send_all((char*)hdrStandard, strlen(hdrStandard)); + tcpsend (hdrStandard); - INFO("Proceeding !"); - // other content must be sent using the 'processResponse' function -} - -void HTTPServer::processResponse (int nLen, char* body) { - - INFO("Processing Response (%d bytes)!\n", nLen); - cliente->send_all (body, nLen); + INFO("Done !"); } @@ -403,14 +382,10 @@ INFO("Handling error !"); - sprintf (buffer,"HTTP/1.1 %d Error\r\n", errorCode); - cliente->send (buffer, strlen(buffer)); - sprintf (buffer, "Content-Length: %ld\r\n", strlen(errorPage)); - cliente->send (buffer, strlen(buffer)); - sprintf(buffer, "Content-Type: text/html\r\nServer: mbed embedded\r\n\r\n"); - cliente->send(buffer, strlen(buffer)); - cliente->send_all((char*)errorPage, strlen(errorPage)); - cliente->send("\r\n", 3); + tcpsend ("HTTP/1.1 %d Error\r\n", errorCode); + tcpsend ("Content-Length: %d\r\n", strlen(errorPage)); + tcpsend ("Content-Type: text/html\r\nServer: mbed embedded\r\n\r\n"); + tcpsend (errorPage); // TODO: better error page (handle error type) INFO("Done !");
--- a/HTTPServer.h Fri Jul 26 22:33:47 2013 +0000 +++ b/HTTPServer.h Sun Jul 28 07:53:35 2013 +0000 @@ -31,6 +31,18 @@ #include <string> #include <map> +#define BUFFER_SIZE 256 +#define TIMEOUT 800 +#define OK 0 +#define ERROR -1 +#define EMPTY -2 +#define MIN_LONG 3 +#define MAX_CHUNK_SIZE 512 +#define MIN_CHUNK_SIZE 128 + +#define DEBUG 0 +#include "debug.h" + enum RequestType { HTTP_RT_GET, /*!< GET request */ HTTP_RT_POST, /*!< POST request */ @@ -55,8 +67,6 @@ RequestType request_type; }; -#define BUFFER_SIZE 256 - class HTTPServer { private: @@ -73,10 +83,32 @@ void handleRequest (); int handleGetRequest(); int handlePostRequest(); - void startResponse (int returnCode, long nLen); - void processResponse (int nLen, char* body); + void startResponse (int returnCode, int nLen); void handleError (int errorCode); + int tcpsend (const char* text, int param) { + //if (cliente == NULL) {return ERROR;} + sprintf (buffer, text, param); + int len = strlen (buffer); + if (cliente->send_all (buffer, len) == len) { + return OK; + } else { + WARN("Unsent bytes left !"); + return ERROR; + } + } + + int tcpsend (const char* text) { + //if (cliente == NULL) {return ERROR;} + int len = strlen (text); + if (cliente->send_all ((char*)text, len) == len) { + return OK; + } else { + WARN("Unsent bytes left !"); + return ERROR; + } + } + public: /** Constructor for HTTPServer objects. */ HTTPServer (int port, const char* _path);
--- a/debug.h Fri Jul 26 22:33:47 2013 +0000 +++ b/debug.h Sun Jul 28 07:53:35 2013 +0000 @@ -1,16 +1,31 @@ - #ifndef __DEBUG_H__ #define __DEBUG_H__ -#ifdef DEBUG +#if (DEBUG == 3) + #define INFO(x, ...) std::printf("[INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); #define WARN(x, ...) std::printf("[WARN: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); #define ERR(x, ...) std::printf("[ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); + +#elif (DEBUG == 2) + +#define INFO(x, ...) +#define WARN(x, ...) std::printf("[WARN: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); + +#elif (DEBUG == 1) + +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) std::printf("[ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); + #else + #define INFO(x, ...) #define WARN(x, ...) #define ERR(x, ...) + #endif