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-26
- Revision:
- 1:6b7472d5e9ee
- Parent:
- 0:7a2421e63e74
- Child:
- 2:8653bbcf7e58
File content as of revision 1:6b7472d5e9ee:
/* HTTPConnection.cpp */ #include "mbed.h" #include "HTTPConnection.h" #include <vector> using std::vector; using std::string; #if (0 && !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] = {}; static char echoHeader[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(echoHeader,"HTTP/1.1 400 NOK\n\rContent-Length: %d\n\rContent-Type: text\n\rConnection: Close\n\r\n\r",strlen(buffer)); m_Tcp.set_blocking(true, 1500); m_Tcp.send(echoHeader,strlen(echoHeader)); 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 !"); } } } if (rcvd == 0) { // sprintf(echoHeader,"HTTP/1.1 200 OK\n\rContent-Length: %d\n\rContent-Type: text\n\rConnection: Close\n\r\n\r",strlen(buffer)); // m_Tcp.set_blocking(true); // m_Tcp.send_all(echoHeader,strlen(echoHeader)); // m_Tcp.send_all(buffer,strlen(buffer)); /// INSERT PRCESSING OF REQUESST HERE /// END OF PROCESSING REQUEST // Do not close the connection, it may be reused } 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(const 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 static char buff[255] = {}; for (int i = 0 ; i < strlen(buffer)+1 ; i++) { if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) { // new arg found strncpy(buff, &buffer[s], i-s); buff[i-s] = 0; INFO("Found argument \"%s\"", buff); args.push_back(std::string(buff)); 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(const char *buffer) { if ((strlen(buffer) <3) || (buffer == NULL)) return -1; // decompose string into a touple of <field name> : <field value> static char fieldname[256] = {}; static char fieldvalue[256] = {}; for (int i = 0 ; i < strlen(buffer)+1 ; i++) { if (buffer[i] == ':') { // touple found strncpy(fieldname, buffer, i); fieldname[i] = 0; strcpy(fieldvalue, &buffer[i+1]); // m_Msg.headers[fieldname] = fieldvalue; INFO("Header name=\"%s\" : value=\"%s\".", fieldname, fieldvalue); return 0; } } ERR("Did not recieve a valid header : \"%s\".", buffer); return -1; }