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
