HTTP Server upon new mbed Ethernet Interface. Based on original code by Henry Leinen.
Dependencies: EthernetInterface mbed-rtos mbed
Fork of HTTP_server by
HTTPServer.cpp@2:dc9184e97328, 2013-07-28 (annotated)
- Committer:
- pabloxid
- Date:
- Sun Jul 28 07:53:35 2013 +0000
- Revision:
- 2:dc9184e97328
- Parent:
- 0:fcceff3299be
- Child:
- 3:27b3a889b327
Many fixes: It works now
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
pabloxid | 0:fcceff3299be | 1 | #include "mbed.h" |
pabloxid | 0:fcceff3299be | 2 | #include "HTTPServer.h" |
pabloxid | 0:fcceff3299be | 3 | |
pabloxid | 0:fcceff3299be | 4 | RequestConfig rq_conf[] = { |
pabloxid | 0:fcceff3299be | 5 | { "GET", HTTP_RT_GET }, |
pabloxid | 0:fcceff3299be | 6 | { "POST", HTTP_RT_POST} |
pabloxid | 0:fcceff3299be | 7 | }; |
pabloxid | 0:fcceff3299be | 8 | |
pabloxid | 0:fcceff3299be | 9 | HTTPServer::HTTPServer (int port, const char* _path) { |
pabloxid | 0:fcceff3299be | 10 | |
pabloxid | 0:fcceff3299be | 11 | INFO("Binding to port %d...", port); |
pabloxid | 0:fcceff3299be | 12 | if (socketServer.bind (port) < 0) { |
pabloxid | 0:fcceff3299be | 13 | ERR("Failed to bind to port !\n"); |
pabloxid | 0:fcceff3299be | 14 | error("Binding"); |
pabloxid | 0:fcceff3299be | 15 | } |
pabloxid | 0:fcceff3299be | 16 | |
pabloxid | 0:fcceff3299be | 17 | INFO("Listening ..."); |
pabloxid | 0:fcceff3299be | 18 | if (socketServer.listen(1) < 0) { |
pabloxid | 0:fcceff3299be | 19 | ERR("Failed to listen !\n"); |
pabloxid | 0:fcceff3299be | 20 | error("Listening"); |
pabloxid | 0:fcceff3299be | 21 | } |
pabloxid | 0:fcceff3299be | 22 | |
pabloxid | 0:fcceff3299be | 23 | INFO("Connected !"); |
pabloxid | 0:fcceff3299be | 24 | // set into blocking operation |
pabloxid | 2:dc9184e97328 | 25 | socketServer.set_blocking (true); |
pabloxid | 0:fcceff3299be | 26 | |
pabloxid | 0:fcceff3299be | 27 | path = _path; |
pabloxid | 0:fcceff3299be | 28 | |
pabloxid | 0:fcceff3299be | 29 | } |
pabloxid | 0:fcceff3299be | 30 | |
pabloxid | 0:fcceff3299be | 31 | HTTPServer::~HTTPServer() { }; |
pabloxid | 0:fcceff3299be | 32 | |
pabloxid | 0:fcceff3299be | 33 | int HTTPServer::poll () { |
pabloxid | 0:fcceff3299be | 34 | |
pabloxid | 0:fcceff3299be | 35 | cliente = new TCPSocketConnection; |
pabloxid | 0:fcceff3299be | 36 | cliente->set_blocking (false, TIMEOUT); |
pabloxid | 0:fcceff3299be | 37 | |
pabloxid | 0:fcceff3299be | 38 | if (socketServer.accept(*cliente) < 0) { |
pabloxid | 0:fcceff3299be | 39 | INFO("No connection\n"); |
pabloxid | 0:fcceff3299be | 40 | return ERROR; |
pabloxid | 0:fcceff3299be | 41 | } |
pabloxid | 0:fcceff3299be | 42 | |
pabloxid | 2:dc9184e97328 | 43 | // a new connection was received |
pabloxid | 2:dc9184e97328 | 44 | INFO("Client (IP=%s) is connected !", cliente->get_address()); |
pabloxid | 0:fcceff3299be | 45 | |
pabloxid | 0:fcceff3299be | 46 | msg = new HTTPMsg; // estructura para decodificar y alojar el mensaje |
pabloxid | 0:fcceff3299be | 47 | |
pabloxid | 2:dc9184e97328 | 48 | int c = pollConnection (); // esto parsea y llena las cosas contenidas en msg |
pabloxid | 0:fcceff3299be | 49 | |
pabloxid | 0:fcceff3299be | 50 | if (c == OK) { |
pabloxid | 2:dc9184e97328 | 51 | // Handle the request |
pabloxid | 2:dc9184e97328 | 52 | // cliente->set_blocking (true); |
pabloxid | 0:fcceff3299be | 53 | INFO("Handling request !"); |
pabloxid | 0:fcceff3299be | 54 | handleRequest (); |
pabloxid | 0:fcceff3299be | 55 | } |
pabloxid | 0:fcceff3299be | 56 | |
pabloxid | 0:fcceff3299be | 57 | delete msg; |
pabloxid | 0:fcceff3299be | 58 | delete cliente; |
pabloxid | 0:fcceff3299be | 59 | |
pabloxid | 2:dc9184e97328 | 60 | INFO("Leaving polling thread\n"); |
pabloxid | 0:fcceff3299be | 61 | return c; |
pabloxid | 0:fcceff3299be | 62 | } |
pabloxid | 0:fcceff3299be | 63 | |
pabloxid | 0:fcceff3299be | 64 | int HTTPServer::pollConnection () { |
pabloxid | 0:fcceff3299be | 65 | |
pabloxid | 0:fcceff3299be | 66 | int received = 0; |
pabloxid | 0:fcceff3299be | 67 | INFO("Waiting for new data in connection"); |
pabloxid | 0:fcceff3299be | 68 | // Try receiving request line |
pabloxid | 0:fcceff3299be | 69 | received = receiveLine (); |
pabloxid | 0:fcceff3299be | 70 | |
pabloxid | 0:fcceff3299be | 71 | if (received == ERROR) { |
pabloxid | 0:fcceff3299be | 72 | // there was an error, probably the connection was closed, so close this connection as well |
pabloxid | 0:fcceff3299be | 73 | INFO("No more data available. Will close this connection now."); |
pabloxid | 0:fcceff3299be | 74 | return ERROR; |
pabloxid | 0:fcceff3299be | 75 | } |
pabloxid | 0:fcceff3299be | 76 | |
pabloxid | 0:fcceff3299be | 77 | // The Request has not yet been received so try it |
pabloxid | 0:fcceff3299be | 78 | received = parse (); |
pabloxid | 0:fcceff3299be | 79 | |
pabloxid | 0:fcceff3299be | 80 | if (received == ERROR) { |
pabloxid | 0:fcceff3299be | 81 | // Invalid content received, so close the connection |
pabloxid | 0:fcceff3299be | 82 | INFO("Invalid message received, so sending negative response and closing connection !"); |
pabloxid | 2:dc9184e97328 | 83 | tcpsend ("HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r", 0); |
pabloxid | 0:fcceff3299be | 84 | return ERROR; |
pabloxid | 0:fcceff3299be | 85 | } |
pabloxid | 0:fcceff3299be | 86 | |
pabloxid | 2:dc9184e97328 | 87 | // The request has been received, try receive the body |
pabloxid | 0:fcceff3299be | 88 | do { |
pabloxid | 0:fcceff3299be | 89 | received = receiveLine (); |
pabloxid | 0:fcceff3299be | 90 | if (received == ERROR) {return ERROR;} |
pabloxid | 0:fcceff3299be | 91 | // First check if we received an empty line. This would indicate the end of the message or message body. |
pabloxid | 0:fcceff3299be | 92 | if (received == EMPTY) { |
pabloxid | 0:fcceff3299be | 93 | // there was an empty line, so we can start with performing the request |
pabloxid | 0:fcceff3299be | 94 | INFO("Request Header was received completely. Performing request."); |
pabloxid | 0:fcceff3299be | 95 | received = 0; |
pabloxid | 0:fcceff3299be | 96 | break; |
pabloxid | 0:fcceff3299be | 97 | } else { |
pabloxid | 2:dc9184e97328 | 98 | /* add message body |
pabloxid | 0:fcceff3299be | 99 | if (parseHeader () != 0) { |
pabloxid | 0:fcceff3299be | 100 | WARN("Invalid message header received !"); |
pabloxid | 2:dc9184e97328 | 101 | }*/ |
pabloxid | 0:fcceff3299be | 102 | } |
pabloxid | 2:dc9184e97328 | 103 | } while (received > 0); // |
pabloxid | 0:fcceff3299be | 104 | |
pabloxid | 0:fcceff3299be | 105 | INFO("Leaving poll function!"); |
pabloxid | 0:fcceff3299be | 106 | return received; |
pabloxid | 0:fcceff3299be | 107 | } |
pabloxid | 0:fcceff3299be | 108 | |
pabloxid | 0:fcceff3299be | 109 | int HTTPServer::receiveLine () { |
pabloxid | 0:fcceff3299be | 110 | |
pabloxid | 0:fcceff3299be | 111 | buffer[0] = 0; |
pabloxid | 0:fcceff3299be | 112 | |
pabloxid | 0:fcceff3299be | 113 | if (!cliente->is_connected()) { |
pabloxid | 0:fcceff3299be | 114 | error("NOT Connected anymore"); |
pabloxid | 0:fcceff3299be | 115 | return ERROR; |
pabloxid | 0:fcceff3299be | 116 | } |
pabloxid | 0:fcceff3299be | 117 | |
pabloxid | 0:fcceff3299be | 118 | Timer tm; |
pabloxid | 0:fcceff3299be | 119 | int i; |
pabloxid | 0:fcceff3299be | 120 | |
pabloxid | 0:fcceff3299be | 121 | // Try to receive up to the max number of characters |
pabloxid | 0:fcceff3299be | 122 | for (i=0; i<BUFFER_SIZE-1; i++) { |
pabloxid | 0:fcceff3299be | 123 | int c = cliente->receive (buffer+i, 1); |
pabloxid | 0:fcceff3299be | 124 | // Check that - if no character was currently received - the timeout period is reached. |
pabloxid | 0:fcceff3299be | 125 | if (c == 0 || c == -1) { |
pabloxid | 0:fcceff3299be | 126 | // no character was read, so check if operation timed out |
pabloxid | 2:dc9184e97328 | 127 | if (tm.read_ms() > 2*TIMEOUT) { |
pabloxid | 0:fcceff3299be | 128 | // Operation timed out |
pabloxid | 0:fcceff3299be | 129 | INFO("Timeout occured in function 'receiveLine'."); |
pabloxid | 0:fcceff3299be | 130 | return ERROR; |
pabloxid | 0:fcceff3299be | 131 | } |
pabloxid | 0:fcceff3299be | 132 | } |
pabloxid | 0:fcceff3299be | 133 | // Check if line terminating character was received |
pabloxid | 0:fcceff3299be | 134 | if (buffer[i] == '\n') {break;} |
pabloxid | 0:fcceff3299be | 135 | } |
pabloxid | 0:fcceff3299be | 136 | // Terminate with \0 |
pabloxid | 0:fcceff3299be | 137 | buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 138 | |
pabloxid | 0:fcceff3299be | 139 | // Trim for '\r' linefeed at the end |
pabloxid | 0:fcceff3299be | 140 | if (i>0 && buffer[i-1] == '\r') { |
pabloxid | 0:fcceff3299be | 141 | i--; |
pabloxid | 0:fcceff3299be | 142 | buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 143 | } |
pabloxid | 0:fcceff3299be | 144 | |
pabloxid | 0:fcceff3299be | 145 | // return number of characters received in the line or return -2 if an empty line was received |
pabloxid | 0:fcceff3299be | 146 | if (i==0 || (i==1 && buffer[0]=='\r')) { |
pabloxid | 0:fcceff3299be | 147 | // empty line received, so return -2 |
pabloxid | 0:fcceff3299be | 148 | return EMPTY; |
pabloxid | 0:fcceff3299be | 149 | } |
pabloxid | 0:fcceff3299be | 150 | // retorna número de caracteres leidos |
pabloxid | 0:fcceff3299be | 151 | return i; |
pabloxid | 0:fcceff3299be | 152 | } |
pabloxid | 0:fcceff3299be | 153 | |
pabloxid | 0:fcceff3299be | 154 | int HTTPServer::parse () { |
pabloxid | 0:fcceff3299be | 155 | |
pabloxid | 0:fcceff3299be | 156 | // Check if buffer content is not long enough. |
pabloxid | 0:fcceff3299be | 157 | if (strlen(buffer) < MIN_LONG) { |
pabloxid | 0:fcceff3299be | 158 | ERR("Buffer content is invalid or too short."); |
pabloxid | 0:fcceff3299be | 159 | return ERROR; |
pabloxid | 0:fcceff3299be | 160 | } |
pabloxid | 0:fcceff3299be | 161 | |
pabloxid | 0:fcceff3299be | 162 | std::vector<std::string> args; |
pabloxid | 0:fcceff3299be | 163 | |
pabloxid | 0:fcceff3299be | 164 | int argno = 0; |
pabloxid | 0:fcceff3299be | 165 | // decompose string into a list of arguments |
pabloxid | 0:fcceff3299be | 166 | int start = 0; // current starting char |
pabloxid | 0:fcceff3299be | 167 | int nLen = strlen(buffer)+1; |
pabloxid | 0:fcceff3299be | 168 | for (int i=0; i<nLen; i++) { |
pabloxid | 0:fcceff3299be | 169 | if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) { |
pabloxid | 0:fcceff3299be | 170 | // new arg found |
pabloxid | 0:fcceff3299be | 171 | buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 172 | if (argno++ == 1) { |
pabloxid | 0:fcceff3299be | 173 | // it's the uri |
pabloxid | 0:fcceff3299be | 174 | // parse the uri args |
pabloxid | 0:fcceff3299be | 175 | parseUriArgs (&buffer[start]); |
pabloxid | 0:fcceff3299be | 176 | } |
pabloxid | 0:fcceff3299be | 177 | INFO("Found argument \"%s\"", &buffer[start]); |
pabloxid | 0:fcceff3299be | 178 | args.push_back(&buffer[start]); |
pabloxid | 0:fcceff3299be | 179 | start = i+1; |
pabloxid | 0:fcceff3299be | 180 | } |
pabloxid | 0:fcceff3299be | 181 | } |
pabloxid | 0:fcceff3299be | 182 | |
pabloxid | 0:fcceff3299be | 183 | // store the uri and the HTTP version |
pabloxid | 0:fcceff3299be | 184 | msg->uri = args[1]; |
pabloxid | 0:fcceff3299be | 185 | msg->version = args[2]; |
pabloxid | 0:fcceff3299be | 186 | |
pabloxid | 0:fcceff3299be | 187 | // Find matching request type |
pabloxid | 0:fcceff3299be | 188 | for (int i=0; i<sizeof(rq_conf)/sizeof(RequestConfig) ; i++) { |
pabloxid | 0:fcceff3299be | 189 | if (args.at(0) == rq_conf[i].request_string) { |
pabloxid | 0:fcceff3299be | 190 | msg->request = rq_conf[i].request_type; |
pabloxid | 0:fcceff3299be | 191 | } |
pabloxid | 0:fcceff3299be | 192 | } |
pabloxid | 0:fcceff3299be | 193 | |
pabloxid | 0:fcceff3299be | 194 | return OK; |
pabloxid | 0:fcceff3299be | 195 | } |
pabloxid | 0:fcceff3299be | 196 | |
pabloxid | 0:fcceff3299be | 197 | /* esta rutina no se usa */ |
pabloxid | 0:fcceff3299be | 198 | |
pabloxid | 0:fcceff3299be | 199 | int HTTPServer::parseHeader () { |
pabloxid | 0:fcceff3299be | 200 | |
pabloxid | 0:fcceff3299be | 201 | // Check if the buffer content is too short to be meaningful |
pabloxid | 0:fcceff3299be | 202 | if (strlen(buffer) < MIN_LONG) {return ERROR;} |
pabloxid | 0:fcceff3299be | 203 | |
pabloxid | 0:fcceff3299be | 204 | // decompose string into a touple of <field name> : <field value> |
pabloxid | 0:fcceff3299be | 205 | int value_start = 0; |
pabloxid | 0:fcceff3299be | 206 | int buflen = strlen(buffer)+1; |
pabloxid | 0:fcceff3299be | 207 | for (int i=0; i<buflen; i++) { |
pabloxid | 0:fcceff3299be | 208 | if (buffer[i] == ':') { |
pabloxid | 0:fcceff3299be | 209 | // touple found |
pabloxid | 0:fcceff3299be | 210 | buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 211 | value_start = i+1; |
pabloxid | 0:fcceff3299be | 212 | msg->headers[buffer] = &buffer[value_start]; |
pabloxid | 0:fcceff3299be | 213 | INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]); |
pabloxid | 0:fcceff3299be | 214 | return OK; |
pabloxid | 0:fcceff3299be | 215 | } |
pabloxid | 0:fcceff3299be | 216 | } |
pabloxid | 0:fcceff3299be | 217 | |
pabloxid | 0:fcceff3299be | 218 | ERR("Did not recieve a valid header : \"%s\".", buffer); |
pabloxid | 0:fcceff3299be | 219 | return ERROR; |
pabloxid | 0:fcceff3299be | 220 | } |
pabloxid | 0:fcceff3299be | 221 | |
pabloxid | 0:fcceff3299be | 222 | int HTTPServer::parseUriArgs (char *uri_buffer) { |
pabloxid | 0:fcceff3299be | 223 | |
pabloxid | 0:fcceff3299be | 224 | // Check if the buffer content is too short to be meaningful |
pabloxid | 0:fcceff3299be | 225 | if (strlen(uri_buffer) < MIN_LONG) {return ERROR;} |
pabloxid | 0:fcceff3299be | 226 | |
pabloxid | 0:fcceff3299be | 227 | int args_start = -1; |
pabloxid | 0:fcceff3299be | 228 | int value_start = -1; |
pabloxid | 0:fcceff3299be | 229 | int buflen = strlen(uri_buffer) + 1; |
pabloxid | 0:fcceff3299be | 230 | char* argname = NULL; |
pabloxid | 0:fcceff3299be | 231 | char* valuename = NULL; |
pabloxid | 0:fcceff3299be | 232 | for (int i=0; i<buflen; i++) { |
pabloxid | 0:fcceff3299be | 233 | if (args_start == -1) { // args section not yet found |
pabloxid | 0:fcceff3299be | 234 | if (uri_buffer[i] == '?') { // starts with a question mark, so got it |
pabloxid | 0:fcceff3299be | 235 | uri_buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 236 | args_start = i; // set the start of the args section |
pabloxid | 0:fcceff3299be | 237 | INFO("Argument section found !"); |
pabloxid | 0:fcceff3299be | 238 | } |
pabloxid | 0:fcceff3299be | 239 | } else { // search arg-value touples |
pabloxid | 0:fcceff3299be | 240 | if (argname == NULL) { // arg-name found ? |
pabloxid | 0:fcceff3299be | 241 | if (uri_buffer[i] == '=') { |
pabloxid | 0:fcceff3299be | 242 | // yes, separate the arg-name |
pabloxid | 0:fcceff3299be | 243 | uri_buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 244 | argname = &uri_buffer[args_start]; |
pabloxid | 0:fcceff3299be | 245 | value_start = i+1; |
pabloxid | 0:fcceff3299be | 246 | INFO("Argument name %s", argname); |
pabloxid | 0:fcceff3299be | 247 | } |
pabloxid | 0:fcceff3299be | 248 | } else { // search for end of value |
pabloxid | 0:fcceff3299be | 249 | if ((uri_buffer[i] == '&') || (uri_buffer[i] == 0) || (uri_buffer[i] == '\r') || (uri_buffer[i] == '\n')) { |
pabloxid | 0:fcceff3299be | 250 | buffer[i] = 0; |
pabloxid | 0:fcceff3299be | 251 | valuename = &uri_buffer[value_start]; |
pabloxid | 0:fcceff3299be | 252 | INFO("Argument value %s", valuename); |
pabloxid | 0:fcceff3299be | 253 | msg->args[argname] = valuename; |
pabloxid | 0:fcceff3299be | 254 | // reset all indicators |
pabloxid | 0:fcceff3299be | 255 | argname = NULL; |
pabloxid | 0:fcceff3299be | 256 | valuename = NULL; |
pabloxid | 0:fcceff3299be | 257 | } |
pabloxid | 0:fcceff3299be | 258 | } |
pabloxid | 0:fcceff3299be | 259 | } |
pabloxid | 0:fcceff3299be | 260 | } |
pabloxid | 0:fcceff3299be | 261 | |
pabloxid | 0:fcceff3299be | 262 | return OK; |
pabloxid | 0:fcceff3299be | 263 | } |
pabloxid | 0:fcceff3299be | 264 | |
pabloxid | 0:fcceff3299be | 265 | /* verificar qué parte de msg realmente se usa, |
pabloxid | 0:fcceff3299be | 266 | eliminar el resto, incluyendo los procesos asociados */ |
pabloxid | 0:fcceff3299be | 267 | |
pabloxid | 0:fcceff3299be | 268 | void HTTPServer::handleRequest () { |
pabloxid | 0:fcceff3299be | 269 | |
pabloxid | 0:fcceff3299be | 270 | int err_; |
pabloxid | 0:fcceff3299be | 271 | |
pabloxid | 0:fcceff3299be | 272 | switch (msg->request) { |
pabloxid | 0:fcceff3299be | 273 | case HTTP_RT_GET: |
pabloxid | 0:fcceff3299be | 274 | INFO("Dispatching GET Request."); |
pabloxid | 0:fcceff3299be | 275 | err_ = handleGetRequest(); |
pabloxid | 0:fcceff3299be | 276 | break; |
pabloxid | 0:fcceff3299be | 277 | case HTTP_RT_POST: |
pabloxid | 0:fcceff3299be | 278 | INFO("Dispatching POST request."); |
pabloxid | 0:fcceff3299be | 279 | err_ = handlePostRequest(); |
pabloxid | 0:fcceff3299be | 280 | break; |
pabloxid | 0:fcceff3299be | 281 | default: |
pabloxid | 0:fcceff3299be | 282 | INFO("Error in handleRequest, unhandled request type."); |
pabloxid | 0:fcceff3299be | 283 | err_ = 501; // HTTP_NotImplemented |
pabloxid | 0:fcceff3299be | 284 | break; |
pabloxid | 0:fcceff3299be | 285 | } |
pabloxid | 0:fcceff3299be | 286 | |
pabloxid | 0:fcceff3299be | 287 | // if any of these functions returns a negative number, call the error handler |
pabloxid | 0:fcceff3299be | 288 | if (err_ > 0) { |
pabloxid | 0:fcceff3299be | 289 | handleError (err_); |
pabloxid | 0:fcceff3299be | 290 | } |
pabloxid | 0:fcceff3299be | 291 | |
pabloxid | 0:fcceff3299be | 292 | } |
pabloxid | 0:fcceff3299be | 293 | |
pabloxid | 0:fcceff3299be | 294 | int HTTPServer::handleGetRequest() { |
pabloxid | 0:fcceff3299be | 295 | |
pabloxid | 2:dc9184e97328 | 296 | int retval = OK; //success |
pabloxid | 0:fcceff3299be | 297 | |
pabloxid | 2:dc9184e97328 | 298 | INFO("Handling Get Request."); |
pabloxid | 0:fcceff3299be | 299 | |
pabloxid | 0:fcceff3299be | 300 | // maping to root path |
pabloxid | 0:fcceff3299be | 301 | std::string reqPath = path + msg->uri.substr(1); |
pabloxid | 0:fcceff3299be | 302 | |
pabloxid | 0:fcceff3299be | 303 | // Check if we received a directory with the local path |
pabloxid | 0:fcceff3299be | 304 | if (reqPath.substr(reqPath.length()-1, 1) == "/") { |
pabloxid | 0:fcceff3299be | 305 | // yes, we shall append the default page name |
pabloxid | 0:fcceff3299be | 306 | reqPath += "index.htm"; |
pabloxid | 0:fcceff3299be | 307 | } |
pabloxid | 0:fcceff3299be | 308 | |
pabloxid | 0:fcceff3299be | 309 | INFO("Mapping \"%s\" to \"%s\"", msg->uri.c_str(), reqPath.c_str()); |
pabloxid | 0:fcceff3299be | 310 | |
pabloxid | 2:dc9184e97328 | 311 | FILE *file = fopen(reqPath.c_str(), "r"); |
pabloxid | 2:dc9184e97328 | 312 | if (file != NULL) { |
pabloxid | 0:fcceff3299be | 313 | |
pabloxid | 2:dc9184e97328 | 314 | // asigna toda la memoria dinámica disponible para 'chunk' |
pabloxid | 2:dc9184e97328 | 315 | char * chunk = NULL; |
pabloxid | 2:dc9184e97328 | 316 | int chunk_sz = MAX_CHUNK_SIZE; |
pabloxid | 2:dc9184e97328 | 317 | while(chunk == NULL) { |
pabloxid | 2:dc9184e97328 | 318 | chunk_sz /= 2; |
pabloxid | 2:dc9184e97328 | 319 | chunk = (char*) malloc (chunk_sz); |
pabloxid | 2:dc9184e97328 | 320 | if (chunk_sz < MIN_CHUNK_SIZE) { |
pabloxid | 0:fcceff3299be | 321 | error ("OutOfMemory"); |
pabloxid | 2:dc9184e97328 | 322 | } |
pabloxid | 0:fcceff3299be | 323 | } |
pabloxid | 0:fcceff3299be | 324 | |
pabloxid | 2:dc9184e97328 | 325 | // File was found and can be returned; first determine the size |
pabloxid | 2:dc9184e97328 | 326 | fseek (file, 0, SEEK_END); |
pabloxid | 2:dc9184e97328 | 327 | int size = ftell (file); |
pabloxid | 2:dc9184e97328 | 328 | fseek (file, 0, SEEK_SET); |
pabloxid | 0:fcceff3299be | 329 | |
pabloxid | 2:dc9184e97328 | 330 | startResponse (200, size); // response: 200 = HTTP_Ok |
pabloxid | 2:dc9184e97328 | 331 | while (!feof(file) && !ferror(file)) { |
pabloxid | 2:dc9184e97328 | 332 | int count = fread (chunk, 1, chunk_sz , file); |
pabloxid | 2:dc9184e97328 | 333 | INFO("Processing Response (%d bytes)!", count); |
pabloxid | 2:dc9184e97328 | 334 | if (cliente->send_all (chunk, count) != count) { |
pabloxid | 2:dc9184e97328 | 335 | WARN ("Unsent bytes left !"); // TODO: handle filesystem errors |
pabloxid | 2:dc9184e97328 | 336 | } |
pabloxid | 0:fcceff3299be | 337 | } |
pabloxid | 0:fcceff3299be | 338 | |
pabloxid | 0:fcceff3299be | 339 | INFO("Ending Response !"); |
pabloxid | 0:fcceff3299be | 340 | |
pabloxid | 2:dc9184e97328 | 341 | free (chunk); |
pabloxid | 2:dc9184e97328 | 342 | fclose (file); |
pabloxid | 0:fcceff3299be | 343 | |
pabloxid | 0:fcceff3299be | 344 | } else { |
pabloxid | 0:fcceff3299be | 345 | retval = 404; |
pabloxid | 0:fcceff3299be | 346 | ERR("Requested file was not found !"); |
pabloxid | 0:fcceff3299be | 347 | } |
pabloxid | 0:fcceff3299be | 348 | |
pabloxid | 0:fcceff3299be | 349 | return retval; |
pabloxid | 0:fcceff3299be | 350 | |
pabloxid | 0:fcceff3299be | 351 | } |
pabloxid | 0:fcceff3299be | 352 | |
pabloxid | 0:fcceff3299be | 353 | int HTTPServer::handlePostRequest() { |
pabloxid | 0:fcceff3299be | 354 | |
pabloxid | 0:fcceff3299be | 355 | return 404; |
pabloxid | 0:fcceff3299be | 356 | } |
pabloxid | 0:fcceff3299be | 357 | |
pabloxid | 0:fcceff3299be | 358 | static const char hdrStandard[] = "DNT: 1\r\n" |
pabloxid | 0:fcceff3299be | 359 | "MaxAge: 0\r\n" |
pabloxid | 0:fcceff3299be | 360 | "Connection: Keep-Alive\r\n" |
pabloxid | 2:dc9184e97328 | 361 | "Content-Type: text/html\r\n" // TODO: handle file types |
pabloxid | 0:fcceff3299be | 362 | "Server: mbed embedded\r\n" |
pabloxid | 0:fcceff3299be | 363 | "Accessible: 1\r\n" |
pabloxid | 0:fcceff3299be | 364 | "\r\n"; |
pabloxid | 0:fcceff3299be | 365 | |
pabloxid | 2:dc9184e97328 | 366 | void HTTPServer::startResponse (int returnCode, int nLen) { |
pabloxid | 0:fcceff3299be | 367 | |
pabloxid | 2:dc9184e97328 | 368 | INFO("Starting response (%d bytes in total)!", nLen); |
pabloxid | 2:dc9184e97328 | 369 | |
pabloxid | 2:dc9184e97328 | 370 | tcpsend ("HTTP/1.1 %d OK\r\n", returnCode); |
pabloxid | 2:dc9184e97328 | 371 | tcpsend ("Content-Length: %d\r\n", nLen); // Add 2 chars for the terminating CR+LF |
pabloxid | 0:fcceff3299be | 372 | INFO("Sending standard headers !"); |
pabloxid | 2:dc9184e97328 | 373 | tcpsend (hdrStandard); |
pabloxid | 0:fcceff3299be | 374 | |
pabloxid | 2:dc9184e97328 | 375 | INFO("Done !"); |
pabloxid | 0:fcceff3299be | 376 | |
pabloxid | 0:fcceff3299be | 377 | } |
pabloxid | 0:fcceff3299be | 378 | |
pabloxid | 0:fcceff3299be | 379 | static const char* errorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error</h1><P>HTTPServer Error<P></BODY></HTML>\r\n\r\n"; |
pabloxid | 0:fcceff3299be | 380 | |
pabloxid | 0:fcceff3299be | 381 | void HTTPServer::handleError (int errorCode) { |
pabloxid | 0:fcceff3299be | 382 | |
pabloxid | 0:fcceff3299be | 383 | INFO("Handling error !"); |
pabloxid | 0:fcceff3299be | 384 | |
pabloxid | 2:dc9184e97328 | 385 | tcpsend ("HTTP/1.1 %d Error\r\n", errorCode); |
pabloxid | 2:dc9184e97328 | 386 | tcpsend ("Content-Length: %d\r\n", strlen(errorPage)); |
pabloxid | 2:dc9184e97328 | 387 | tcpsend ("Content-Type: text/html\r\nServer: mbed embedded\r\n\r\n"); |
pabloxid | 2:dc9184e97328 | 388 | tcpsend (errorPage); // TODO: better error page (handle error type) |
pabloxid | 0:fcceff3299be | 389 | |
pabloxid | 0:fcceff3299be | 390 | INFO("Done !"); |
pabloxid | 0:fcceff3299be | 391 | |
pabloxid | 0:fcceff3299be | 392 | } |