HTTP Server upon new mbed Ethernet Interface. Based on original code by Henry Leinen.

Dependencies:   EthernetInterface mbed-rtos mbed

Fork of HTTP_server by pablo gindel

Revision:
2:dc9184e97328
Parent:
0:fcceff3299be
Child:
3:27b3a889b327
--- 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 !");