aa

Dependents:   Internet-Piano_WIZwiki-W7500

Fork of httpServer by IOP

Committer:
ysy00700
Date:
Tue Aug 11 05:37:32 2015 +0000
Revision:
2:45877b9fab33
Parent:
0:e59cc54df17c
aa

Who changed what in which revision?

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