Single instance HTTP Server using new Ethernet Interface. Blocking mode only; this improved stability, but the HTTP server must be started from a separate thread.
Fork of HTTPServer by
HTTPConnection.cpp
- Committer:
- leihen
- Date:
- 2013-05-28
- Revision:
- 3:d6224049b3bf
- Parent:
- 2:8653bbcf7e58
- Child:
- 4:d065642c32cc
File content as of revision 3:d6224049b3bf:
/* HTTPConnection.cpp */ #include "mbed.h" #include "HTTPConnection.h" #include <vector> using std::vector; using std::string; #if (1 && !defined(TARGET_LPC11U24)) #define INFO(x, ...) std::printf("[HttpConnection : INFO]"x"\r\n", ##__VA_ARGS__); #define WARN(x, ...) std::printf("[HttpConnection : WARN]"x"\r\n", ##__VA_ARGS__); #define ERR(x, ...) std::printf("[HttpConnection : ERR]"x"\r\n", ##__VA_ARGS__); #else #define INFO(x, ...) #define WARN(x, ...) #define ERR(x, ...) #endif HTTPConnection::HTTPConnection() { } HTTPConnection::~HTTPConnection() { close(); } void HTTPConnection::close() { m_Msg.headers.clear(); } int HTTPConnection::poll() { static char buffer[256] = {}; int rcvd= 0; INFO("[HTTPConnection]Waiting for new data in connection"); // Try receiving request line rcvd = receiveLine(buffer, 255, 3000); if (rcvd == -1) { // 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."); close(); return -1; } // The Request has not yet been received so try it rcvd = parse(buffer); if (rcvd == -1) { // Invalid content received, so close the connection INFO("Invalid message received, so sending negative response and closing connection !"); sprintf(buffer,"HTTP/1.1 400 NOK\n\rContent-Length: %d\n\rContent-Type: text\n\rConnection: Close\n\r\n\r",0); m_Tcp.set_blocking(true, 1500); m_Tcp.send(buffer,strlen(buffer)); close(); rcvd = -1; return -1; } // The request has been received, try receive the body while(rcvd > 0) { rcvd = receiveLine((char*)buffer, 255, 3000); // First check if we received an empty line. This would indicate the end of the message or message body. if (rcvd < 0) { // there was an empty line, so we can start with performing the request INFO("Request Header was received completely. Performing request."); rcvd = 0; break; } else { // add message body if (parseHeader(buffer) == 0) { } else { WARN("Invalid message header received !"); } } } INFO("Leaving poll function!"); return rcvd; } int HTTPConnection::receiveLine(char* szLine, int nMaxLen, int nTimeout, char cLineTerm) { if ((szLine == NULL) || (nMaxLen == 0)) return -1; m_Tcp.set_blocking(false); Timer tm; int i; // Try to receive up to the max number of characters for (i = 0 ; i < nMaxLen-1 ; i++) { int c; c = m_Tcp.receive_all( szLine + i, 1 ); // 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() > nTimeout) { // Operation timed out INFO("Timeout occured in function 'receiveLine'."); return -1; } } // Check if line terminating character was received if (szLine[i] == cLineTerm) break; } // Terminate with \0 szLine[i] = 0; // Trim for '\r' linefeed at the end if( (i >0) && (szLine[i-1] == '\r')) { i--; szLine[i] = 0; } INFO("receiveLine : \"%s\".", szLine); // return number of characters received in the line or return -2 if an empty line was received if ((i == 0) || ((i==1) &&(szLine[0] == '\r'))) { // empty line received, so return -2 return -2; } return i; } int HTTPConnection::parse(char* buffer) { if ((buffer == NULL) || (strlen(buffer) < 4)) { ERR("Buffer content is invalid or too short."); return -1; } vector<std::string> args; args.clear(); // decompose string into a list of arguments char s = 0; // current starting char int nLen = strlen(buffer)+1; for (int i = 0 ; i < nLen ; i++) { if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) { // new arg found buffer[i] = 0; INFO("Found argument \"%s\"", &buffer[s]); args.push_back(&buffer[s]); s = i+1; } } if (args.at(0) == "GET") { m_Msg.request = HTTP_RT_GET; m_Msg.uri = args[1]; m_Msg.version = args[2]; } else { if (args.at(0) == "POST") { m_Msg.request = HTTP_RT_GET; m_Msg.uri = args[1]; m_Msg.version = args[2]; } else { INFO("unhandled message."); } } args.clear(); return 1; } int HTTPConnection::parseHeader(char *buffer) { if ((strlen(buffer) <3) || (buffer == NULL)) return -1; // decompose string into a touple of <field name> : <field value> int value_start = 0; int buflen = strlen(buffer)+1; for (int i = 0 ; i < buflen ; i++) { if (buffer[i] == ':') { // touple found buffer[i] = 0; value_start = i+1; m_Msg.headers[buffer] = &buffer[value_start]; INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]); return 0; } } ERR("Did not recieve a valid header : \"%s\".", buffer); return -1; }