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.
Dependencies: EthernetInterface mbed-rtos mbed
Fork of HTTP_server by
Diff: HTTPServer.cpp
- Revision:
- 3:27b3a889b327
- Parent:
- 2:dc9184e97328
- Child:
- 4:2a34139c7246
--- a/HTTPServer.cpp Sun Jul 28 07:53:35 2013 +0000
+++ b/HTTPServer.cpp Tue Jul 30 04:37:09 2013 +0000
@@ -21,7 +21,7 @@
}
INFO("Connected !");
- // set into blocking operation
+ // set into blocking operation
socketServer.set_blocking (true);
path = _path;
@@ -32,75 +32,83 @@
int HTTPServer::poll () {
+ int retvalue;
+
cliente = new TCPSocketConnection;
cliente->set_blocking (false, TIMEOUT);
- if (socketServer.accept(*cliente) < 0) {
+ retvalue = socketServer.accept (*cliente);
+
+ if (retvalue == OK) {
+
+ // a new connection was received
+ INFO("Client (IP=%s) is connected !", cliente->get_address());
+
+ msg = new HTTPMsg; // estructura para decodificar y alojar el mensaje
+
+ retvalue = pollConnection (); // esto parsea y llena las cosas contenidas en msg
+
+ if (retvalue == OK) {
+ // Handle the request
+ INFO("Handling request !");
+ handleRequest ();
+ }
+
+ delete msg;
+
+ } else { // retvalue == ERROR
INFO("No connection\n");
- return ERROR;
}
- // 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
-
- if (c == OK) {
- // Handle the request
- // cliente->set_blocking (true);
- INFO("Handling request !");
- handleRequest ();
- }
-
- delete msg;
delete cliente;
INFO("Leaving polling thread\n");
- return c;
+ return retvalue;
+
}
int HTTPServer::pollConnection () {
int received = 0;
INFO("Waiting for new data in connection");
- // Try receiving request line
+
+ // Try receiving request line
received = receiveLine ();
if (received == ERROR) {
- // there was an error, probably the connection was closed, so close this connection as well
+ // there was an error, probably the connection was closed, so close this connection as well
INFO("No more data available. Will close this connection now.");
return ERROR;
}
- // The Request has not yet been received so try it
- received = parse ();
+ // Request has not yet been received, so try it
+ received = parseRequest ();
if (received == ERROR) {
- // Invalid content received, so close the connection
+ // Invalid content received, so close the connection
INFO("Invalid message received, so sending negative response and closing connection !");
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
+ // Request has been received, try receive the headers section
do {
received = receiveLine ();
if (received == ERROR) {return ERROR;}
- // First check if we received an empty line. This would indicate the end of the message or message body.
+ // First check if we received an empty line;
+ // This would indicate the end of headers section.
if (received == EMPTY) {
- // there was an empty line, so we can start with performing the request
+ // there was an empty line, so the headers section is complete
INFO("Request Header was received completely. Performing request.");
received = 0;
break;
} else {
- /* add message body
- if (parseHeader () != 0) {
+ // parse header field
+ if (parseHeader() != OK) {
WARN("Invalid message header received !");
- }*/
+ }
}
- } while (received > 0); //
+ } while (received > 0);
INFO("Leaving poll function!");
return received;
@@ -151,7 +159,7 @@
return i;
}
-int HTTPServer::parse () {
+int HTTPServer::parseRequest () {
// Check if buffer content is not long enough.
if (strlen(buffer) < MIN_LONG) {
@@ -191,11 +199,12 @@
}
}
+ // init body section length
+ msg->body_length = 0;
+
return OK;
}
-/* esta rutina no se usa */
-
int HTTPServer::parseHeader () {
// Check if the buffer content is too short to be meaningful
@@ -209,13 +218,19 @@
// touple found
buffer[i] = 0;
value_start = i+1;
- msg->headers[buffer] = &buffer[value_start];
+ // headers storage is disabled; uncomment next line to enable
+ // msg->headers[buffer] = &buffer[value_start];
INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]);
+ // Look for "Content-Length" header
+ if (strcmp (buffer, "Content-Length") == 0) {
+ msg->body_length = atoi(&buffer[value_start]);
+ INFO ("Body section found. Length: %i", msg->body_length);
+ }
return OK;
}
}
- ERR("Did not recieve a valid header : \"%s\".", buffer);
+ ERR("Did not receive a valid header : \"%s\".", buffer);
return ERROR;
}
@@ -230,16 +245,16 @@
char* argname = NULL;
char* valuename = NULL;
for (int i=0; i<buflen; i++) {
- if (args_start == -1) { // args section not yet found
+ if (args_start == -1) { // args section not yet found
if (uri_buffer[i] == '?') { // starts with a question mark, so got it
uri_buffer[i] = 0;
args_start = i; // set the start of the args section
INFO("Argument section found !");
}
- } else { // search arg-value touples
- if (argname == NULL) { // arg-name found ?
+ } else { // search arg-value touples
+ if (argname == NULL) { // arg-name found ?
if (uri_buffer[i] == '=') {
- // yes, separate the arg-name
+ // yes, separate the arg-name
uri_buffer[i] = 0;
argname = &uri_buffer[args_start];
value_start = i+1;
@@ -250,21 +265,17 @@
buffer[i] = 0;
valuename = &uri_buffer[value_start];
INFO("Argument value %s", valuename);
- msg->args[argname] = valuename;
- // reset all indicators
+ msg->uri_args[argname] = valuename;
+ // reset all indicators
argname = NULL;
valuename = NULL;
}
}
}
}
-
return OK;
}
-/* verificar qué parte de msg realmente se usa,
- eliminar el resto, incluyendo los procesos asociados */
-
void HTTPServer::handleRequest () {
int err_;
@@ -311,17 +322,6 @@
FILE *file = fopen(reqPath.c_str(), "r");
if (file != NULL) {
- // 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 (file, 0, SEEK_END);
int size = ftell (file);
@@ -329,16 +329,14 @@
startResponse (200, size); // response: 200 = HTTP_Ok
while (!feof(file) && !ferror(file)) {
- int count = fread (chunk, 1, chunk_sz , file);
+ int count = fread (buffer, 1, CHUNK_SIZE, file);
INFO("Processing Response (%d bytes)!", count);
- if (cliente->send_all (chunk, count) != count) {
+ if (cliente->send_all (buffer, count) != count) {
WARN ("Unsent bytes left !"); // TODO: handle filesystem errors
}
}
-
INFO("Ending Response !");
- free (chunk);
fclose (file);
} else {
@@ -352,6 +350,36 @@
int HTTPServer::handlePostRequest() {
+ // Try receive the body data, if there is any
+ if (msg->body_length > 0) {
+
+ INFO("Receiving body data.");
+ if (msg->body_length > BUFFER_SIZE) {error ("OutOfMemory");}
+
+ int bytes_read = 0;
+ while (bytes_read < msg->body_length) {
+ int result = cliente->receive_all(buffer+bytes_read, msg->body_length-bytes_read);
+ if (result == ERROR) {
+ WARN("Error receiving body data.");
+ break;
+ }
+ bytes_read += result;
+ }
+
+ INFO("Body data received.");
+
+ // do something
+ // use the url_decode routine :)
+
+ INFO("Done !\n");
+ return handleGetRequest();
+
+ } else {
+
+ ERR("POST data not found !");
+
+ }
+
return 404;
}
@@ -361,6 +389,9 @@
"Content-Type: text/html\r\n" // TODO: handle file types
"Server: mbed embedded\r\n"
"Accessible: 1\r\n"
+ "Pragma: no-cache\r\n"
+ "Cache-control: no-cache;no-store\r\n"
+ "Expires: 0\r\n"
"\r\n";
void HTTPServer::startResponse (int returnCode, int nLen) {
@@ -390,3 +421,33 @@
INFO("Done !");
}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// UTILS //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include <ctype.h>
+
+/* Converts a hex character to its integer value */
+char from_hex (char ch) {
+ return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/* Returns a url-decoded version of str */
+void url_decode (char *str) {
+ char *lee = str, *escribe = str;
+ while (*lee) {
+ if (*lee == '%') {
+ if (lee[1] && lee[2]) {
+ *escribe++ = from_hex(lee[1])<<4 | from_hex(lee[2]);
+ lee += 2;
+ }
+ } else if (*lee == '+') {
+ *escribe++ = ' ';
+ } else {
+ *escribe++ = *lee;
+ }
+ lee++;
+ }
+ *escribe = 0;
+}
