Single instance HTTP Server using WiFly Interface.

Dependents:   WiFlyHTTPServerSample MultiThreadingHTTPServer

This is my implementation for a HTTP Server using the WiFly Interface. Please note that this is still under development.

It may still contain several bugs. I have tested it using a 1768 on an application board plus RN-XV board.

Currently there is only a FileSystem implemented. Also it is limited to GET request.

I try to extend it further so it will be more useful.

Btw, it does NOT work with RTOS, which seems not to be the Problem of my library.

Do not Forget to Import the WiFly Interface into your Project when using this library.

Change History:

REV5: - added support for basic RPC GET request functionality.

REV4: - added argument parsing from the request uri. - documentation extended and updated.

Committer:
leihen
Date:
Wed Jun 26 22:41:05 2013 +0000
Revision:
14:7f9fbfc18623
Moved the HttpServer module inside this library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 14:7f9fbfc18623 1 #include "mbed.h"
leihen 14:7f9fbfc18623 2 #include "HttpServer.h"
leihen 14:7f9fbfc18623 3
leihen 14:7f9fbfc18623 4 #define DEBUG
leihen 14:7f9fbfc18623 5 #include "debug.h"
leihen 14:7f9fbfc18623 6
leihen 14:7f9fbfc18623 7
leihen 14:7f9fbfc18623 8 #define EVENT_DATA_READY 0x05
leihen 14:7f9fbfc18623 9
leihen 14:7f9fbfc18623 10 DigitalOut ledRX(LED4);
leihen 14:7f9fbfc18623 11
leihen 14:7f9fbfc18623 12
leihen 14:7f9fbfc18623 13 typedef struct {
leihen 14:7f9fbfc18623 14 char c;
leihen 14:7f9fbfc18623 15 } message_t;
leihen 14:7f9fbfc18623 16
leihen 14:7f9fbfc18623 17 Queue<char, 256> m_queue;
leihen 14:7f9fbfc18623 18
leihen 14:7f9fbfc18623 19 typedef struct {
leihen 14:7f9fbfc18623 20 const char* method;
leihen 14:7f9fbfc18623 21 msg_t type;
leihen 14:7f9fbfc18623 22 } methodType_t;
leihen 14:7f9fbfc18623 23
leihen 14:7f9fbfc18623 24 const methodType_t supportedOps[] = {
leihen 14:7f9fbfc18623 25 { "GET", msg_get },
leihen 14:7f9fbfc18623 26 { "POST", msg_post },
leihen 14:7f9fbfc18623 27 { "PUT", msg_put },
leihen 14:7f9fbfc18623 28 { "HEAD", msg_head},
leihen 14:7f9fbfc18623 29 { "CONNECT", msg_connect},
leihen 14:7f9fbfc18623 30 { "DELETE", msg_delete},
leihen 14:7f9fbfc18623 31 { "TRACE", msg_trace},
leihen 14:7f9fbfc18623 32 { "OPTIONS", msg_options}
leihen 14:7f9fbfc18623 33 };
leihen 14:7f9fbfc18623 34
leihen 14:7f9fbfc18623 35
leihen 14:7f9fbfc18623 36 Queue<request_msg_t, 5> m_requestQueue; // Do not allow more than 5 concurrent requests
leihen 14:7f9fbfc18623 37 MemoryPool<request_msg_t, 5> m_requestPool;
leihen 14:7f9fbfc18623 38
leihen 14:7f9fbfc18623 39 map<string, string> messageHeaders;
leihen 14:7f9fbfc18623 40
leihen 14:7f9fbfc18623 41 map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&), HttpServer::handlersComp> HttpServer::m_lpHandlers;
leihen 14:7f9fbfc18623 42
leihen 14:7f9fbfc18623 43
leihen 14:7f9fbfc18623 44
leihen 14:7f9fbfc18623 45 /* Constructor will create and initialize all objects excep the threads */
leihen 14:7f9fbfc18623 46 HttpServer::HttpServer(PinName tx, PinName rx, PinName rst, PinName tcp_status, const char * ssid, const char * phrase, Security sec, Wifly::WiflyBaudrate_t baud)
leihen 14:7f9fbfc18623 47 : Wifly(tx, rx, rst, tcp_status, ssid, phrase, sec, baud), m_listener(NULL), m_worker(NULL)
leihen 14:7f9fbfc18623 48 {
leihen 14:7f9fbfc18623 49 INFO("Initializing wifly\n");
leihen 14:7f9fbfc18623 50 // Initialize the wifly wlan device
leihen 14:7f9fbfc18623 51 reset();
leihen 14:7f9fbfc18623 52
leihen 14:7f9fbfc18623 53 state.dhcp = true;
leihen 14:7f9fbfc18623 54 INFO("Connecting to network...");
leihen 14:7f9fbfc18623 55 // Try join the network
leihen 14:7f9fbfc18623 56 while(!join()) {
leihen 14:7f9fbfc18623 57 INFO("Failed to connect. Trying again\n");
leihen 14:7f9fbfc18623 58 reset();
leihen 14:7f9fbfc18623 59 }
leihen 14:7f9fbfc18623 60 INFO("connected\n");
leihen 14:7f9fbfc18623 61 }
leihen 14:7f9fbfc18623 62
leihen 14:7f9fbfc18623 63 HttpServer::~HttpServer()
leihen 14:7f9fbfc18623 64 {
leihen 14:7f9fbfc18623 65 if (m_listener) {
leihen 14:7f9fbfc18623 66 m_listener->terminate();
leihen 14:7f9fbfc18623 67 delete m_listener;
leihen 14:7f9fbfc18623 68 }
leihen 14:7f9fbfc18623 69 if (m_worker) {
leihen 14:7f9fbfc18623 70 m_worker->terminate();
leihen 14:7f9fbfc18623 71 delete m_worker;
leihen 14:7f9fbfc18623 72 }
leihen 14:7f9fbfc18623 73 }
leihen 14:7f9fbfc18623 74
leihen 14:7f9fbfc18623 75
leihen 14:7f9fbfc18623 76 bool HttpServer::start(int port)
leihen 14:7f9fbfc18623 77 {
leihen 14:7f9fbfc18623 78 // Bind to that port
leihen 14:7f9fbfc18623 79 if (!bind(port)) {
leihen 14:7f9fbfc18623 80 ERR("Failed to bind to port %d\n", port);
leihen 14:7f9fbfc18623 81 return false;
leihen 14:7f9fbfc18623 82 }
leihen 14:7f9fbfc18623 83
leihen 14:7f9fbfc18623 84 // Start the child threads
leihen 14:7f9fbfc18623 85 m_worker = new Thread(HttpServer::worker_thread, NULL, osPriorityAboveNormal, DEFAULT_STACK_SIZE*4);
leihen 14:7f9fbfc18623 86 if (m_worker == NULL) {
leihen 14:7f9fbfc18623 87 ERR("Failed to start server thread !\n");
leihen 14:7f9fbfc18623 88 return false;
leihen 14:7f9fbfc18623 89 }
leihen 14:7f9fbfc18623 90
leihen 14:7f9fbfc18623 91 m_listener = new Thread(&HttpServer::listen_thread, NULL, osPriorityAboveNormal, DEFAULT_STACK_SIZE*2);
leihen 14:7f9fbfc18623 92 if (m_listener == NULL) {
leihen 14:7f9fbfc18623 93 ERR("Failed to start listener thread !\n");
leihen 14:7f9fbfc18623 94 m_worker->terminate();
leihen 14:7f9fbfc18623 95 delete m_worker;
leihen 14:7f9fbfc18623 96 m_worker = NULL;
leihen 14:7f9fbfc18623 97 return false;
leihen 14:7f9fbfc18623 98 }
leihen 14:7f9fbfc18623 99
leihen 14:7f9fbfc18623 100 return true;
leihen 14:7f9fbfc18623 101 }
leihen 14:7f9fbfc18623 102
leihen 14:7f9fbfc18623 103
leihen 14:7f9fbfc18623 104
leihen 14:7f9fbfc18623 105
leihen 14:7f9fbfc18623 106
leihen 14:7f9fbfc18623 107 bool HttpServer::bind(int port)
leihen 14:7f9fbfc18623 108 {
leihen 14:7f9fbfc18623 109 char cmd[20];
leihen 14:7f9fbfc18623 110
leihen 14:7f9fbfc18623 111 // set TCP protocol
leihen 14:7f9fbfc18623 112 setProtocol(TCP);
leihen 14:7f9fbfc18623 113
leihen 14:7f9fbfc18623 114 // set local port
leihen 14:7f9fbfc18623 115 sprintf(cmd, "set i l %d\r", port);
leihen 14:7f9fbfc18623 116 if (!sendCommand(cmd, "AOK"))
leihen 14:7f9fbfc18623 117 return false;
leihen 14:7f9fbfc18623 118
leihen 14:7f9fbfc18623 119 // save
leihen 14:7f9fbfc18623 120 if (!sendCommand("save\r", "Stor"))
leihen 14:7f9fbfc18623 121 return false;
leihen 14:7f9fbfc18623 122
leihen 14:7f9fbfc18623 123 // reboot
leihen 14:7f9fbfc18623 124 reboot();
leihen 14:7f9fbfc18623 125
leihen 14:7f9fbfc18623 126 // connect the network
leihen 14:7f9fbfc18623 127 if (isDHCP()) {
leihen 14:7f9fbfc18623 128 if (!sendCommand("join\r", "DHCP=ON", NULL, 10000))
leihen 14:7f9fbfc18623 129 return false;
leihen 14:7f9fbfc18623 130 } else {
leihen 14:7f9fbfc18623 131 if (!sendCommand("join\r", "Associated", NULL, 10000))
leihen 14:7f9fbfc18623 132 return false;
leihen 14:7f9fbfc18623 133 }
leihen 14:7f9fbfc18623 134
leihen 14:7f9fbfc18623 135 // exit
leihen 14:7f9fbfc18623 136 exit();
leihen 14:7f9fbfc18623 137
leihen 14:7f9fbfc18623 138 Thread::wait(200);
leihen 14:7f9fbfc18623 139 flush();
leihen 14:7f9fbfc18623 140
leihen 14:7f9fbfc18623 141 return true;
leihen 14:7f9fbfc18623 142 }
leihen 14:7f9fbfc18623 143
leihen 14:7f9fbfc18623 144 DigitalOut Led2(LED2);
leihen 14:7f9fbfc18623 145
leihen 14:7f9fbfc18623 146 void HttpServer::handler_rx(void)
leihen 14:7f9fbfc18623 147 {
leihen 14:7f9fbfc18623 148 static char sequence = 0;
leihen 14:7f9fbfc18623 149 //read characters
leihen 14:7f9fbfc18623 150 while (wifi.readable()) {
leihen 14:7f9fbfc18623 151 char c = LPC_UART3->RBR;
leihen 14:7f9fbfc18623 152 ledRX = !ledRX;
leihen 14:7f9fbfc18623 153 switch(sequence) {
leihen 14:7f9fbfc18623 154 case 0 : if (c == 'G') sequence = 1; break;
leihen 14:7f9fbfc18623 155 case 1 : if (c == 'E') sequence = 2; break;
leihen 14:7f9fbfc18623 156 case 2 : if (c == 'T') sequence = 0; Led2 = !Led2;break;
leihen 14:7f9fbfc18623 157 default: break;
leihen 14:7f9fbfc18623 158 }
leihen 14:7f9fbfc18623 159 m_queue.put((char*)(int)c);
leihen 14:7f9fbfc18623 160 }
leihen 14:7f9fbfc18623 161 }
leihen 14:7f9fbfc18623 162
leihen 14:7f9fbfc18623 163
leihen 14:7f9fbfc18623 164 void HttpServer::attach_rx(bool callback)
leihen 14:7f9fbfc18623 165 {
leihen 14:7f9fbfc18623 166 if (!callback)
leihen 14:7f9fbfc18623 167 wifi.attach(NULL);
leihen 14:7f9fbfc18623 168 else
leihen 14:7f9fbfc18623 169 wifi.attach(this, &HttpServer::handler_rx);
leihen 14:7f9fbfc18623 170 }
leihen 14:7f9fbfc18623 171
leihen 14:7f9fbfc18623 172
leihen 14:7f9fbfc18623 173 bool HttpServer::join()
leihen 14:7f9fbfc18623 174 {
leihen 14:7f9fbfc18623 175 return Wifly::join();
leihen 14:7f9fbfc18623 176 }
leihen 14:7f9fbfc18623 177
leihen 14:7f9fbfc18623 178 int HttpServer::send(const char * str, int len, const char * ACK, char * res, int timeout)
leihen 14:7f9fbfc18623 179 {
leihen 14:7f9fbfc18623 180 return Wifly::send(str, len, ACK, res, timeout);
leihen 14:7f9fbfc18623 181 }
leihen 14:7f9fbfc18623 182
leihen 14:7f9fbfc18623 183 request_msg_t* HttpServer::checkMessageReceived(char *data)
leihen 14:7f9fbfc18623 184 {
leihen 14:7f9fbfc18623 185 INFO("Checking for new HTTP request !\n");
leihen 14:7f9fbfc18623 186 char *req = data;
leihen 14:7f9fbfc18623 187 char *uri = NULL;
leihen 14:7f9fbfc18623 188 char *ver = NULL;
leihen 14:7f9fbfc18623 189 while( *data ) {
leihen 14:7f9fbfc18623 190 if (*data == ' ') {
leihen 14:7f9fbfc18623 191 *data = 0;
leihen 14:7f9fbfc18623 192 if (uri == NULL) {
leihen 14:7f9fbfc18623 193 uri = data+1;
leihen 14:7f9fbfc18623 194 } else {
leihen 14:7f9fbfc18623 195 ver = data+1;
leihen 14:7f9fbfc18623 196 break;
leihen 14:7f9fbfc18623 197 }
leihen 14:7f9fbfc18623 198 }
leihen 14:7f9fbfc18623 199 data++;
leihen 14:7f9fbfc18623 200 }
leihen 14:7f9fbfc18623 201
leihen 14:7f9fbfc18623 202 INFO("Detected : %s, %s, %s\n", req, uri, ver);
leihen 14:7f9fbfc18623 203
leihen 14:7f9fbfc18623 204 if ((req != NULL) && (uri != NULL) && (ver != NULL) ) {
leihen 14:7f9fbfc18623 205 for (int i = 0 ; i < sizeof(supportedOps) / sizeof(methodType_t) ; i++) {
leihen 14:7f9fbfc18623 206 if (strcmp(supportedOps[i].method, req) == 0) {
leihen 14:7f9fbfc18623 207 // found the request
leihen 14:7f9fbfc18623 208 INFO("Request valid !!!\n");
leihen 14:7f9fbfc18623 209 request_msg_t* pmsg = m_requestPool.alloc();
leihen 14:7f9fbfc18623 210 pmsg->requestType = supportedOps[i].type;
leihen 14:7f9fbfc18623 211 strncpy(pmsg->requestUri, uri, 255);
leihen 14:7f9fbfc18623 212 return pmsg;
leihen 14:7f9fbfc18623 213 }
leihen 14:7f9fbfc18623 214 }
leihen 14:7f9fbfc18623 215 }
leihen 14:7f9fbfc18623 216
leihen 14:7f9fbfc18623 217 INFO("Invalid request \"%s\"\n", req);
leihen 14:7f9fbfc18623 218 return NULL;
leihen 14:7f9fbfc18623 219 }
leihen 14:7f9fbfc18623 220
leihen 14:7f9fbfc18623 221 void HttpServer::processMessageHeader(char* headerLine, char **fieldname, char **fieldvalue)
leihen 14:7f9fbfc18623 222 {
leihen 14:7f9fbfc18623 223 *fieldname = headerLine;
leihen 14:7f9fbfc18623 224 *fieldvalue = NULL;
leihen 14:7f9fbfc18623 225
leihen 14:7f9fbfc18623 226 while( *headerLine ) {
leihen 14:7f9fbfc18623 227 if (*headerLine == ':') {
leihen 14:7f9fbfc18623 228 *headerLine++ = 0;
leihen 14:7f9fbfc18623 229 while(*headerLine == ' ') headerLine++;
leihen 14:7f9fbfc18623 230 *fieldvalue = headerLine;
leihen 14:7f9fbfc18623 231 return;
leihen 14:7f9fbfc18623 232 }
leihen 14:7f9fbfc18623 233 headerLine++;
leihen 14:7f9fbfc18623 234 }
leihen 14:7f9fbfc18623 235 return ;
leihen 14:7f9fbfc18623 236 }
leihen 14:7f9fbfc18623 237
leihen 14:7f9fbfc18623 238
leihen 14:7f9fbfc18623 239 void HttpServer::listenForRequests()
leihen 14:7f9fbfc18623 240 {
leihen 14:7f9fbfc18623 241 static char data[256];
leihen 14:7f9fbfc18623 242 static int curPos = 0;
leihen 14:7f9fbfc18623 243 int CRLF = 0;
leihen 14:7f9fbfc18623 244 int m_openConnections = 0;
leihen 14:7f9fbfc18623 245
leihen 14:7f9fbfc18623 246 request_msg_t *pMsg = NULL;
leihen 14:7f9fbfc18623 247 INFO("Listener running\n");
leihen 14:7f9fbfc18623 248 bool asteriskReceivedOnce = false;
leihen 14:7f9fbfc18623 249 while(1) {
leihen 14:7f9fbfc18623 250 osEvent evt = m_queue.get();
leihen 14:7f9fbfc18623 251 if (evt.status == osEventMessage) {
leihen 14:7f9fbfc18623 252 char c;
leihen 14:7f9fbfc18623 253 c = (char)(int)evt.value.p;
leihen 14:7f9fbfc18623 254 if ((c!='\n') && (c!='\r')) {
leihen 14:7f9fbfc18623 255 data[curPos++] = c;
leihen 14:7f9fbfc18623 256 data[curPos] = 0;
leihen 14:7f9fbfc18623 257 }
leihen 14:7f9fbfc18623 258 if (pMsg != NULL) { // request was detected and will further be processed completely
leihen 14:7f9fbfc18623 259 // check for CRLF
leihen 14:7f9fbfc18623 260 if (c == '\n') {
leihen 14:7f9fbfc18623 261 CRLF++;
leihen 14:7f9fbfc18623 262 INFO("<CR>(%d)", CRLF);
leihen 14:7f9fbfc18623 263 if (CRLF == 2) { // all message headers received, so send message and be ready for new one
leihen 14:7f9fbfc18623 264 CRLF = 0;
leihen 14:7f9fbfc18623 265 // SPAWN MESSAGE
leihen 14:7f9fbfc18623 266 INFO("REQUEST COMPLETE --> Handing over to worker thread !\n\n\n\n");
leihen 14:7f9fbfc18623 267 m_requestQueue.put(pMsg);
leihen 14:7f9fbfc18623 268 data[0] = 0;
leihen 14:7f9fbfc18623 269 curPos = 0;
leihen 14:7f9fbfc18623 270 asteriskReceivedOnce = false;
leihen 14:7f9fbfc18623 271 pMsg = NULL;
leihen 14:7f9fbfc18623 272 } else { // must be a new header
leihen 14:7f9fbfc18623 273 // char *name, *value;
leihen 14:7f9fbfc18623 274 // INFO("Processing Header !\"%s\"", data);
leihen 14:7f9fbfc18623 275 /* processMessageHeader(data, &name, &value);
leihen 14:7f9fbfc18623 276 if (strncmp(name, "Content-Length", 14 ) == 0) {
leihen 14:7f9fbfc18623 277 // Data will be sent, be ready to receive
leihen 14:7f9fbfc18623 278 } else {
leihen 14:7f9fbfc18623 279 INFO("HEADER: Name=\"%s\", Value=\"%s\"", name, value);
leihen 14:7f9fbfc18623 280 }
leihen 14:7f9fbfc18623 281 */ data[0] = 0;
leihen 14:7f9fbfc18623 282 curPos = 0;
leihen 14:7f9fbfc18623 283 }
leihen 14:7f9fbfc18623 284 } else {
leihen 14:7f9fbfc18623 285 if (c != '\r')
leihen 14:7f9fbfc18623 286 CRLF = 0;
leihen 14:7f9fbfc18623 287 else
leihen 14:7f9fbfc18623 288 INFO("<LF>");
leihen 14:7f9fbfc18623 289 }
leihen 14:7f9fbfc18623 290 } else if (c == '*') {
leihen 14:7f9fbfc18623 291 CRLF = 0;
leihen 14:7f9fbfc18623 292 if (asteriskReceivedOnce) {
leihen 14:7f9fbfc18623 293 // could be an open, close or read command
leihen 14:7f9fbfc18623 294 if (curPos >= 6) { // only need to process if data is large enough
leihen 14:7f9fbfc18623 295 if ( (data[curPos-6] == '*') && (data[curPos-5] == 'O') && (data[curPos-4] == 'P') && (data[curPos-3] == 'E') && (data[curPos-2] == 'N') && (data[curPos-1] == '*')) {
leihen 14:7f9fbfc18623 296 // Add a connection
leihen 14:7f9fbfc18623 297 INFO("New connection opened (%d)...\n", ++m_openConnections);
leihen 14:7f9fbfc18623 298 data[0] = 0;
leihen 14:7f9fbfc18623 299 curPos = 0;
leihen 14:7f9fbfc18623 300 } else if ( (data[curPos-6] == '*') && (data[curPos-5] == 'C') && (data[curPos-4] == 'L') && (data[curPos-3] == 'O') && (data[curPos-2] == 'S') && (data[curPos-1] == '*')) {
leihen 14:7f9fbfc18623 301 // close a connection
leihen 14:7f9fbfc18623 302 INFO("Connection was closed ...(%d)\n", --m_openConnections);
leihen 14:7f9fbfc18623 303 data[0] = 0;
leihen 14:7f9fbfc18623 304 curPos = 0;
leihen 14:7f9fbfc18623 305 }
leihen 14:7f9fbfc18623 306 }
leihen 14:7f9fbfc18623 307 asteriskReceivedOnce = false;
leihen 14:7f9fbfc18623 308 } else { // set the indicator so that next time we'll check for valid connection commands
leihen 14:7f9fbfc18623 309 asteriskReceivedOnce = true;
leihen 14:7f9fbfc18623 310 }
leihen 14:7f9fbfc18623 311 } else { // first make sure that when no asterisk is received the asteriskReceivedOnce flag will be reset on each newline
leihen 14:7f9fbfc18623 312 if (c == '\n') {
leihen 14:7f9fbfc18623 313 if (m_openConnections > 0) {
leihen 14:7f9fbfc18623 314 // Check to see if we received a valid request
leihen 14:7f9fbfc18623 315 pMsg = checkMessageReceived(data);
leihen 14:7f9fbfc18623 316 if (pMsg == NULL) {
leihen 14:7f9fbfc18623 317 // not received valid stuff, so discard
leihen 14:7f9fbfc18623 318 INFO("Unrecognised data received : \"%s\"\n", data);
leihen 14:7f9fbfc18623 319 } else {
leihen 14:7f9fbfc18623 320 INFO("New request detected ! : \"%s\"\n", data);
leihen 14:7f9fbfc18623 321 }
leihen 14:7f9fbfc18623 322 } else {
leihen 14:7f9fbfc18623 323 INFO("Unrecognised data detected : \"%s\"\n", data);
leihen 14:7f9fbfc18623 324 }
leihen 14:7f9fbfc18623 325 asteriskReceivedOnce = false;
leihen 14:7f9fbfc18623 326 data[0] = 0;
leihen 14:7f9fbfc18623 327 curPos = 0;
leihen 14:7f9fbfc18623 328 CRLF = 1;
leihen 14:7f9fbfc18623 329 }
leihen 14:7f9fbfc18623 330 }
leihen 14:7f9fbfc18623 331 }
leihen 14:7f9fbfc18623 332 // else {
leihen 14:7f9fbfc18623 333 Thread::yield();
leihen 14:7f9fbfc18623 334 // }
leihen 14:7f9fbfc18623 335 }
leihen 14:7f9fbfc18623 336 }
leihen 14:7f9fbfc18623 337
leihen 14:7f9fbfc18623 338 void HttpServer::serveRequests()
leihen 14:7f9fbfc18623 339 {
leihen 14:7f9fbfc18623 340 HTTPConnection::HTTPMessage *myMessage = new HTTPConnection::HTTPMessage;
leihen 14:7f9fbfc18623 341
leihen 14:7f9fbfc18623 342 INFO("Server running\n");
leihen 14:7f9fbfc18623 343
leihen 14:7f9fbfc18623 344 while(1) {
leihen 14:7f9fbfc18623 345 INFO("Listening for new request !");
leihen 14:7f9fbfc18623 346 osEvent evt = m_requestQueue.get();
leihen 14:7f9fbfc18623 347 if (evt.status == osEventMessage) {
leihen 14:7f9fbfc18623 348 request_msg_t* pMsg = (request_msg_t*)evt.value.p;
leihen 14:7f9fbfc18623 349 m_worker->set_priority(osPriorityBelowNormal);
leihen 14:7f9fbfc18623 350 Thread::yield();
leihen 14:7f9fbfc18623 351 switch(pMsg->requestType) {
leihen 14:7f9fbfc18623 352 case msg_get:
leihen 14:7f9fbfc18623 353 INFO("Server received GET message !");
leihen 14:7f9fbfc18623 354 myMessage->request = HTTP_RT_GET;
leihen 14:7f9fbfc18623 355 myMessage->uri = pMsg->requestUri;
leihen 14:7f9fbfc18623 356 HandleRequest(myMessage);
leihen 14:7f9fbfc18623 357 Thread::yield();
leihen 14:7f9fbfc18623 358 break;
leihen 14:7f9fbfc18623 359
leihen 14:7f9fbfc18623 360 case msg_post:
leihen 14:7f9fbfc18623 361 case msg_put:
leihen 14:7f9fbfc18623 362 case msg_head:
leihen 14:7f9fbfc18623 363 case msg_delete:
leihen 14:7f9fbfc18623 364 case msg_trace:
leihen 14:7f9fbfc18623 365 case msg_options:
leihen 14:7f9fbfc18623 366 case msg_connect:
leihen 14:7f9fbfc18623 367 default:
leihen 14:7f9fbfc18623 368 break;
leihen 14:7f9fbfc18623 369 }
leihen 14:7f9fbfc18623 370 m_worker->set_priority(osPriorityNormal);
leihen 14:7f9fbfc18623 371 m_requestPool.free(pMsg);
leihen 14:7f9fbfc18623 372 }
leihen 14:7f9fbfc18623 373 Thread::yield();
leihen 14:7f9fbfc18623 374 }
leihen 14:7f9fbfc18623 375 }
leihen 14:7f9fbfc18623 376
leihen 14:7f9fbfc18623 377 bool HttpServer::parseRequest(char *request)
leihen 14:7f9fbfc18623 378 {
leihen 14:7f9fbfc18623 379 // dissect into : path, file[, [arg, value]1..N ] as "/path/file?arg1=val1&arg2=val2...
leihen 14:7f9fbfc18623 380 // first check for questionmark sign to separate the file and path from any arguments
leihen 14:7f9fbfc18623 381 char* path = request;
leihen 14:7f9fbfc18623 382 char* file = NULL;
leihen 14:7f9fbfc18623 383 char* arglist = NULL;
leihen 14:7f9fbfc18623 384
leihen 14:7f9fbfc18623 385 char* lastPathSep = NULL;
leihen 14:7f9fbfc18623 386 while(*request) {
leihen 14:7f9fbfc18623 387 if (*request == '/' )
leihen 14:7f9fbfc18623 388 lastPathSep = request;
leihen 14:7f9fbfc18623 389 if (*request == '?') {
leihen 14:7f9fbfc18623 390 *request++ = 0;
leihen 14:7f9fbfc18623 391 arglist = request;
leihen 14:7f9fbfc18623 392 }
leihen 14:7f9fbfc18623 393 }
leihen 14:7f9fbfc18623 394
leihen 14:7f9fbfc18623 395 if (arglist == NULL) {
leihen 14:7f9fbfc18623 396 INFO("Request does not have parameters !");
leihen 14:7f9fbfc18623 397 }
leihen 14:7f9fbfc18623 398
leihen 14:7f9fbfc18623 399 if (lastPathSep == NULL)
leihen 14:7f9fbfc18623 400 return false; // no path provided !!!!
leihen 14:7f9fbfc18623 401
leihen 14:7f9fbfc18623 402 // now, whatever is provided to the left including the slash is the 'path', the part to the right is the file. caution: the file may be left blank !
leihen 14:7f9fbfc18623 403 if (lastPathSep != 0) {
leihen 14:7f9fbfc18623 404 // 2 cases to handle :
leihen 14:7f9fbfc18623 405 // 1. : "/blah/" or "/blah/blub/" --> path = "/blah/", file = "index.html"
leihen 14:7f9fbfc18623 406 // 2. : "/blah/blub" or "/blah/blub/blubber" --> path = "/blah/", file = "blub"
leihen 14:7f9fbfc18623 407 } else {
leihen 14:7f9fbfc18623 408 // 2 cases to handle :
leihen 14:7f9fbfc18623 409 // 1. : "/" --> path = "/", file = "index.html"
leihen 14:7f9fbfc18623 410 // 2. : "/blah" --> path = "/", file = "blah"
leihen 14:7f9fbfc18623 411 }
leihen 14:7f9fbfc18623 412 return true;
leihen 14:7f9fbfc18623 413 }
leihen 14:7f9fbfc18623 414
leihen 14:7f9fbfc18623 415
leihen 14:7f9fbfc18623 416 void HttpServer::listen_thread(const void *params)
leihen 14:7f9fbfc18623 417 {
leihen 14:7f9fbfc18623 418 HttpServer* pSvr = (HttpServer*)params;
leihen 14:7f9fbfc18623 419
leihen 14:7f9fbfc18623 420 pSvr->listenForRequests();
leihen 14:7f9fbfc18623 421 }
leihen 14:7f9fbfc18623 422
leihen 14:7f9fbfc18623 423 void HttpServer::worker_thread(const void * params)
leihen 14:7f9fbfc18623 424 {
leihen 14:7f9fbfc18623 425 HttpServer* pSvr = (HttpServer*)params;
leihen 14:7f9fbfc18623 426
leihen 14:7f9fbfc18623 427 pSvr->serveRequests();
leihen 14:7f9fbfc18623 428 }
leihen 14:7f9fbfc18623 429
leihen 14:7f9fbfc18623 430
leihen 14:7f9fbfc18623 431
leihen 14:7f9fbfc18623 432
leihen 14:7f9fbfc18623 433 static const char* szStdErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error 404</h1><P>This resource is not available<P></BODY></HTML>\r\n\r\n";
leihen 14:7f9fbfc18623 434
leihen 14:7f9fbfc18623 435 void HttpServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg)
leihen 14:7f9fbfc18623 436 {
leihen 14:7f9fbfc18623 437 char echoHeader[256];
leihen 14:7f9fbfc18623 438 sprintf(echoHeader,"HTTP/1.0 404 Fail\r\nConnection: close\r\nContent-Length: %d\r\nContent-Type: text/html\r\nServer: mbed embedded\r\n\n\r",strlen(szStdErrorPage));
leihen 14:7f9fbfc18623 439
leihen 14:7f9fbfc18623 440 Wifly::getInstance()->sendData(echoHeader, strlen(echoHeader));
leihen 14:7f9fbfc18623 441 Wifly::getInstance()->sendData((char*)szStdErrorPage, strlen(szStdErrorPage));
leihen 14:7f9fbfc18623 442 }
leihen 14:7f9fbfc18623 443
leihen 14:7f9fbfc18623 444 void HttpServer::HandleRequest(HTTPConnection::HTTPMessage* pmsg)
leihen 14:7f9fbfc18623 445 {
leihen 14:7f9fbfc18623 446 static std::string localPath;
leihen 14:7f9fbfc18623 447 static std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&), handlersComp>::const_iterator it;
leihen 14:7f9fbfc18623 448
leihen 14:7f9fbfc18623 449 INFO("Trying to handle request");
leihen 14:7f9fbfc18623 450 // Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
leihen 14:7f9fbfc18623 451 for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
leihen 14:7f9fbfc18623 452 // check if this entries' path is fully contained at the beginning of the requested path
leihen 14:7f9fbfc18623 453 std::string curpth = it->first;
leihen 14:7f9fbfc18623 454
leihen 14:7f9fbfc18623 455 if (pmsg->uri.find(curpth) == 0) {
leihen 14:7f9fbfc18623 456 // firts matching handler found, we just take it and we'll be happy
leihen 14:7f9fbfc18623 457 localPath = pmsg->uri.substr(curpth.length());
leihen 14:7f9fbfc18623 458 break;
leihen 14:7f9fbfc18623 459 }
leihen 14:7f9fbfc18623 460 }
leihen 14:7f9fbfc18623 461
leihen 14:7f9fbfc18623 462 if (it == m_lpHandlers.end()) {
leihen 14:7f9fbfc18623 463 // There is no such handler, so return invalid
leihen 14:7f9fbfc18623 464 INFO("Webrequest left unhandled.");
leihen 14:7f9fbfc18623 465
leihen 14:7f9fbfc18623 466 m_pErrorHandler(*pmsg);
leihen 14:7f9fbfc18623 467 } else {
leihen 14:7f9fbfc18623 468 // Valid handler was found
leihen 14:7f9fbfc18623 469 INFO("Routing webrequest !");
leihen 14:7f9fbfc18623 470 // Instantiate the handler object (handling will be done from withing the object's constructor
leihen 14:7f9fbfc18623 471 HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), *pmsg);
leihen 14:7f9fbfc18623 472 // now we can delete the object, because handling is completed.
leihen 14:7f9fbfc18623 473 if (phdl != NULL)
leihen 14:7f9fbfc18623 474 delete phdl;
leihen 14:7f9fbfc18623 475 }
leihen 14:7f9fbfc18623 476 }
leihen 14:7f9fbfc18623 477