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:
Sat Jun 22 15:41:34 2013 +0000
Revision:
13:aa5338a5e452
Parent:
12:ba81cc117fb6
Child:
14:011edcd33e86
First Version of a working Ethernet HTTP Server.

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 13:aa5338a5e452 3 #define DEBUG
leihen 13:aa5338a5e452 4 #include "debug.h"
leihen 0:7a2421e63e74 5
leihen 13:aa5338a5e452 6 #define _DEBUG 1
leihen 4:d065642c32cc 7
leihen 4:d065642c32cc 8 #ifdef _DEBUG
leihen 0:7a2421e63e74 9 DigitalOut led1(LED1);
leihen 0:7a2421e63e74 10 DigitalOut led2(LED2);
leihen 0:7a2421e63e74 11 DigitalOut led3(LED3);
leihen 0:7a2421e63e74 12 DigitalOut led4(LED4);
leihen 4:d065642c32cc 13 #endif
leihen 0:7a2421e63e74 14
leihen 13:aa5338a5e452 15 static EthernetInterface eth;
leihen 4:d065642c32cc 16
leihen 4:d065642c32cc 17 /* Constructor */
leihen 4:d065642c32cc 18 /* initialize all members and set the standard error handler. */
leihen 13:aa5338a5e452 19 HTTPServer::HTTPServer()
leihen 0:7a2421e63e74 20 {
leihen 9:c2a1462b9b71 21 m_pErrorHandler = StdErrorHandler;
leihen 0:7a2421e63e74 22 }
leihen 0:7a2421e63e74 23
leihen 0:7a2421e63e74 24 HTTPServer::~HTTPServer()
leihen 0:7a2421e63e74 25 {
leihen 0:7a2421e63e74 26 }
leihen 0:7a2421e63e74 27
leihen 2:8653bbcf7e58 28
leihen 4:d065642c32cc 29 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 30
leihen 3:d6224049b3bf 31 void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 2:8653bbcf7e58 32 {
leihen 4:d065642c32cc 33 char echoHeader[256];
leihen 2:8653bbcf7e58 34 tcp.set_blocking(true, 1500);
leihen 11:3943841e1798 35 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 36 tcp.send(echoHeader, strlen(echoHeader));
leihen 2:8653bbcf7e58 37 tcp.send((char*)szStdErrorPage, strlen(szStdErrorPage));
leihen 2:8653bbcf7e58 38 }
leihen 2:8653bbcf7e58 39
leihen 2:8653bbcf7e58 40
leihen 13:aa5338a5e452 41 bool HTTPServer::start(int port)
leihen 0:7a2421e63e74 42 {
leihen 13:aa5338a5e452 43 INFO("Initializing network\n");
leihen 13:aa5338a5e452 44 eth.init();
leihen 9:c2a1462b9b71 45
leihen 9:c2a1462b9b71 46 INFO("Connecting to network...");
leihen 13:aa5338a5e452 47 eth.connect();
leihen 9:c2a1462b9b71 48
leihen 13:aa5338a5e452 49 INFO("Binding to port %d...", port);
leihen 13:aa5338a5e452 50 if (m_Svr.bind(port) < 0) {
leihen 13:aa5338a5e452 51 ERR("Failed to bind to port !\n");
leihen 13:aa5338a5e452 52 error("Binding");
leihen 13:aa5338a5e452 53 return false;
leihen 0:7a2421e63e74 54 }
leihen 0:7a2421e63e74 55
leihen 13:aa5338a5e452 56 INFO("Listening ...");
leihen 13:aa5338a5e452 57 if (m_Svr.listen(1) < 0) {
leihen 13:aa5338a5e452 58 ERR("Failed to listen !\n");
leihen 13:aa5338a5e452 59 error("Listening");
leihen 13:aa5338a5e452 60 return false;
leihen 0:7a2421e63e74 61 }
leihen 0:7a2421e63e74 62
leihen 13:aa5338a5e452 63 ERR("Connected !");
leihen 0:7a2421e63e74 64 // set into non blocking operation
leihen 13:aa5338a5e452 65 m_Svr.set_blocking(false, 100);
leihen 13:aa5338a5e452 66
leihen 13:aa5338a5e452 67 return true;
leihen 0:7a2421e63e74 68 }
leihen 0:7a2421e63e74 69
leihen 0:7a2421e63e74 70
leihen 6:fe661fa9d18a 71 int HTTPServer::poll(bool blocking)
leihen 13:aa5338a5e452 72 {
leihen 5:dc88012caef1 73 int retval = -1;
leihen 0:7a2421e63e74 74
leihen 13:aa5338a5e452 75 #ifdef _DEBUG
leihen 13:aa5338a5e452 76 led4 = 1; // Indicate we are waiting for a new connection
leihen 13:aa5338a5e452 77 #endif
leihen 0:7a2421e63e74 78 // This thread basically checks if there is a new incoming connection.
leihen 0:7a2421e63e74 79 // If so , a new HTTPConnection is created and the connection thread is started.
leihen 0:7a2421e63e74 80 TCPSocketConnection Clnt;
leihen 13:aa5338a5e452 81 if (m_Svr.accept(Clnt) < 0) {
leihen 4:d065642c32cc 82 #ifdef _DEBUG
leihen 0:7a2421e63e74 83 led4 = 0;
leihen 0:7a2421e63e74 84 led3 = 1; // ERROR
leihen 0:7a2421e63e74 85 led2 = 0;
leihen 0:7a2421e63e74 86 led1 = 0;
leihen 4:d065642c32cc 87 #endif
leihen 0:7a2421e63e74 88 return -1;
leihen 0:7a2421e63e74 89 }
leihen 13:aa5338a5e452 90
leihen 13:aa5338a5e452 91 // a new connection was received
leihen 13:aa5338a5e452 92 INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
leihen 13:aa5338a5e452 93 #ifdef _DEBUG
leihen 13:aa5338a5e452 94 led4 = 0;
leihen 13:aa5338a5e452 95 led3 = 0;
leihen 13:aa5338a5e452 96 led2 = 0;
leihen 13:aa5338a5e452 97 #endif
leihen 13:aa5338a5e452 98
leihen 4:d065642c32cc 99 #ifdef _DEBUG
leihen 13:aa5338a5e452 100 led3 = 1;
leihen 13:aa5338a5e452 101 led2 = 1;
leihen 13:aa5338a5e452 102 #endif
leihen 13:aa5338a5e452 103 HTTPConnection con(Clnt);
leihen 13:aa5338a5e452 104 int c = con.poll();
leihen 13:aa5338a5e452 105 if (c == 0) {
leihen 13:aa5338a5e452 106 // Handle the request
leihen 13:aa5338a5e452 107 INFO("Handling request !");
leihen 13:aa5338a5e452 108 HandleRequest(con.m_Msg, Clnt);
leihen 0:7a2421e63e74 109 }
leihen 13:aa5338a5e452 110 if (c == -1) {
leihen 13:aa5338a5e452 111 // break;
leihen 13:aa5338a5e452 112 }
leihen 13:aa5338a5e452 113 #ifdef _DEBUG
leihen 13:aa5338a5e452 114 led2 = 0;
leihen 13:aa5338a5e452 115 led3 = 0;
leihen 13:aa5338a5e452 116 #endif
leihen 13:aa5338a5e452 117
leihen 13:aa5338a5e452 118
leihen 0:7a2421e63e74 119 INFO("Leaving polling thread");
leihen 0:7a2421e63e74 120 return 0;
leihen 1:6b7472d5e9ee 121 }
leihen 1:6b7472d5e9ee 122
leihen 3:d6224049b3bf 123 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
leihen 3:d6224049b3bf 124 {
leihen 3:d6224049b3bf 125 std::string localPath;
leihen 3:d6224049b3bf 126 std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp>::const_iterator it;
leihen 3:d6224049b3bf 127
leihen 4:d065642c32cc 128 // Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
leihen 3:d6224049b3bf 129 for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
leihen 3:d6224049b3bf 130 // check if this entries' path is fully contained at the beginning of the requested path
leihen 3:d6224049b3bf 131 std::string curpth = it->first;
leihen 3:d6224049b3bf 132
leihen 3:d6224049b3bf 133 if (msg.uri.find(curpth) == 0) {
leihen 4:d065642c32cc 134 // firts matching handler found, we just take it and we'll be happy
leihen 3:d6224049b3bf 135 localPath = msg.uri.substr(curpth.length());
leihen 3:d6224049b3bf 136 break;
leihen 3:d6224049b3bf 137 }
leihen 3:d6224049b3bf 138 }
leihen 13:aa5338a5e452 139
leihen 3:d6224049b3bf 140 if (it == m_lpHandlers.end()) {
leihen 3:d6224049b3bf 141 // There is no such handler, so return invalid
leihen 3:d6224049b3bf 142
leihen 13:aa5338a5e452 143 m_pErrorHandler(msg, tcp);
leihen 3:d6224049b3bf 144 INFO("Webrequest left unhandled.");
leihen 13:aa5338a5e452 145 } else {
leihen 4:d065642c32cc 146 // Valid handler was found
leihen 3:d6224049b3bf 147 INFO("Routing webrequest !");
leihen 4:d065642c32cc 148 // Instantiate the handler object (handling will be done from withing the object's constructor
leihen 3:d6224049b3bf 149 HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp);
leihen 4:d065642c32cc 150 // now we can delete the object, because handling is completed.
leihen 3:d6224049b3bf 151 if (phdl != NULL)
leihen 3:d6224049b3bf 152 delete phdl;
leihen 3:d6224049b3bf 153 }
leihen 3:d6224049b3bf 154 }