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

Files at this revision

API Documentation at this revision

Comitter:
cabledev
Date:
Thu May 15 16:09:51 2014 +0000
Parent:
16:cc3f5c53d0d5
Commit message:
- converted to blocking mode & removed polling; greatly improving stability, but HTTP server must be started from a separate thread (not the main app thread); - moved ethernet interface and port assignment out of start() method; - updated log messages

Changed in this revision

HTTPConnection.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPRequestHandler.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPServer.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
Handler/FsHandler.cpp Show annotated file Show diff for this revision Revisions of this file
Handler/RpcHandler.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/HTTPConnection.cpp	Sat Aug 17 16:17:55 2013 +0000
+++ b/HTTPConnection.cpp	Thu May 15 16:09:51 2014 +0000
@@ -62,7 +62,7 @@
     rcvd = parse(buffer);
     if (rcvd == -1) {
         //  Invalid content received, so close the connection
-        INFO("Invalid message received, so sending negative response and closing connection !");
+        INFO("Invalid message received, so sending negative response and closing connection!");
         sprintf(buffer,"HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r",0);
         m_Tcp.set_blocking(true, 1500);
         m_Tcp.send(buffer,strlen(buffer));
@@ -85,7 +85,7 @@
             if (parseHeader(buffer) == 0) {
             }
             else {
-                WARN("Invalid message header received !");
+                WARN("Invalid message header received!");
             }
         }
     }             
@@ -102,7 +102,7 @@
     m_Tcp.set_blocking(false);
     
     if (!m_Tcp.is_connected()) {
-        error("NOT COnnected anymore");
+        error("NOT connected anymore");
         return -1;
     }
     Timer tm;
@@ -233,7 +233,7 @@
             if (buffer[i] == '?') {  // starts with a question mark, so got it
                 buffer[i] = 0;
                 args_start = i; //  set the start of the args section
-                INFO("Argument section found !");
+                INFO("Argument section found!");
             }
         }
         else {                  // search arg-value touples
--- a/HTTPRequestHandler.cpp	Sat Aug 17 16:17:55 2013 +0000
+++ b/HTTPRequestHandler.cpp	Thu May 15 16:09:51 2014 +0000
@@ -116,7 +116,7 @@
 
 void HTTPRequestHandler::handleError(int errorCode, HTTPHeaders* header)
 {
-    INFO("Handling error !");
+    INFO("Handling error!");
     tcp.set_blocking(false, 1500);
     sprintf(buffer,"HTTP/1.1 %d Error\r\n", errorCode);
     tcp.send(buffer, strlen(buffer));
@@ -147,7 +147,7 @@
     tcp.send(buffer, strlen(buffer));
     sprintf(buffer, "Content-Length: %ld\r\n", nLen);    //  Add 2 chars for the terminating CR+LF
     tcp.send(buffer, strlen(buffer));
-    INFO("Sending standard headers !");
+    INFO("Sending standard headers!");
     if (header == NULL) {
         tcp.send_all((char*)hdrStandard, strlen(hdrStandard));
     }
@@ -160,7 +160,7 @@
         }
         tcp.send_all("\r\n", 2);
     }
-    INFO("Proceeding !");
+    INFO("Proceeding!");
     //  other content must be sent using the 'processResponse' function
 }
 
@@ -172,5 +172,5 @@
 
 void HTTPRequestHandler::endResponse()
 {
-    INFO("Ending Response !");
+    INFO("Ending Response!");
 }
--- a/HTTPServer.cpp	Sat Aug 17 16:17:55 2013 +0000
+++ b/HTTPServer.cpp	Thu May 15 16:09:51 2014 +0000
@@ -8,7 +8,7 @@
 /* Constructor */
 /* initialize all members and set the standard error handler. */
 HTTPServer::HTTPServer()
-    : m_pEthernet(NULL)
+    : m_port(80), m_pEthernet(NULL)
 {
     m_pErrorHandler = StdErrorHandler;
 }
@@ -32,91 +32,104 @@
     tcp.send((char*)szStdErrorPage, strlen(szStdErrorPage));
 }
 
+void HTTPServer::setPort(int port)
+{
+    m_port = port;
+}
 
-bool HTTPServer::start(int port, EthernetInterface* pEthernet)
+void HTTPServer::setEthernetInterface(EthernetInterface* pEthernet)
+{
+    m_pEthernet = pEthernet;
+}
+
+void HTTPServer::start()
 {
     //  If no ethernet interface is provided, instantiate own on the heap. This has to be deleted later in the destructor.
     //  If a valid pointer to an thernet interface is proveded, we can simply use it. 
-    if (pEthernet == NULL) {
+    if (m_pEthernet == NULL) {
         INFO("Creating EthernetInterface object\n");
         m_pEthernet = new EthernetInterface();
         
         if (m_pEthernet == NULL) {
             ERR("Out of memory, unable to instantiate an EthernetInterface object.");
-            return false;
+            //return false;
         }
 
         //  Initiaize the network
         INFO("Initializing network\n");
         if (m_pEthernet->init() != 0) {
-            ERR("Failed to initialize the ethernet interface !");
+            ERR("Failed to initialize the ethernet interface!");
             delete m_pEthernet;
             m_pEthernet = NULL;
-            return false;
+            //return false;
         }
         
         //  Connect to the network using DHCP
         INFO("Connecting to the network using DHCP...");
         if (m_pEthernet->connect() != 0) {
-            ERR("Failed to connect to the ethernet !");
+            ERR("Failed to connect to the ethernet!");
             delete m_pEthernet;
             m_pEthernet = NULL;
-            return false;
+            //return false;
         }
         
         INFO("Connected IP %s", m_pEthernet->getIPAddress());
         
     } else {
         //  In the case that the ethernet interface is provided, it is assumed that a connection has already been created.
-        INFO("Using connection IP %s", pEthernet->getIPAddress());
+        INFO("Using connection IP %s", m_pEthernet->getIPAddress());
     }
     
-    INFO("Binding to port %d...", port);
-    if (m_Svr.bind(port) < 0) {
-        ERR("Failed to bind to port !\n");
+    INFO("Binding to port %d...", m_port);
+    if (m_Svr.bind(m_port) < 0) {
+        ERR("Failed to bind to port!\n");
         error("Binding");
-        return false;
+        //return false;
     }
-
+    
     INFO("Listening ...");
     if (m_Svr.listen(1) < 0) {
-        ERR("Failed to listen !\n");
+        ERR("Failed to listen!\n");
         error("Listening");
-        return false;
+        //return false;
     }
+    
+    m_Svr.set_blocking(true);
 
-    INFO("Connected !");
-    //  set into non blocking operation
-    m_Svr.set_blocking(false, 100);
-
-    return true;
-}
-
+    INFO("Connected!");
+    
+    //osThreadSetPriority( Thread::gettid() ,  osPriorityBelowNormal );
+    
+    while (1)
+    {
+//    INFO("Entering polling thread");
 
-int HTTPServer::poll(bool blocking)
-{
-    //  This thread basically checks if there is a new incoming connection.
-    //  If so , a new HTTPConnection is created and the connection thread is started.
-    TCPSocketConnection Clnt;
-    if (m_Svr.accept(Clnt) < 0) {
-        return -1;
-    }
+        //  This thread basically checks if there is a new incoming connection.
+        //  If so , a new HTTPConnection is created and the connection thread is started.
+        TCPSocketConnection Clnt;
+        if (m_Svr.accept(Clnt) < 0) {
+//        INFO("Failure accepting client connection.");
+//            return -1;
+        }
 
-    //   a new connection was received
-    INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
-    HTTPConnection con(Clnt);
-    int c = con.poll();
-    if (c == 0) {
-        //  Handle the request
-        INFO("Handling request !");
-        HandleRequest(con.m_Msg, Clnt);
+        //   a new connection was received
+        INFO("Client (IP=%s) is connected!\n", Clnt.get_address());
+        HTTPConnection con(Clnt);
+        int c = con.poll();
+        if (c == 0) {
+            //  Handle the request
+            INFO("Handling request!");
+            HandleRequest(con.m_Msg, Clnt);
+        }
+        if (c == -1) {
+//        break;
+        }
+
+        INFO("Leaving polling thread");
+//        return 0;
     }
-    if (c == -1) {
-//        break;
-    }
-
-    INFO("Leaving polling thread");
-    return 0;
+    
+    //return true;
 }
 
 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
@@ -143,7 +156,7 @@
         INFO("Webrequest left unhandled.");
     } else {
         //  Valid handler was found
-        INFO("Routing webrequest !");
+        INFO("Routing webrequest!");
         //  Instantiate the handler object (handling will be done from withing the object's constructor
         HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp);
         //  now we can delete the object, because handling is completed.
--- a/HTTPServer.h	Sat Aug 17 16:17:55 2013 +0000
+++ b/HTTPServer.h	Thu May 15 16:09:51 2014 +0000
@@ -91,12 +91,12 @@
 *     HTTPServer svr;
 *     //    Initialize the ethernet interface
 *     if (eth.init() != 0) {
-*         printf("Initialization of EthernetInterface failed !");
+*         printf("Initialization of EthernetInterface failed!");
 *         exit(0);
 *     }
 *     //    Connect using DHCP
 *     if (eth.connect() !=0) {
-*         printf("Failed to connect using DHCP !");
+*         printf("Failed to connect using DHCP!");
 *         exit(0);
 *     }
 *     
@@ -118,8 +118,9 @@
 {
         TCPSocketServer         m_Svr;
         bool                    m_bServerListening;
+        int                     m_port;
         EthernetInterface*      m_pEthernet;
-       
+        
     public:
         /** Constructor for HTTPServer objects.
         */
@@ -163,24 +164,22 @@
         * @param hdlFunc: User specified handler function which will be used in error conditions.
         */
         void addErrorHandler(HTTPRequestHandlerFunction hdlFunc)
-        { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }    
+        { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }
 
-        /** Binds server to a specific port and starts listening. This member prepares the internal variables and the server socket
-        * and terminates after successfull initialization
+        /** Sets the port on which the HTTP server will listen
         * @param port : port on which to listen for incoming connections
+        */
+        void setPort(int port = 80);
+        
+        /** Sets the port on which the HTTP server will listen
         * @param pEthernet : a pointer to an existing EthernetInterface object or NULL if the HTTPServer shall allocate the object. _Please note that for compatibility reasons
         * your should consider to create the EthernetInterface as a static variable. Otherwise the the object will be created on the heap._
-        * @returns : false if an unrecoverable error occured or if the ethernet interface was not set or not initialized correctly, or true if everything was ok.
         */
-        bool start(int port = 80, EthernetInterface* pEthernet = NULL);
+        void setEthernetInterface(EthernetInterface* pEthernet = NULL);
         
-        /** Performs the regular polling of the server component. Needs to be called cyclically.
-        * The function will internally check whether new connections are requested by a client and will also poll all existing client connections.
-        * @param blocking : if true, 
-        * @returns -1 if there was a problem. If 0 is returned, the latest request was served successfully and the server is
-        * ready for processing the next request. Simply call \c poll as long as you want to serve new incoming requests.
+        /** Starts listening for incoming connections. This method blocks and should be invoked on a separate thread.
         */
-        int poll(bool blocking = true);
+        void start();
         
     private:
         
--- a/Handler/FsHandler.cpp	Sat Aug 17 16:17:55 2013 +0000
+++ b/Handler/FsHandler.cpp	Thu May 15 16:09:51 2014 +0000
@@ -109,7 +109,7 @@
     }
     else {
         retval = 404;
-        ERR("Requested file was not found !");
+        ERR("Requested file was not found!");
     }
     
     return retval;
--- a/Handler/RpcHandler.cpp	Sat Aug 17 16:17:55 2013 +0000
+++ b/Handler/RpcHandler.cpp	Thu May 15 16:09:51 2014 +0000
@@ -32,7 +32,7 @@
     int err = 404;
     string rpc_args("");
     
-    INFO("Handling RPC Get Requesst.");
+    INFO("Handling RPC Get Request.");
     // This version of the RPC handler does only accept native RPC commands in the format
     //  /<class>/<method> <argument1> [<argument2> [<argument3> ...]]
     // So we can simply pass our local pathg to our rpc