HTTPServer

Committer:
jphuc96
Date:
Sat Sep 16 02:39:55 2017 +0000
Revision:
0:caf5feddac47
v1

Who changed what in which revision?

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