Henry Leinen / Mbed 2 deprecated MultiThreadingHTTPServer

Dependencies:   WiFlyHTTPServer WiflyInterface mbed-rpc mbed-rtos mbed

Committer:
leihen
Date:
Wed Jun 26 21:13:55 2013 +0000
Revision:
0:9c6ebc97c758
Working Multithreaded HTTP Server

Who changed what in which revision?

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