Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of HTTPServer by
HTTPServer.cpp
- Committer:
- leihen
- Date:
- 2013-06-05
- Revision:
- 12:ba81cc117fb6
- Parent:
- 11:3943841e1798
- Child:
- 13:aa5338a5e452
File content as of revision 12:ba81cc117fb6:
#include "mbed.h"
#include "HTTPServer.h"
#define _DEBUG      0
#ifdef _DEBUG
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
#endif
#if (_DEBUG && !defined(TARGET_LPC11U24))
#define INFO(x, ...) std::printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
#define WARN(x, ...) std::printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
#define ERR(x, ...) std::printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
#else
#define INFO(x, ...)
#define WARN(x, ...)
#define ERR(x, ...)
#endif
/* Constructor */
/* initialize all members and set the standard error handler. */
HTTPServer::HTTPServer(PinName tx, PinName rx, PinName reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec)
    : m_wifly(tx, rx, reset, tcp_status, ssid, phrase, sec)
{
    m_pErrorHandler = StdErrorHandler;
    m_pSvr = NULL;
}
HTTPServer::~HTTPServer()
{
    if (m_pSvr) {
        delete m_pSvr;
        m_pSvr = NULL;
    }
}
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";
void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
{
    char echoHeader[256];
    tcp.set_blocking(true, 1500);
    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));
    tcp.send(echoHeader, strlen(echoHeader));
    tcp.send((char*)szStdErrorPage, strlen(szStdErrorPage));
}
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;
    }
    INFO("Initializing wifly\n");    
    //  Initialize the wifly wlan device
    m_wifly.init();
    INFO("Connecting to network...");
    //  Try join the network
    while(!m_wifly.connect()) {
        INFO("Failed to connect. Trying again\n");
        m_wifly.reset();
    }
    INFO("connected\n");
    // 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;
    }
    
    //  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");
    }
    //  set into non blocking operation
    m_pSvr->set_blocking(false, 100);
    
    return 0;
}
int HTTPServer::poll(bool blocking)
{    
    int retval = -1;
    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;
#ifdef _DEBUG
    led4 = 1;   //  Indicate we are waiting for a new connection 
#endif
    m_pSvr->set_blocking(blocking); 
    retval = m_pSvr->accept(Clnt);
    if (retval > 0) {
        // no connection availale yet, so just return
#ifdef _DEBUG
led4 = 0;
led3 = 0;
led2 = 0;
#endif
        return retval;
    }
    if ( retval < 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");
#ifdef _DEBUG
        led2 = 0;
#endif 
        m_pSvr->close();
        delete m_pSvr;
        m_pSvr = NULL;
#ifdef _DEBUG
        led4 = 0;
        led3 = 1;   //  ERROR
        led2 = 0;
        led1 = 0;
#endif
        return -1;
    }
    else {
#ifdef _DEBUG
        led4 = 0;
#endif 
        //   a new connection was received
        INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
        //  Start the main connection thread
//        while(1) {
            
    #ifdef _DEBUG
            led3 = 1;
            led2 = 1;
    #endif
            HTTPConnection con;
            int c = con.poll();
            if (c == 0) {
                //  Handle the request
                HandleRequest(con.m_Msg, Clnt);
//                INFO("Closing connection.\n");
//                if (!m_wifly.close()) {
//                    ERR("Failed to close connection !\n");
//                }
            }
            if (c == -1) {
                // No more data available or error
 //               break;
            }
    #ifdef _DEBUG
            led2 = 0;
            led3 = 0;
    #endif
//        }
    }
    
    INFO("Leaving polling thread");
    return 0;
}
void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
{
    std::string localPath;
    std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp>::const_iterator it;
    //  Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
    for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
        //  check if this entries' path is fully contained at the beginning of the requested path
        std::string curpth = it->first;
        if (msg.uri.find(curpth) == 0) {
            // firts matching handler found, we just take it and we'll be happy
            localPath = msg.uri.substr(curpth.length());
            break;
        }
    }
    
    if (it == m_lpHandlers.end()) {
        //  There is no such handler, so return invalid
        m_pErrorHandler(msg, tcp);        
        INFO("Webrequest left unhandled.");
    }
    else {
        //  Valid handler was found
        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.
        if (phdl != NULL)
            delete phdl;
    }
}
            
    