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

HTTPServer.cpp

Committer:
leihen
Date:
2013-05-26
Revision:
1:6b7472d5e9ee
Parent:
0:7a2421e63e74
Child:
2:8653bbcf7e58

File content as of revision 1:6b7472d5e9ee:

#include "mbed.h"
#include "HTTPServer.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

#if (0 && !defined(TARGET_LPC11U24))
#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__);
#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__);
#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__);
#else
#define INFO(x, ...)
#define WARN(x, ...)
#define ERR(x, ...)
#endif

static const char* szMsgs = "No such file or folder.";

HTTPServer::HTTPServer(Serial* pDbg)
{
    m_pDbg = pDbg;
    m_pSvr = NULL;
    m_bServerListening = false;
}

HTTPServer::~HTTPServer()
{
    if (m_pSvr) {
        delete m_pSvr;
        m_pSvr = NULL;
        m_bServerListening = false;
    }
}

int HTTPServer::start(int port)
{
    // check if the start member was called already once
    if (m_pSvr != NULL) {
        ERR("start function was already called, server is already in listening state.");
        return -1;
    }

    m_bServerListening = false;
    
    //  Create a new server object
    m_pSvr = new TCPSocketServer();
    
    //  Bind the local server to the given port
    if (m_pSvr->bind(port) < 0) {
        ERR("Failed to bind to port %d\n", port);
        return -1;
    }
    else {
        INFO("Binding succeeded !\n");
    }

    //  Listen to a maximum of 10 concurrent connections
    if (m_pSvr->listen(1) < 0) {
        ERR("Faild to listen !\n");
        delete m_pSvr;
        m_pSvr = NULL;
        return -1;
    }
    else {
        INFO("Listening\n");
        m_bServerListening = true;
    }

    //  set into non blocking operation
    m_pSvr->set_blocking(false, 100);
    
    return 0;
}


int HTTPServer::poll()
{    
    INFO("Listening for new connection requests.");

    //  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;

    led4 = 1;   //  Indicate we are waiting for a new connection 
    if (m_pSvr->accept(Clnt) < 0) {
        //  an error occured 
        ERR("There was an error, Accept returned with an error. Probably the connection to the router was lost. Shutting down server");
        led2 = 0;
        m_bServerListening = false;
        m_pSvr->close();
        delete m_pSvr;
        m_pSvr = NULL;
        led4 = 0;
        led3 = 1;   //  ERROR
        led2 = 0;
        led1 = 0;
        return -1;
    }
    else {
        led4 = 0;
        //   a new connection was received
        INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
        //  Start the main connection thread
        led3 = 1;
        led2 = 1;
        HTTPConnection con;
        int c = con.poll();
        if (c == 0) {
            //  Handle the request
            HandleRequest(con.m_Msg, Clnt);
        }
        led2 = 0;
        led3 = 0;
    }
    
    INFO("Leaving polling thread");
    return 0;
}

void HTTPServer::HandleRequest(HTTPMessage& msg, TCPSocketConnection& tcp)
{
    static char echoHeader[256] = {};
    static const char* szPage = {
        "<HTML>\r\n"
        "<HEAD>\r\n"
        "<META content=\"text/html\" http-equiv=Content-Type>\r\n"
        "</HEAD>\r\n"
        "<BODY>\r\n"
        "<h1>ERROR 404</h1>\r\n"
        "<P>File not found<P>\r\n"
        "</BODY>\r\n"
        "</HTML>\r\n\r\n"};

    map<string, HTTPRequestHandlerFunction>::iterator it;
    
    it = m_pHandlers.find(msg.uri);
    
    if (it == m_pHandlers.end()) {
        //  There is no such handler, so return invalid
        
        tcp.set_blocking(true, 1500);
        sprintf(echoHeader,"HTTP/1.1 404 Fail\r\nContent-Length: %d\r\nContent-Type: text/html\r\nServer: mbed embedded\r\nConnection: Close\r\n\r\n",strlen(szPage));
        tcp.send(echoHeader,strlen(echoHeader));
        tcp.send((char*)szPage,strlen(szMsgs));
        INFO("Webrequest left unhandled.");
    }
    else {
        //  Handler was found so pass action to handler
        INFO("Routing webrequest !");
        (it->second)(msg, tcp);
    }
}