Team E1

Fork of HTTPServer by Sam Kirsch

Committer:
leihen
Date:
Wed Jun 05 23:39:24 2013 +0000
Revision:
12:ba81cc117fb6
Parent:
11:3943841e1798
Child:
13:aa5338a5e452
Improved throughput of data.
; fixed incorrect Header handling.
; Fixed Support for other FileSystem Handler

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 0:7a2421e63e74 1 #include "mbed.h"
leihen 0:7a2421e63e74 2 #include "HTTPServer.h"
leihen 0:7a2421e63e74 3
leihen 11:3943841e1798 4 #define _DEBUG 0
leihen 4:d065642c32cc 5
leihen 4:d065642c32cc 6 #ifdef _DEBUG
leihen 0:7a2421e63e74 7 DigitalOut led1(LED1);
leihen 0:7a2421e63e74 8 DigitalOut led2(LED2);
leihen 0:7a2421e63e74 9 DigitalOut led3(LED3);
leihen 0:7a2421e63e74 10 DigitalOut led4(LED4);
leihen 4:d065642c32cc 11 #endif
leihen 0:7a2421e63e74 12
leihen 4:d065642c32cc 13 #if (_DEBUG && !defined(TARGET_LPC11U24))
leihen 9:c2a1462b9b71 14 #define INFO(x, ...) std::printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
leihen 9:c2a1462b9b71 15 #define WARN(x, ...) std::printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
leihen 9:c2a1462b9b71 16 #define ERR(x, ...) std::printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 17 #else
leihen 0:7a2421e63e74 18 #define INFO(x, ...)
leihen 0:7a2421e63e74 19 #define WARN(x, ...)
leihen 0:7a2421e63e74 20 #define ERR(x, ...)
leihen 0:7a2421e63e74 21 #endif
leihen 0:7a2421e63e74 22
leihen 4:d065642c32cc 23
leihen 4:d065642c32cc 24 /* Constructor */
leihen 4:d065642c32cc 25 /* initialize all members and set the standard error handler. */
leihen 9:c2a1462b9b71 26 HTTPServer::HTTPServer(PinName tx, PinName rx, PinName reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec)
leihen 9:c2a1462b9b71 27 : m_wifly(tx, rx, reset, tcp_status, ssid, phrase, sec)
leihen 0:7a2421e63e74 28 {
leihen 9:c2a1462b9b71 29 m_pErrorHandler = StdErrorHandler;
leihen 0:7a2421e63e74 30 m_pSvr = NULL;
leihen 0:7a2421e63e74 31 }
leihen 0:7a2421e63e74 32
leihen 0:7a2421e63e74 33 HTTPServer::~HTTPServer()
leihen 0:7a2421e63e74 34 {
leihen 0:7a2421e63e74 35 if (m_pSvr) {
leihen 0:7a2421e63e74 36 delete m_pSvr;
leihen 0:7a2421e63e74 37 m_pSvr = NULL;
leihen 0:7a2421e63e74 38 }
leihen 0:7a2421e63e74 39 }
leihen 0:7a2421e63e74 40
leihen 2:8653bbcf7e58 41
leihen 4:d065642c32cc 42 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 2:8653bbcf7e58 43
leihen 3:d6224049b3bf 44 void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 2:8653bbcf7e58 45 {
leihen 4:d065642c32cc 46 char echoHeader[256];
leihen 2:8653bbcf7e58 47 tcp.set_blocking(true, 1500);
leihen 11:3943841e1798 48 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 2:8653bbcf7e58 49 tcp.send(echoHeader, strlen(echoHeader));
leihen 2:8653bbcf7e58 50 tcp.send((char*)szStdErrorPage, strlen(szStdErrorPage));
leihen 2:8653bbcf7e58 51 }
leihen 2:8653bbcf7e58 52
leihen 2:8653bbcf7e58 53
leihen 0:7a2421e63e74 54 int HTTPServer::start(int port)
leihen 0:7a2421e63e74 55 {
leihen 0:7a2421e63e74 56 // check if the start member was called already once
leihen 0:7a2421e63e74 57 if (m_pSvr != NULL) {
leihen 0:7a2421e63e74 58 ERR("start function was already called, server is already in listening state.");
leihen 0:7a2421e63e74 59 return -1;
leihen 0:7a2421e63e74 60 }
leihen 9:c2a1462b9b71 61 INFO("Initializing wifly\n");
leihen 9:c2a1462b9b71 62 // Initialize the wifly wlan device
leihen 9:c2a1462b9b71 63 m_wifly.init();
leihen 9:c2a1462b9b71 64
leihen 9:c2a1462b9b71 65 INFO("Connecting to network...");
leihen 9:c2a1462b9b71 66 // Try join the network
leihen 11:3943841e1798 67 while(!m_wifly.connect()) {
leihen 11:3943841e1798 68 INFO("Failed to connect. Trying again\n");
leihen 11:3943841e1798 69 m_wifly.reset();
leihen 11:3943841e1798 70 }
leihen 9:c2a1462b9b71 71 INFO("connected\n");
leihen 9:c2a1462b9b71 72
leihen 9:c2a1462b9b71 73 // check if the start member was called already once
leihen 9:c2a1462b9b71 74 if (m_pSvr != NULL) {
leihen 9:c2a1462b9b71 75 ERR("start function was already called, server is already in listening state.");
leihen 9:c2a1462b9b71 76 return -1;
leihen 9:c2a1462b9b71 77 }
leihen 0:7a2421e63e74 78
leihen 0:7a2421e63e74 79 // Create a new server object
leihen 0:7a2421e63e74 80 m_pSvr = new TCPSocketServer();
leihen 0:7a2421e63e74 81
leihen 0:7a2421e63e74 82 // Bind the local server to the given port
leihen 0:7a2421e63e74 83 if (m_pSvr->bind(port) < 0) {
leihen 0:7a2421e63e74 84 ERR("Failed to bind to port %d\n", port);
leihen 0:7a2421e63e74 85 return -1;
leihen 0:7a2421e63e74 86 }
leihen 0:7a2421e63e74 87 else {
leihen 0:7a2421e63e74 88 INFO("Binding succeeded !\n");
leihen 0:7a2421e63e74 89 }
leihen 0:7a2421e63e74 90
leihen 0:7a2421e63e74 91 // Listen to a maximum of 10 concurrent connections
leihen 0:7a2421e63e74 92 if (m_pSvr->listen(1) < 0) {
leihen 0:7a2421e63e74 93 ERR("Faild to listen !\n");
leihen 0:7a2421e63e74 94 delete m_pSvr;
leihen 0:7a2421e63e74 95 m_pSvr = NULL;
leihen 0:7a2421e63e74 96 return -1;
leihen 0:7a2421e63e74 97 }
leihen 0:7a2421e63e74 98 else {
leihen 0:7a2421e63e74 99 INFO("Listening\n");
leihen 0:7a2421e63e74 100 }
leihen 0:7a2421e63e74 101
leihen 0:7a2421e63e74 102 // set into non blocking operation
leihen 0:7a2421e63e74 103 m_pSvr->set_blocking(false, 100);
leihen 0:7a2421e63e74 104
leihen 0:7a2421e63e74 105 return 0;
leihen 0:7a2421e63e74 106 }
leihen 0:7a2421e63e74 107
leihen 0:7a2421e63e74 108
leihen 6:fe661fa9d18a 109 int HTTPServer::poll(bool blocking)
leihen 0:7a2421e63e74 110 {
leihen 5:dc88012caef1 111 int retval = -1;
leihen 0:7a2421e63e74 112 INFO("Listening for new connection requests.");
leihen 0:7a2421e63e74 113
leihen 0:7a2421e63e74 114 // This thread basically checks if there is a new incoming connection.
leihen 0:7a2421e63e74 115 // If so , a new HTTPConnection is created and the connection thread is started.
leihen 0:7a2421e63e74 116 TCPSocketConnection Clnt;
leihen 0:7a2421e63e74 117
leihen 4:d065642c32cc 118 #ifdef _DEBUG
leihen 0:7a2421e63e74 119 led4 = 1; // Indicate we are waiting for a new connection
leihen 5:dc88012caef1 120 #endif
leihen 6:fe661fa9d18a 121 m_pSvr->set_blocking(blocking);
leihen 5:dc88012caef1 122 retval = m_pSvr->accept(Clnt);
leihen 5:dc88012caef1 123 if (retval > 0) {
leihen 5:dc88012caef1 124 // no connection availale yet, so just return
leihen 5:dc88012caef1 125 #ifdef _DEBUG
leihen 5:dc88012caef1 126 led4 = 0;
leihen 5:dc88012caef1 127 led3 = 0;
leihen 5:dc88012caef1 128 led2 = 0;
leihen 5:dc88012caef1 129 #endif
leihen 5:dc88012caef1 130 return retval;
leihen 5:dc88012caef1 131 }
leihen 5:dc88012caef1 132 if ( retval < 0) {
leihen 0:7a2421e63e74 133 // an error occured
leihen 0:7a2421e63e74 134 ERR("There was an error, Accept returned with an error. Probably the connection to the router was lost. Shutting down server");
leihen 4:d065642c32cc 135 #ifdef _DEBUG
leihen 0:7a2421e63e74 136 led2 = 0;
leihen 4:d065642c32cc 137 #endif
leihen 0:7a2421e63e74 138 m_pSvr->close();
leihen 0:7a2421e63e74 139 delete m_pSvr;
leihen 0:7a2421e63e74 140 m_pSvr = NULL;
leihen 4:d065642c32cc 141 #ifdef _DEBUG
leihen 0:7a2421e63e74 142 led4 = 0;
leihen 0:7a2421e63e74 143 led3 = 1; // ERROR
leihen 0:7a2421e63e74 144 led2 = 0;
leihen 0:7a2421e63e74 145 led1 = 0;
leihen 4:d065642c32cc 146 #endif
leihen 0:7a2421e63e74 147 return -1;
leihen 0:7a2421e63e74 148 }
leihen 0:7a2421e63e74 149 else {
leihen 4:d065642c32cc 150 #ifdef _DEBUG
leihen 0:7a2421e63e74 151 led4 = 0;
leihen 4:d065642c32cc 152 #endif
leihen 0:7a2421e63e74 153 // a new connection was received
leihen 0:7a2421e63e74 154 INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
leihen 0:7a2421e63e74 155 // Start the main connection thread
leihen 11:3943841e1798 156 // while(1) {
leihen 11:3943841e1798 157
leihen 11:3943841e1798 158 #ifdef _DEBUG
leihen 11:3943841e1798 159 led3 = 1;
leihen 11:3943841e1798 160 led2 = 1;
leihen 11:3943841e1798 161 #endif
leihen 11:3943841e1798 162 HTTPConnection con;
leihen 11:3943841e1798 163 int c = con.poll();
leihen 11:3943841e1798 164 if (c == 0) {
leihen 11:3943841e1798 165 // Handle the request
leihen 11:3943841e1798 166 HandleRequest(con.m_Msg, Clnt);
leihen 12:ba81cc117fb6 167 // INFO("Closing connection.\n");
leihen 11:3943841e1798 168 // if (!m_wifly.close()) {
leihen 11:3943841e1798 169 // ERR("Failed to close connection !\n");
leihen 11:3943841e1798 170 // }
leihen 11:3943841e1798 171 }
leihen 11:3943841e1798 172 if (c == -1) {
leihen 11:3943841e1798 173 // No more data available or error
leihen 11:3943841e1798 174 // break;
leihen 11:3943841e1798 175 }
leihen 11:3943841e1798 176 #ifdef _DEBUG
leihen 11:3943841e1798 177 led2 = 0;
leihen 11:3943841e1798 178 led3 = 0;
leihen 11:3943841e1798 179 #endif
leihen 11:3943841e1798 180 // }
leihen 0:7a2421e63e74 181 }
leihen 0:7a2421e63e74 182
leihen 0:7a2421e63e74 183 INFO("Leaving polling thread");
leihen 0:7a2421e63e74 184 return 0;
leihen 1:6b7472d5e9ee 185 }
leihen 1:6b7472d5e9ee 186
leihen 3:d6224049b3bf 187 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 3:d6224049b3bf 188 {
leihen 3:d6224049b3bf 189 std::string localPath;
leihen 3:d6224049b3bf 190 std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp>::const_iterator it;
leihen 3:d6224049b3bf 191
leihen 4:d065642c32cc 192 // Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
leihen 3:d6224049b3bf 193 for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
leihen 3:d6224049b3bf 194 // check if this entries' path is fully contained at the beginning of the requested path
leihen 3:d6224049b3bf 195 std::string curpth = it->first;
leihen 3:d6224049b3bf 196
leihen 3:d6224049b3bf 197 if (msg.uri.find(curpth) == 0) {
leihen 4:d065642c32cc 198 // firts matching handler found, we just take it and we'll be happy
leihen 3:d6224049b3bf 199 localPath = msg.uri.substr(curpth.length());
leihen 3:d6224049b3bf 200 break;
leihen 3:d6224049b3bf 201 }
leihen 3:d6224049b3bf 202 }
leihen 3:d6224049b3bf 203
leihen 3:d6224049b3bf 204 if (it == m_lpHandlers.end()) {
leihen 3:d6224049b3bf 205 // There is no such handler, so return invalid
leihen 3:d6224049b3bf 206
leihen 3:d6224049b3bf 207 m_pErrorHandler(msg, tcp);
leihen 3:d6224049b3bf 208 INFO("Webrequest left unhandled.");
leihen 3:d6224049b3bf 209 }
leihen 3:d6224049b3bf 210 else {
leihen 4:d065642c32cc 211 // Valid handler was found
leihen 3:d6224049b3bf 212 INFO("Routing webrequest !");
leihen 4:d065642c32cc 213 // Instantiate the handler object (handling will be done from withing the object's constructor
leihen 3:d6224049b3bf 214 HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp);
leihen 4:d065642c32cc 215 // now we can delete the object, because handling is completed.
leihen 3:d6224049b3bf 216 if (phdl != NULL)
leihen 3:d6224049b3bf 217 delete phdl;
leihen 3:d6224049b3bf 218 }
leihen 3:d6224049b3bf 219 }