Single instance HTTP Server using new Ethernet Interface with bug fix for URL arguments

Fork of HTTPServer by Henry Leinen

Committer:
leihen
Date:
Sun May 26 23:22:36 2013 +0000
Revision:
2:8653bbcf7e58
Parent:
1:6b7472d5e9ee
Child:
3:d6224049b3bf
Optimized for RAM.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 0:7a2421e63e74 1 /* HTTPConnection.cpp */
leihen 0:7a2421e63e74 2
leihen 0:7a2421e63e74 3 #include "mbed.h"
leihen 0:7a2421e63e74 4 #include "HTTPConnection.h"
leihen 0:7a2421e63e74 5
leihen 0:7a2421e63e74 6 #include <vector>
leihen 0:7a2421e63e74 7 using std::vector;
leihen 0:7a2421e63e74 8
leihen 0:7a2421e63e74 9 using std::string;
leihen 0:7a2421e63e74 10
leihen 2:8653bbcf7e58 11 #if (1 && !defined(TARGET_LPC11U24))
leihen 0:7a2421e63e74 12 #define INFO(x, ...) std::printf("[HttpConnection : INFO]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 13 #define WARN(x, ...) std::printf("[HttpConnection : WARN]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 14 #define ERR(x, ...) std::printf("[HttpConnection : ERR]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 15 #else
leihen 0:7a2421e63e74 16 #define INFO(x, ...)
leihen 0:7a2421e63e74 17 #define WARN(x, ...)
leihen 0:7a2421e63e74 18 #define ERR(x, ...)
leihen 0:7a2421e63e74 19 #endif
leihen 0:7a2421e63e74 20
leihen 0:7a2421e63e74 21
leihen 0:7a2421e63e74 22
leihen 0:7a2421e63e74 23
leihen 0:7a2421e63e74 24 HTTPConnection::HTTPConnection()
leihen 0:7a2421e63e74 25 {
leihen 0:7a2421e63e74 26 }
leihen 0:7a2421e63e74 27
leihen 0:7a2421e63e74 28
leihen 0:7a2421e63e74 29 HTTPConnection::~HTTPConnection()
leihen 0:7a2421e63e74 30 {
leihen 0:7a2421e63e74 31 close();
leihen 0:7a2421e63e74 32 }
leihen 0:7a2421e63e74 33
leihen 0:7a2421e63e74 34 void HTTPConnection::close()
leihen 0:7a2421e63e74 35 {
leihen 0:7a2421e63e74 36 m_Msg.headers.clear();
leihen 0:7a2421e63e74 37 }
leihen 0:7a2421e63e74 38
leihen 0:7a2421e63e74 39 int HTTPConnection::poll()
leihen 0:7a2421e63e74 40 {
leihen 0:7a2421e63e74 41 static char buffer[256] = {};
leihen 0:7a2421e63e74 42
leihen 0:7a2421e63e74 43
leihen 0:7a2421e63e74 44 int rcvd= 0;
leihen 0:7a2421e63e74 45 INFO("[HTTPConnection]Waiting for new data in connection");
leihen 0:7a2421e63e74 46 // Try receiving request line
leihen 0:7a2421e63e74 47 rcvd = receiveLine(buffer, 255, 3000);
leihen 0:7a2421e63e74 48 if (rcvd == -1) {
leihen 0:7a2421e63e74 49 // there was an error, probably the connection was closed, so close this connection as well
leihen 0:7a2421e63e74 50 INFO("No more data available. Will close this connection now.");
leihen 0:7a2421e63e74 51 close();
leihen 0:7a2421e63e74 52 return -1;
leihen 0:7a2421e63e74 53 }
leihen 0:7a2421e63e74 54
leihen 0:7a2421e63e74 55 // The Request has not yet been received so try it
leihen 0:7a2421e63e74 56 rcvd = parse(buffer);
leihen 0:7a2421e63e74 57 if (rcvd == -1) {
leihen 0:7a2421e63e74 58 // Invalid content received, so close the connection
leihen 0:7a2421e63e74 59 INFO("Invalid message received, so sending negative response and closing connection !");
leihen 2:8653bbcf7e58 60 sprintf(buffer,"HTTP/1.1 400 NOK\n\rContent-Length: %d\n\rContent-Type: text\n\rConnection: Close\n\r\n\r",0);
leihen 0:7a2421e63e74 61 m_Tcp.set_blocking(true, 1500);
leihen 0:7a2421e63e74 62 m_Tcp.send(buffer,strlen(buffer));
leihen 0:7a2421e63e74 63 close();
leihen 0:7a2421e63e74 64 rcvd = -1;
leihen 0:7a2421e63e74 65 return -1;
leihen 0:7a2421e63e74 66 }
leihen 0:7a2421e63e74 67 // The request has been received, try receive the body
leihen 0:7a2421e63e74 68 while(rcvd > 0) {
leihen 0:7a2421e63e74 69 rcvd = receiveLine((char*)buffer, 255, 3000);
leihen 0:7a2421e63e74 70 // First check if we received an empty line. This would indicate the end of the message or message body.
leihen 0:7a2421e63e74 71 if (rcvd < 0) {
leihen 0:7a2421e63e74 72 // there was an empty line, so we can start with performing the request
leihen 0:7a2421e63e74 73 INFO("Request Header was received completely. Performing request.");
leihen 0:7a2421e63e74 74 rcvd = 0;
leihen 0:7a2421e63e74 75 break;
leihen 0:7a2421e63e74 76 }
leihen 0:7a2421e63e74 77 else {
leihen 0:7a2421e63e74 78 // add message body
leihen 0:7a2421e63e74 79 if (parseHeader(buffer) == 0) {
leihen 0:7a2421e63e74 80 }
leihen 0:7a2421e63e74 81 else {
leihen 0:7a2421e63e74 82 WARN("Invalid message header received !");
leihen 0:7a2421e63e74 83 }
leihen 0:7a2421e63e74 84 }
leihen 0:7a2421e63e74 85 }
leihen 0:7a2421e63e74 86 INFO("Leaving poll function!");
leihen 0:7a2421e63e74 87 return rcvd;
leihen 0:7a2421e63e74 88 }
leihen 0:7a2421e63e74 89
leihen 0:7a2421e63e74 90 int HTTPConnection::receiveLine(char* szLine, int nMaxLen, int nTimeout, char cLineTerm)
leihen 0:7a2421e63e74 91 {
leihen 0:7a2421e63e74 92 if ((szLine == NULL) || (nMaxLen == 0))
leihen 0:7a2421e63e74 93 return -1;
leihen 0:7a2421e63e74 94
leihen 0:7a2421e63e74 95 m_Tcp.set_blocking(false);
leihen 0:7a2421e63e74 96
leihen 0:7a2421e63e74 97 Timer tm;
leihen 0:7a2421e63e74 98 int i;
leihen 0:7a2421e63e74 99
leihen 0:7a2421e63e74 100 // Try to receive up to the max number of characters
leihen 0:7a2421e63e74 101 for (i = 0 ; i < nMaxLen-1 ; i++) {
leihen 0:7a2421e63e74 102 int c;
leihen 0:7a2421e63e74 103 c = m_Tcp.receive_all( szLine + i, 1 );
leihen 0:7a2421e63e74 104 // Check that - if no character was currently received - the timeout period is reached.
leihen 0:7a2421e63e74 105 if ((c == 0) || (c==-1)) {
leihen 0:7a2421e63e74 106 // no character was read, so check if operation timed out
leihen 0:7a2421e63e74 107 if (tm.read_ms() > nTimeout) {
leihen 0:7a2421e63e74 108 // Operation timed out
leihen 0:7a2421e63e74 109 INFO("Timeout occured in function 'receiveLine'.");
leihen 0:7a2421e63e74 110 return -1;
leihen 0:7a2421e63e74 111 }
leihen 0:7a2421e63e74 112 }
leihen 0:7a2421e63e74 113
leihen 0:7a2421e63e74 114 // Check if line terminating character was received
leihen 0:7a2421e63e74 115 if (szLine[i] == cLineTerm)
leihen 0:7a2421e63e74 116 break;
leihen 0:7a2421e63e74 117 }
leihen 0:7a2421e63e74 118 // Terminate with \0
leihen 0:7a2421e63e74 119 szLine[i] = 0;
leihen 0:7a2421e63e74 120
leihen 0:7a2421e63e74 121 // Trim for '\r' linefeed at the end
leihen 0:7a2421e63e74 122 if( (i >0) && (szLine[i-1] == '\r')) {
leihen 0:7a2421e63e74 123 i--;
leihen 0:7a2421e63e74 124 szLine[i] = 0;
leihen 0:7a2421e63e74 125 }
leihen 0:7a2421e63e74 126 INFO("receiveLine : \"%s\".", szLine);
leihen 0:7a2421e63e74 127
leihen 0:7a2421e63e74 128 // return number of characters received in the line or return -2 if an empty line was received
leihen 0:7a2421e63e74 129 if ((i == 0) || ((i==1) &&(szLine[0] == '\r')))
leihen 0:7a2421e63e74 130 {
leihen 0:7a2421e63e74 131 // empty line received, so return -2
leihen 0:7a2421e63e74 132 return -2;
leihen 0:7a2421e63e74 133 }
leihen 0:7a2421e63e74 134 return i;
leihen 0:7a2421e63e74 135 }
leihen 0:7a2421e63e74 136
leihen 2:8653bbcf7e58 137 int HTTPConnection::parse(char* buffer)
leihen 0:7a2421e63e74 138 {
leihen 0:7a2421e63e74 139 if ((buffer == NULL) || (strlen(buffer) < 4)) {
leihen 0:7a2421e63e74 140 ERR("Buffer content is invalid or too short.");
leihen 0:7a2421e63e74 141 return -1;
leihen 0:7a2421e63e74 142 }
leihen 0:7a2421e63e74 143
leihen 0:7a2421e63e74 144 vector<std::string> args;
leihen 0:7a2421e63e74 145 args.clear();
leihen 0:7a2421e63e74 146
leihen 0:7a2421e63e74 147 // decompose string into a list of arguments
leihen 0:7a2421e63e74 148 char s = 0; // current starting char
leihen 2:8653bbcf7e58 149 int nLen = strlen(buffer)+1;
leihen 2:8653bbcf7e58 150 for (int i = 0 ; i < nLen ; i++) {
leihen 0:7a2421e63e74 151 if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) {
leihen 0:7a2421e63e74 152 // new arg found
leihen 2:8653bbcf7e58 153 buffer[i] = 0;
leihen 2:8653bbcf7e58 154 INFO("Found argument \"%s\"", &buffer[s]);
leihen 2:8653bbcf7e58 155 args.push_back(&buffer[s]);
leihen 0:7a2421e63e74 156 s = i+1;
leihen 0:7a2421e63e74 157 }
leihen 0:7a2421e63e74 158 }
leihen 0:7a2421e63e74 159
leihen 0:7a2421e63e74 160 if (args.at(0) == "GET") {
leihen 0:7a2421e63e74 161 m_Msg.request = HTTP_RT_GET;
leihen 0:7a2421e63e74 162 m_Msg.uri = args[1];
leihen 0:7a2421e63e74 163 m_Msg.version = args[2];
leihen 0:7a2421e63e74 164 }
leihen 0:7a2421e63e74 165 else {
leihen 0:7a2421e63e74 166 if (args.at(0) == "POST") {
leihen 0:7a2421e63e74 167 m_Msg.request = HTTP_RT_GET;
leihen 0:7a2421e63e74 168 m_Msg.uri = args[1];
leihen 0:7a2421e63e74 169 m_Msg.version = args[2];
leihen 0:7a2421e63e74 170 }
leihen 0:7a2421e63e74 171 else {
leihen 0:7a2421e63e74 172 INFO("unhandled message.");
leihen 0:7a2421e63e74 173 }
leihen 0:7a2421e63e74 174 }
leihen 0:7a2421e63e74 175 args.clear();
leihen 0:7a2421e63e74 176
leihen 0:7a2421e63e74 177 return 1;
leihen 0:7a2421e63e74 178 }
leihen 0:7a2421e63e74 179
leihen 0:7a2421e63e74 180
leihen 0:7a2421e63e74 181 int HTTPConnection::parseHeader(const char *buffer)
leihen 0:7a2421e63e74 182 {
leihen 0:7a2421e63e74 183 if ((strlen(buffer) <3) || (buffer == NULL))
leihen 0:7a2421e63e74 184 return -1;
leihen 0:7a2421e63e74 185
leihen 0:7a2421e63e74 186 // decompose string into a touple of <field name> : <field value>
leihen 0:7a2421e63e74 187 static char fieldname[256] = {};
leihen 0:7a2421e63e74 188 static char fieldvalue[256] = {};
leihen 0:7a2421e63e74 189 for (int i = 0 ; i < strlen(buffer)+1 ; i++) {
leihen 0:7a2421e63e74 190 if (buffer[i] == ':') {
leihen 0:7a2421e63e74 191 // touple found
leihen 0:7a2421e63e74 192 strncpy(fieldname, buffer, i);
leihen 0:7a2421e63e74 193 fieldname[i] = 0;
leihen 0:7a2421e63e74 194 strcpy(fieldvalue, &buffer[i+1]);
leihen 0:7a2421e63e74 195
leihen 0:7a2421e63e74 196 // m_Msg.headers[fieldname] = fieldvalue;
leihen 0:7a2421e63e74 197
leihen 0:7a2421e63e74 198 INFO("Header name=\"%s\" : value=\"%s\".", fieldname, fieldvalue);
leihen 0:7a2421e63e74 199 return 0;
leihen 0:7a2421e63e74 200 }
leihen 0:7a2421e63e74 201 }
leihen 0:7a2421e63e74 202
leihen 0:7a2421e63e74 203 ERR("Did not recieve a valid header : \"%s\".", buffer);
leihen 0:7a2421e63e74 204 return -1;
leihen 0:7a2421e63e74 205 }