Changes made for RPC

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPServer.cpp Source File

HTTPServer.cpp

00001 #include "mbed.h"
00002 #include "HTTPServer.h"
00003 //#define DEBUG
00004 #include "hl_debug.h"
00005 
00006 
00007 
00008 /* Constructor */
00009 /* initialize all members and set the standard error handler. */
00010 HTTPServer::HTTPServer()
00011     : m_pEthernet(NULL)
00012 {
00013     m_pErrorHandler = StdErrorHandler;
00014 }
00015 
00016 HTTPServer::~HTTPServer()
00017 {
00018     if (m_pEthernet == NULL) {
00019         INFO("Deleting EthernetInterface Object.\n");
00020         delete m_pEthernet;
00021     }
00022 }
00023 
00024 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";
00025 
00026 void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
00027 {
00028     char echoHeader[256];
00029     tcp.set_blocking(true, 1500);
00030     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));
00031     tcp.send(echoHeader, strlen(echoHeader));
00032     tcp.send((char*)szStdErrorPage, strlen(szStdErrorPage));
00033 }
00034 
00035 
00036 bool HTTPServer::start(int port, EthernetInterface* pEthernet)
00037 {
00038     //  If no ethernet interface is provided, instantiate own on the heap. This has to be deleted later in the destructor.
00039     //  If a valid pointer to an thernet interface is proveded, we can simply use it. 
00040     if (pEthernet == NULL) {
00041         INFO("Creating EthernetInterface object\n");
00042         m_pEthernet = new EthernetInterface();
00043         
00044         if (m_pEthernet == NULL) {
00045             ERR("Out of memory, unable to instantiate an EthernetInterface object.");
00046             return false;
00047         }
00048 
00049         //  Initiaize the network
00050         INFO("Initializing network\n");
00051         if (m_pEthernet->init() != 0) {
00052             ERR("Failed to initialize the ethernet interface !");
00053             delete m_pEthernet;
00054             m_pEthernet = NULL;
00055             return false;
00056         }
00057         
00058         //  Connect to the network using DHCP
00059         INFO("Connecting to the network using DHCP...");
00060         if (m_pEthernet->connect() != 0) {
00061             ERR("Failed to connect to the ethernet !");
00062             delete m_pEthernet;
00063             m_pEthernet = NULL;
00064             return false;
00065         }
00066         
00067         INFO("Connected IP %s", m_pEthernet->getIPAddress());
00068         
00069     } else {
00070         //  In the case that the ethernet interface is provided, it is assumed that a connection has already been created.
00071         INFO("Using connection IP %s", pEthernet->getIPAddress());
00072     }
00073     
00074     INFO("Binding to port %d...", port);
00075     if (m_Svr.bind(port) < 0) {
00076         ERR("Failed to bind to port !\n");
00077         error("Binding");
00078         return false;
00079     }
00080 
00081     INFO("Listening ...");
00082     if (m_Svr.listen(1) < 0) {
00083         ERR("Failed to listen !\n");
00084         error("Listening");
00085         return false;
00086     }
00087 
00088     INFO("Connected !");
00089     //  set into non blocking operation
00090     m_Svr.set_blocking(false, 100);
00091 
00092     return true;
00093 }
00094 
00095 
00096 int HTTPServer::poll(bool blocking)
00097 {
00098     //  This thread basically checks if there is a new incoming connection.
00099     //  If so , a new HTTPConnection is created and the connection thread is started.
00100     TCPSocketConnection Clnt;
00101     if (m_Svr.accept(Clnt) < 0) {
00102         return -1;
00103     }
00104 
00105     //   a new connection was received
00106     INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
00107     HTTPConnection con(Clnt);
00108     int c = con.poll();
00109     if (c == 0) {
00110         //  Handle the request
00111         INFO("Handling request !");
00112         HandleRequest(con.m_Msg, Clnt);
00113     }
00114     if (c == -1) {
00115 //        break;
00116     }
00117 
00118     INFO("Leaving polling thread");
00119     return 0;
00120 }
00121 
00122 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
00123 {
00124     std::string localPath;
00125     std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp>::const_iterator it;
00126 
00127     //  Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
00128     for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
00129         //  check if this entries' path is fully contained at the beginning of the requested path
00130         std::string curpth = it->first;
00131 
00132         if (msg.uri.find(curpth) == 0) {
00133             // firts matching handler found, we just take it and we'll be happy
00134             localPath = msg.uri.substr(curpth.length());
00135             break;
00136         }
00137     }
00138 
00139     if (it == m_lpHandlers.end()) {
00140         //  There is no such handler, so return invalid
00141 
00142         m_pErrorHandler(msg, tcp);
00143         INFO("Webrequest left unhandled.");
00144     } else {
00145         //  Valid handler was found
00146         INFO("Routing webrequest !");
00147         //  Instantiate the handler object (handling will be done from withing the object's constructor
00148         HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp);
00149         //  now we can delete the object, because handling is completed.
00150         if (phdl != NULL)
00151             delete phdl;
00152     }
00153 }