Single instance HTTP Server using new Ethernet Interface. Blocking mode only; this improved stability, but the HTTP server must be started from a separate thread.

Dependents:   SmartLight

Fork of HTTPServer by Henry Leinen

Committer:
leihen
Date:
Tue May 28 01:56:14 2013 +0000
Revision:
3:d6224049b3bf
Parent:
2:8653bbcf7e58
Child:
4:d065642c32cc
First beta version

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 0:7a2421e63e74 4 DigitalOut led1(LED1);
leihen 0:7a2421e63e74 5 DigitalOut led2(LED2);
leihen 0:7a2421e63e74 6 DigitalOut led3(LED3);
leihen 0:7a2421e63e74 7 DigitalOut led4(LED4);
leihen 0:7a2421e63e74 8
leihen 3:d6224049b3bf 9 #if (1 && !defined(TARGET_LPC11U24))
leihen 0:7a2421e63e74 10 #define INFO(x, ...) if (m_pDbg) m_pDbg->printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__); else printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 11 #define WARN(x, ...) if (m_pDbg) m_pDbg->printf("[HttpServer : WARN]"x"\r\n", ##__VA_ARGS__); else printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 12 #define ERR(x, ...) if (m_pDbg) m_pDbg->printf("[HttpServer : ERR]"x"\r\n", ##__VA_ARGS__); else printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
leihen 0:7a2421e63e74 13 #else
leihen 0:7a2421e63e74 14 #define INFO(x, ...)
leihen 0:7a2421e63e74 15 #define WARN(x, ...)
leihen 0:7a2421e63e74 16 #define ERR(x, ...)
leihen 0:7a2421e63e74 17 #endif
leihen 0:7a2421e63e74 18
leihen 3:d6224049b3bf 19 HTTPServer::HTTPServer(Serial *dbg)
leihen 0:7a2421e63e74 20 {
leihen 3:d6224049b3bf 21 m_pDbg = dbg;
leihen 0:7a2421e63e74 22 m_pSvr = NULL;
leihen 0:7a2421e63e74 23 m_bServerListening = false;
leihen 2:8653bbcf7e58 24 m_pErrorHandler = StdErrorHandler;
leihen 0:7a2421e63e74 25 }
leihen 0:7a2421e63e74 26
leihen 0:7a2421e63e74 27 HTTPServer::~HTTPServer()
leihen 0:7a2421e63e74 28 {
leihen 0:7a2421e63e74 29 if (m_pSvr) {
leihen 0:7a2421e63e74 30 delete m_pSvr;
leihen 0:7a2421e63e74 31 m_pSvr = NULL;
leihen 0:7a2421e63e74 32 m_bServerListening = false;
leihen 0:7a2421e63e74 33 }
leihen 0:7a2421e63e74 34 }
leihen 0:7a2421e63e74 35
leihen 2:8653bbcf7e58 36
leihen 2:8653bbcf7e58 37 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 38
leihen 3:d6224049b3bf 39 void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 2:8653bbcf7e58 40 {
leihen 2:8653bbcf7e58 41 char echoHeader[512];
leihen 2:8653bbcf7e58 42
leihen 2:8653bbcf7e58 43 tcp.set_blocking(true, 1500);
leihen 2:8653bbcf7e58 44 sprintf(echoHeader,"HTTP/1.1 404 Fail\r\nContent-Length: %d\r\nContent-Type: text/html\r\nServer: mbed embedded\r\n\n\r",strlen(szStdErrorPage));
leihen 2:8653bbcf7e58 45 tcp.send(echoHeader, strlen(echoHeader));
leihen 2:8653bbcf7e58 46 tcp.send((char*)szStdErrorPage, strlen(szStdErrorPage));
leihen 2:8653bbcf7e58 47 }
leihen 2:8653bbcf7e58 48
leihen 2:8653bbcf7e58 49
leihen 0:7a2421e63e74 50 int HTTPServer::start(int port)
leihen 0:7a2421e63e74 51 {
leihen 0:7a2421e63e74 52 // check if the start member was called already once
leihen 0:7a2421e63e74 53 if (m_pSvr != NULL) {
leihen 0:7a2421e63e74 54 ERR("start function was already called, server is already in listening state.");
leihen 0:7a2421e63e74 55 return -1;
leihen 0:7a2421e63e74 56 }
leihen 0:7a2421e63e74 57
leihen 0:7a2421e63e74 58 m_bServerListening = false;
leihen 0:7a2421e63e74 59
leihen 0:7a2421e63e74 60 // Create a new server object
leihen 0:7a2421e63e74 61 m_pSvr = new TCPSocketServer();
leihen 0:7a2421e63e74 62
leihen 0:7a2421e63e74 63 // Bind the local server to the given port
leihen 0:7a2421e63e74 64 if (m_pSvr->bind(port) < 0) {
leihen 0:7a2421e63e74 65 ERR("Failed to bind to port %d\n", port);
leihen 0:7a2421e63e74 66 return -1;
leihen 0:7a2421e63e74 67 }
leihen 0:7a2421e63e74 68 else {
leihen 0:7a2421e63e74 69 INFO("Binding succeeded !\n");
leihen 0:7a2421e63e74 70 }
leihen 0:7a2421e63e74 71
leihen 0:7a2421e63e74 72 // Listen to a maximum of 10 concurrent connections
leihen 0:7a2421e63e74 73 if (m_pSvr->listen(1) < 0) {
leihen 0:7a2421e63e74 74 ERR("Faild to listen !\n");
leihen 0:7a2421e63e74 75 delete m_pSvr;
leihen 0:7a2421e63e74 76 m_pSvr = NULL;
leihen 0:7a2421e63e74 77 return -1;
leihen 0:7a2421e63e74 78 }
leihen 0:7a2421e63e74 79 else {
leihen 0:7a2421e63e74 80 INFO("Listening\n");
leihen 0:7a2421e63e74 81 m_bServerListening = true;
leihen 0:7a2421e63e74 82 }
leihen 0:7a2421e63e74 83
leihen 0:7a2421e63e74 84 // set into non blocking operation
leihen 0:7a2421e63e74 85 m_pSvr->set_blocking(false, 100);
leihen 0:7a2421e63e74 86
leihen 0:7a2421e63e74 87 return 0;
leihen 0:7a2421e63e74 88 }
leihen 0:7a2421e63e74 89
leihen 0:7a2421e63e74 90
leihen 0:7a2421e63e74 91 int HTTPServer::poll()
leihen 0:7a2421e63e74 92 {
leihen 0:7a2421e63e74 93 INFO("Listening for new connection requests.");
leihen 0:7a2421e63e74 94
leihen 0:7a2421e63e74 95 // This thread basically checks if there is a new incoming connection.
leihen 0:7a2421e63e74 96 // If so , a new HTTPConnection is created and the connection thread is started.
leihen 0:7a2421e63e74 97 TCPSocketConnection Clnt;
leihen 0:7a2421e63e74 98
leihen 0:7a2421e63e74 99 led4 = 1; // Indicate we are waiting for a new connection
leihen 0:7a2421e63e74 100 if (m_pSvr->accept(Clnt) < 0) {
leihen 0:7a2421e63e74 101 // an error occured
leihen 0:7a2421e63e74 102 ERR("There was an error, Accept returned with an error. Probably the connection to the router was lost. Shutting down server");
leihen 0:7a2421e63e74 103 led2 = 0;
leihen 0:7a2421e63e74 104 m_bServerListening = false;
leihen 0:7a2421e63e74 105 m_pSvr->close();
leihen 0:7a2421e63e74 106 delete m_pSvr;
leihen 0:7a2421e63e74 107 m_pSvr = NULL;
leihen 0:7a2421e63e74 108 led4 = 0;
leihen 0:7a2421e63e74 109 led3 = 1; // ERROR
leihen 0:7a2421e63e74 110 led2 = 0;
leihen 0:7a2421e63e74 111 led1 = 0;
leihen 0:7a2421e63e74 112 return -1;
leihen 0:7a2421e63e74 113 }
leihen 0:7a2421e63e74 114 else {
leihen 0:7a2421e63e74 115 led4 = 0;
leihen 0:7a2421e63e74 116 // a new connection was received
leihen 0:7a2421e63e74 117 INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
leihen 0:7a2421e63e74 118 // Start the main connection thread
leihen 0:7a2421e63e74 119 led3 = 1;
leihen 0:7a2421e63e74 120 led2 = 1;
leihen 0:7a2421e63e74 121 HTTPConnection con;
leihen 0:7a2421e63e74 122 int c = con.poll();
leihen 0:7a2421e63e74 123 if (c == 0) {
leihen 1:6b7472d5e9ee 124 // Handle the request
leihen 1:6b7472d5e9ee 125 HandleRequest(con.m_Msg, Clnt);
leihen 0:7a2421e63e74 126 }
leihen 0:7a2421e63e74 127 led2 = 0;
leihen 0:7a2421e63e74 128 led3 = 0;
leihen 0:7a2421e63e74 129 }
leihen 0:7a2421e63e74 130
leihen 0:7a2421e63e74 131 INFO("Leaving polling thread");
leihen 0:7a2421e63e74 132 return 0;
leihen 1:6b7472d5e9ee 133 }
leihen 1:6b7472d5e9ee 134
leihen 3:d6224049b3bf 135 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 3:d6224049b3bf 136 {
leihen 3:d6224049b3bf 137 std::string localPath;
leihen 3:d6224049b3bf 138 std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp>::const_iterator it;
leihen 3:d6224049b3bf 139
leihen 3:d6224049b3bf 140 for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
leihen 3:d6224049b3bf 141 // check if this entries' path is fully contained at the beginning of the requested path
leihen 3:d6224049b3bf 142 std::string curpth = it->first;
leihen 3:d6224049b3bf 143
leihen 3:d6224049b3bf 144 if (msg.uri.find(curpth) == 0) {
leihen 3:d6224049b3bf 145 // handler found
leihen 3:d6224049b3bf 146 localPath = msg.uri.substr(curpth.length());
leihen 3:d6224049b3bf 147 break;
leihen 3:d6224049b3bf 148 }
leihen 3:d6224049b3bf 149 }
leihen 3:d6224049b3bf 150
leihen 3:d6224049b3bf 151 if (it == m_lpHandlers.end()) {
leihen 3:d6224049b3bf 152 // There is no such handler, so return invalid
leihen 3:d6224049b3bf 153
leihen 3:d6224049b3bf 154 m_pErrorHandler(msg, tcp);
leihen 3:d6224049b3bf 155 INFO("Webrequest left unhandled.");
leihen 3:d6224049b3bf 156 }
leihen 3:d6224049b3bf 157 else {
leihen 3:d6224049b3bf 158 INFO("Routing webrequest !");
leihen 3:d6224049b3bf 159
leihen 3:d6224049b3bf 160 HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp);
leihen 3:d6224049b3bf 161 if (phdl != NULL)
leihen 3:d6224049b3bf 162 delete phdl;
leihen 3:d6224049b3bf 163 }
leihen 3:d6224049b3bf 164
leihen 3:d6224049b3bf 165 }
leihen 3:d6224049b3bf 166 /*
leihen 3:d6224049b3bf 167 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 1:6b7472d5e9ee 168 {
leihen 1:6b7472d5e9ee 169 map<string, HTTPRequestHandlerFunction>::iterator it;
leihen 1:6b7472d5e9ee 170
leihen 1:6b7472d5e9ee 171 it = m_pHandlers.find(msg.uri);
leihen 1:6b7472d5e9ee 172
leihen 1:6b7472d5e9ee 173 if (it == m_pHandlers.end()) {
leihen 1:6b7472d5e9ee 174 // There is no such handler, so return invalid
leihen 2:8653bbcf7e58 175
leihen 2:8653bbcf7e58 176 m_pErrorHandler(msg, tcp);
leihen 1:6b7472d5e9ee 177 INFO("Webrequest left unhandled.");
leihen 1:6b7472d5e9ee 178 }
leihen 1:6b7472d5e9ee 179 else {
leihen 1:6b7472d5e9ee 180 // Handler was found so pass action to handler
leihen 1:6b7472d5e9ee 181 INFO("Routing webrequest !");
leihen 1:6b7472d5e9ee 182 (it->second)(msg, tcp);
leihen 1:6b7472d5e9ee 183 }
leihen 3:d6224049b3bf 184 }
leihen 3:d6224049b3bf 185 */