HTTPServer

Committer:
jphuc96
Date:
Sat Sep 16 02:39:55 2017 +0000
Revision:
0:caf5feddac47
v1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jphuc96 0:caf5feddac47 1 /* HTTPConnection.cpp */
jphuc96 0:caf5feddac47 2
jphuc96 0:caf5feddac47 3 #include "mbed.h"
jphuc96 0:caf5feddac47 4 #include "HTTPConnection.h"
jphuc96 0:caf5feddac47 5 #define DEBUG
jphuc96 0:caf5feddac47 6 #include "hl_debug.h"
jphuc96 0:caf5feddac47 7
jphuc96 0:caf5feddac47 8 #include <vector>
jphuc96 0:caf5feddac47 9 using std::vector;
jphuc96 0:caf5feddac47 10
jphuc96 0:caf5feddac47 11 using std::string;
jphuc96 0:caf5feddac47 12
jphuc96 0:caf5feddac47 13
jphuc96 0:caf5feddac47 14
jphuc96 0:caf5feddac47 15 const struct HTTPRequestConfig {
jphuc96 0:caf5feddac47 16 const char* request_string;
jphuc96 0:caf5feddac47 17 HTTPRequestType request_type;
jphuc96 0:caf5feddac47 18 } g_requestConfig[] = {
jphuc96 0:caf5feddac47 19 { "GET", HTTP_RT_GET },
jphuc96 0:caf5feddac47 20 { "POST", HTTP_RT_POST},
jphuc96 0:caf5feddac47 21 { "PUT", HTTP_RT_PUT},
jphuc96 0:caf5feddac47 22 { "OPTIONS",HTTP_RT_OPTIONS},
jphuc96 0:caf5feddac47 23 { "HEAD", HTTP_RT_HEAD},
jphuc96 0:caf5feddac47 24 { "DELETE", HTTP_RT_DELETE},
jphuc96 0:caf5feddac47 25 { "TRACE", HTTP_RT_TRACE},
jphuc96 0:caf5feddac47 26 { "CONNECT",HTTP_RT_CONNECT}
jphuc96 0:caf5feddac47 27 };
jphuc96 0:caf5feddac47 28
jphuc96 0:caf5feddac47 29
jphuc96 0:caf5feddac47 30 HTTPConnection::HTTPConnection(TCPSocketConnection& clnt) : m_Tcp(clnt)
jphuc96 0:caf5feddac47 31 {
jphuc96 0:caf5feddac47 32 }
jphuc96 0:caf5feddac47 33
jphuc96 0:caf5feddac47 34
jphuc96 0:caf5feddac47 35 HTTPConnection::~HTTPConnection()
jphuc96 0:caf5feddac47 36 {
jphuc96 0:caf5feddac47 37 close();
jphuc96 0:caf5feddac47 38 }
jphuc96 0:caf5feddac47 39
jphuc96 0:caf5feddac47 40 void HTTPConnection::close()
jphuc96 0:caf5feddac47 41 {
jphuc96 0:caf5feddac47 42 m_Msg.headers.clear();
jphuc96 0:caf5feddac47 43 }
jphuc96 0:caf5feddac47 44
jphuc96 0:caf5feddac47 45 int HTTPConnection::poll()
jphuc96 0:caf5feddac47 46 {
jphuc96 0:caf5feddac47 47 static char buffer[256] = {};
jphuc96 0:caf5feddac47 48
jphuc96 0:caf5feddac47 49
jphuc96 0:caf5feddac47 50 int rcvd= 0;
jphuc96 0:caf5feddac47 51 INFO("Waiting for new data in connection");
jphuc96 0:caf5feddac47 52 // Try receiving request line
jphuc96 0:caf5feddac47 53 rcvd = receiveLine(buffer, 255, 3000);
jphuc96 0:caf5feddac47 54 if (rcvd == -1) {
jphuc96 0:caf5feddac47 55 // there was an error, probably the connection was closed, so close this connection as well
jphuc96 0:caf5feddac47 56 INFO("No more data available. Will close this connection now.");
jphuc96 0:caf5feddac47 57 close();
jphuc96 0:caf5feddac47 58 return -1;
jphuc96 0:caf5feddac47 59 }
jphuc96 0:caf5feddac47 60
jphuc96 0:caf5feddac47 61 // The Request has not yet been received so try it
jphuc96 0:caf5feddac47 62 rcvd = parse(buffer);
jphuc96 0:caf5feddac47 63 if (rcvd == -1) {
jphuc96 0:caf5feddac47 64 // Invalid content received, so close the connection
jphuc96 0:caf5feddac47 65 INFO("Invalid message received, so sending negative response and closing connection !");
jphuc96 0:caf5feddac47 66 sprintf(buffer,"HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r",0);
jphuc96 0:caf5feddac47 67 m_Tcp.set_blocking(true, 1500);
jphuc96 0:caf5feddac47 68 m_Tcp.send(buffer,strlen(buffer));
jphuc96 0:caf5feddac47 69 close();
jphuc96 0:caf5feddac47 70 rcvd = -1;
jphuc96 0:caf5feddac47 71 return -1;
jphuc96 0:caf5feddac47 72 }
jphuc96 0:caf5feddac47 73 // The request has been received, try receive the body
jphuc96 0:caf5feddac47 74 while(rcvd > 0) {
jphuc96 0:caf5feddac47 75 rcvd = receiveLine((char*)buffer, 255, 3000);
jphuc96 0:caf5feddac47 76 // First check if we received an empty line. This would indicate the end of the message or message body.
jphuc96 0:caf5feddac47 77 if (rcvd < 0) {
jphuc96 0:caf5feddac47 78 // there was an empty line, so we can start with performing the request
jphuc96 0:caf5feddac47 79 INFO("Request Header was received completely. Performing request.");
jphuc96 0:caf5feddac47 80 rcvd = 0;
jphuc96 0:caf5feddac47 81 break;
jphuc96 0:caf5feddac47 82 }
jphuc96 0:caf5feddac47 83 else {
jphuc96 0:caf5feddac47 84 // add message body
jphuc96 0:caf5feddac47 85 if (parseHeader(buffer) == 0) {
jphuc96 0:caf5feddac47 86 }
jphuc96 0:caf5feddac47 87 else {
jphuc96 0:caf5feddac47 88 WARN("Invalid message header received !");
jphuc96 0:caf5feddac47 89 }
jphuc96 0:caf5feddac47 90 }
jphuc96 0:caf5feddac47 91 }
jphuc96 0:caf5feddac47 92 INFO("Leaving poll function!");
jphuc96 0:caf5feddac47 93 return rcvd;
jphuc96 0:caf5feddac47 94 }
jphuc96 0:caf5feddac47 95
jphuc96 0:caf5feddac47 96 int HTTPConnection::receiveLine(char* szLine, int nMaxLen, int nTimeout, char cLineTerm)
jphuc96 0:caf5feddac47 97 {
jphuc96 0:caf5feddac47 98 if ((szLine == NULL) || (nMaxLen == 0))
jphuc96 0:caf5feddac47 99 return -1;
jphuc96 0:caf5feddac47 100
jphuc96 0:caf5feddac47 101 szLine[0] = 0;
jphuc96 0:caf5feddac47 102 m_Tcp.set_blocking(false);
jphuc96 0:caf5feddac47 103
jphuc96 0:caf5feddac47 104 if (!m_Tcp.is_connected()) {
jphuc96 0:caf5feddac47 105 error("NOT COnnected anymore");
jphuc96 0:caf5feddac47 106 return -1;
jphuc96 0:caf5feddac47 107 }
jphuc96 0:caf5feddac47 108 Timer tm;
jphuc96 0:caf5feddac47 109 int i;
jphuc96 0:caf5feddac47 110
jphuc96 0:caf5feddac47 111 // Try to receive up to the max number of characters
jphuc96 0:caf5feddac47 112 for (i = 0 ; i < nMaxLen-1 ; i++) {
jphuc96 0:caf5feddac47 113 int c;
jphuc96 0:caf5feddac47 114 c = m_Tcp.receive( szLine + i, 1 );
jphuc96 0:caf5feddac47 115 // Check that - if no character was currently received - the timeout period is reached.
jphuc96 0:caf5feddac47 116 if ((c == 0) || (c==-1)) {
jphuc96 0:caf5feddac47 117 // no character was read, so check if operation timed out
jphuc96 0:caf5feddac47 118 if (tm.read_ms() > nTimeout) {
jphuc96 0:caf5feddac47 119 // Operation timed out
jphuc96 0:caf5feddac47 120 INFO("Timeout occured in function 'receiveLine'.");
jphuc96 0:caf5feddac47 121 return -1;
jphuc96 0:caf5feddac47 122 }
jphuc96 0:caf5feddac47 123 }
jphuc96 0:caf5feddac47 124
jphuc96 0:caf5feddac47 125 // Check if line terminating character was received
jphuc96 0:caf5feddac47 126 if (szLine[i] == cLineTerm)
jphuc96 0:caf5feddac47 127 {
jphuc96 0:caf5feddac47 128 break;
jphuc96 0:caf5feddac47 129 }
jphuc96 0:caf5feddac47 130 }
jphuc96 0:caf5feddac47 131 // Terminate with \0
jphuc96 0:caf5feddac47 132 szLine[i] = 0;
jphuc96 0:caf5feddac47 133
jphuc96 0:caf5feddac47 134 // Trim for '\r' linefeed at the end
jphuc96 0:caf5feddac47 135 if( (i >0) && (szLine[i-1] == '\r')) {
jphuc96 0:caf5feddac47 136 i--;
jphuc96 0:caf5feddac47 137 szLine[i] = 0;
jphuc96 0:caf5feddac47 138 }
jphuc96 0:caf5feddac47 139
jphuc96 0:caf5feddac47 140 // return number of characters received in the line or return -2 if an empty line was received
jphuc96 0:caf5feddac47 141 if ((i == 0) || ((i==1) &&(szLine[0] == '\r')))
jphuc96 0:caf5feddac47 142 {
jphuc96 0:caf5feddac47 143 // empty line received, so return -2
jphuc96 0:caf5feddac47 144 return -2;
jphuc96 0:caf5feddac47 145 }
jphuc96 0:caf5feddac47 146 return i;
jphuc96 0:caf5feddac47 147 }
jphuc96 0:caf5feddac47 148
jphuc96 0:caf5feddac47 149 int HTTPConnection::parse(char* buffer)
jphuc96 0:caf5feddac47 150 {
jphuc96 0:caf5feddac47 151 // Check if buffer is invalid or its content not long enough.
jphuc96 0:caf5feddac47 152 if ((buffer == NULL) || (strlen(buffer) < 4)) {
jphuc96 0:caf5feddac47 153 ERR("Buffer content is invalid or too short.");
jphuc96 0:caf5feddac47 154 return -1;
jphuc96 0:caf5feddac47 155 }
jphuc96 0:caf5feddac47 156
jphuc96 0:caf5feddac47 157 std::vector<std::string> args;
jphuc96 0:caf5feddac47 158 args.clear();
jphuc96 0:caf5feddac47 159
jphuc96 0:caf5feddac47 160 int argno = 0;
jphuc96 0:caf5feddac47 161 // decompose string into a list of arguments
jphuc96 0:caf5feddac47 162 char s = 0; // current starting char
jphuc96 0:caf5feddac47 163 int nLen = strlen(buffer)+1;
jphuc96 0:caf5feddac47 164 for (int i = 0 ; i < nLen ; i++) {
jphuc96 0:caf5feddac47 165 if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) {
jphuc96 0:caf5feddac47 166 // new arg found
jphuc96 0:caf5feddac47 167 buffer[i] = 0;
jphuc96 0:caf5feddac47 168 if (argno++ == 1) {
jphuc96 0:caf5feddac47 169 // its the uri
jphuc96 0:caf5feddac47 170 // parse the uri args
jphuc96 0:caf5feddac47 171 parseUriArgs(&buffer[s], m_Msg.args);
jphuc96 0:caf5feddac47 172 }
jphuc96 0:caf5feddac47 173 INFO("Found argument \"%s\"", &buffer[s]);
jphuc96 0:caf5feddac47 174 args.push_back(&buffer[s]);
jphuc96 0:caf5feddac47 175 s = i+1;
jphuc96 0:caf5feddac47 176 }
jphuc96 0:caf5feddac47 177 }
jphuc96 0:caf5feddac47 178
jphuc96 0:caf5feddac47 179 // store the uri and the HTTP version
jphuc96 0:caf5feddac47 180 m_Msg.uri = args[1];
jphuc96 0:caf5feddac47 181 m_Msg.version = args[2];
jphuc96 0:caf5feddac47 182
jphuc96 0:caf5feddac47 183 // Find matching request type
jphuc96 0:caf5feddac47 184 for (int i = 0 ; i < sizeof(g_requestConfig)/sizeof(struct HTTPRequestConfig) ; i++) {
jphuc96 0:caf5feddac47 185 if (args.at(0) == g_requestConfig[i].request_string) {
jphuc96 0:caf5feddac47 186 m_Msg.request = g_requestConfig[i].request_type;
jphuc96 0:caf5feddac47 187 }
jphuc96 0:caf5feddac47 188 }
jphuc96 0:caf5feddac47 189 args.clear();
jphuc96 0:caf5feddac47 190
jphuc96 0:caf5feddac47 191 return 1;
jphuc96 0:caf5feddac47 192 }
jphuc96 0:caf5feddac47 193
jphuc96 0:caf5feddac47 194
jphuc96 0:caf5feddac47 195 int HTTPConnection::parseHeader(char *buffer)
jphuc96 0:caf5feddac47 196 {
jphuc96 0:caf5feddac47 197 // Check if the buffer is invalid or if the content is too short to be meaningful
jphuc96 0:caf5feddac47 198 if ((strlen(buffer) <3) || (buffer == NULL))
jphuc96 0:caf5feddac47 199 return -1;
jphuc96 0:caf5feddac47 200
jphuc96 0:caf5feddac47 201 // decompose string into a touple of <field name> : <field value>
jphuc96 0:caf5feddac47 202 int value_start = 0;
jphuc96 0:caf5feddac47 203 int buflen = strlen(buffer)+1;
jphuc96 0:caf5feddac47 204 for (int i = 0 ; i < buflen ; i++) {
jphuc96 0:caf5feddac47 205 if (buffer[i] == ':') {
jphuc96 0:caf5feddac47 206 // touple found
jphuc96 0:caf5feddac47 207 buffer[i] = 0;
jphuc96 0:caf5feddac47 208 value_start = i+1;
jphuc96 0:caf5feddac47 209 m_Msg.headers[buffer] = &buffer[value_start];
jphuc96 0:caf5feddac47 210
jphuc96 0:caf5feddac47 211 INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]);
jphuc96 0:caf5feddac47 212 return 0;
jphuc96 0:caf5feddac47 213 }
jphuc96 0:caf5feddac47 214 }
jphuc96 0:caf5feddac47 215
jphuc96 0:caf5feddac47 216 ERR("Did not recieve a valid header : \"%s\".", buffer);
jphuc96 0:caf5feddac47 217 return -1;
jphuc96 0:caf5feddac47 218 }
jphuc96 0:caf5feddac47 219
jphuc96 0:caf5feddac47 220 int HTTPConnection::parseUriArgs(char *buffer, map<string,string>&args)
jphuc96 0:caf5feddac47 221 {
jphuc96 0:caf5feddac47 222 // Check if the buffer is invalid or if the content is too short to be meaningful
jphuc96 0:caf5feddac47 223 if ((strlen(buffer) <3) || (buffer == NULL))
jphuc96 0:caf5feddac47 224 return -1;
jphuc96 0:caf5feddac47 225
jphuc96 0:caf5feddac47 226 int args_start = -1;
jphuc96 0:caf5feddac47 227 int value_start = -1;
jphuc96 0:caf5feddac47 228 int buflen = strlen(buffer) +1;
jphuc96 0:caf5feddac47 229 const char* argname = NULL;
jphuc96 0:caf5feddac47 230 const char* valuename = NULL;
jphuc96 0:caf5feddac47 231 for (int i = 0; i < buflen ; i++) {
jphuc96 0:caf5feddac47 232 if (args_start == -1) { // args section not yet found
jphuc96 0:caf5feddac47 233 if (buffer[i] == '?') { // starts with a question mark, so got it
jphuc96 0:caf5feddac47 234 buffer[i] = 0;
jphuc96 0:caf5feddac47 235 args_start = i; // set the start of the args section
jphuc96 0:caf5feddac47 236 INFO("Argument section found !");
jphuc96 0:caf5feddac47 237 }
jphuc96 0:caf5feddac47 238 }
jphuc96 0:caf5feddac47 239 else { // search arg-value touples
jphuc96 0:caf5feddac47 240 if (argname == NULL) { // arg-name found ?
jphuc96 0:caf5feddac47 241 if (buffer[i] == '=') {
jphuc96 0:caf5feddac47 242 // yes, separate the arg-name
jphuc96 0:caf5feddac47 243 buffer[i] = 0;
jphuc96 0:caf5feddac47 244 argname = &buffer[args_start];
jphuc96 0:caf5feddac47 245 value_start = i+1;
jphuc96 0:caf5feddac47 246 INFO("Argument name %s", argname);
jphuc96 0:caf5feddac47 247 }
jphuc96 0:caf5feddac47 248 }
jphuc96 0:caf5feddac47 249 else { // search for end of value
jphuc96 0:caf5feddac47 250 if ((buffer[i] == '&') || (buffer[i] == 0) || (buffer[i] == '\r') || (buffer[i] == '\n')) {
jphuc96 0:caf5feddac47 251 buffer[i] = 0;
jphuc96 0:caf5feddac47 252 valuename = &buffer[value_start];
jphuc96 0:caf5feddac47 253 INFO("Argument value %s", valuename);
jphuc96 0:caf5feddac47 254 args[argname] = valuename;
jphuc96 0:caf5feddac47 255 // reset all indicators
jphuc96 0:caf5feddac47 256 argname = NULL;
jphuc96 0:caf5feddac47 257 valuename = NULL;
jphuc96 0:caf5feddac47 258 }
jphuc96 0:caf5feddac47 259 }
jphuc96 0:caf5feddac47 260 }
jphuc96 0:caf5feddac47 261 }
jphuc96 0:caf5feddac47 262
jphuc96 0:caf5feddac47 263 return 0;
jphuc96 0:caf5feddac47 264 }