Main Server - Listen to different ports and write information to SD card, synchronize RTC with NTP over the internet, and stream events over serial

Fork of HoneyPot by Shlomi Ruder

Honeypot Server - WIZnet W7500

/media/uploads/proxytype/honeypot.png

Main server library responsible for detecting and report unwanted activities.

Features:

  • listen up to 7 different ports.
  • synchronize RTC with NTP service.
  • support http chunks responses.
  • write connection details to log file on SD card.
  • inject data to pattern html file (like real server).
  • administrator control panel.
  • visitors display message over http.

Http Server Upgrade

the based code of wiznet http server example load file from the sd card and return it to the user, using content-length to define the size of the package, because reading from file the size is fixed so it's very easy to handle but if you want to use the file as pattern and then inject dynamic data directly like a real server it's become more difficult because memory limitation of the device, to solved this we must to remove the content length header and replace it with transfer-encoding, this way we can stream the data to the client without knowing the content length only the chunks size.

 header["Transfer-Encoding"] = "chunked";

HTTPRequestHandler.cpp

Committer:
proxytype
Date:
2017-09-01
Revision:
3:1d6096332358
Parent:
2:f52734664057

File content as of revision 3:1d6096332358:

/* HTTPRequestHandler.cpp */
#include "mbed.h"
#include "HTTPRequestHandler.h"
//#define DEBUG
#include "hl_debug.h"
#include <ctype.h>


static char buffer[128];


const char hdrStandard[] = "DNT: 1\r\n"
                            "MaxAge: 0\r\n"
                            "Connection: Keep-Alive\r\n"
                            "Content-Type: text/html\r\n"
                            "Server: mbed embedded\r\n"
                            "Accessible: 1\r\n"
                            "\r\n";


static int _stricmp(const char* a, const char* b)
{
    int la = strlen(a);
    int lb = strlen(b);
    for (int i = 0 ; i < min(la, lb) ; i++) {
        if (tolower((int)a[i]) != tolower((int)b[i]))
            return i;
    }
    return 0;
}


static const struct mapping_t {
    const char* key;
    const char* value;
} fileTypeMapping[]  = {
        {".gif", "Content-Type: image/gif\r\n"   },
    {".jpg", "Content-Type: image/jpeg\r\n"  },
    {".jpeg","Content-Type: image/jpeg\r\n"  },
    {".ico", "Content-Type: image/x-icon\r\n"},
    {".png", "Content-Type: image/png\r\n"   },
    {".zip", "Content-Type: image/zip\r\n"   },
    {".gz",  "Content-Type: image/gz\r\n"    },
    {".tar", "Content-Type: image/tar\r\n"   },
    {".txt", "Content-Type: plain/text\r\n"  },
    {".pdf", "Content-Type: application/pdf\r\n" },
    {".htm", "Content-Type: text/html\r\n"   },
    {".html","Content-Type: text/html\r\n"   },
    {".css", "Content-Type: text/css\r\n"    },
    {".js",  "Content-Type: text/javascript\r\n"}};
    
HTTPRequestHandler::HTTPRequestHandler(HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp, int isMaster, int * ports, int portsCount, int * hits)
    : msg(Msg), tcp(Tcp)
{
    msg = Msg;
    tcp = Tcp;
    m_isMaster = isMaster;
    m_ports = ports;
    m_portsCount = portsCount;
    m_hits = hits; 

}

HTTPRequestHandler::~HTTPRequestHandler()
{
}

void HTTPRequestHandler::getStandardHeaders(HTTPHeaders& header, const char* fext)
{
    header.clear();
    header["DNT"] = "1";
    header["MaxAge"] = "0";
    header["Connection"] = "Keep-Alive";
    header["Server"] = "mbed Embedded";
    if (fext == NULL)
        header["Content-Type"] = "text/html";
    else {
        for (int i = 0 ; i < sizeof(fileTypeMapping)/sizeof(struct mapping_t) ;i++) {
            if (_stricmp(fileTypeMapping[i].key, fext) == 0) {
                header["Content-Type"] = fileTypeMapping[i].value;
                header["Transfer-Encoding"] = "chunked";
                break;
            }
        }
    }
}

void HTTPRequestHandler::handleRequest()
{
    int err = 0;
    
    switch (msg.request) {
        case HTTP_RT_GET:
            INFO("Dispatching GET Request.");
            err = handleGetRequest();
            break;
            
        case HTTP_RT_POST:
            INFO("Dispatching POST request.");
            err = handlePostRequest();
            break;
            
        case HTTP_RT_PUT:
            INFO("Dispatching PUT request.");
            err = handlePutRequest();
            break;
            
        default:
            INFO("Error in handleRequest, unhandled request type.");
            err = HTTP_NotImplemented;
            break;
    }
    
    //  if any of these functions returns a negative number, call the error handler
    if (err > 0) {
        handleError(err);
    }        
}

static const char* szErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error</h1><P>HTTPServer Error<P></BODY></HTML>\r\n\r\n";

void HTTPRequestHandler::handleError(int errorCode, HTTPHeaders* header)
{
    INFO("Handling error !");
    tcp.set_blocking(false, 1500);
    sprintf(buffer,"HTTP/1.1 %d Error\r\n", errorCode);
    tcp.send(buffer, strlen(buffer));
    sprintf(buffer, "Content-Length: %d\r\n", strlen(szErrorPage));
    tcp.send(buffer, strlen(buffer));
    if (header == NULL) {
        sprintf(buffer, "Content-Type: text/html\r\nServer: mbed embedded\r\n\n\r");
        tcp.send(buffer, strlen(buffer));
    }
    else {
        for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) {
            tcp.send((char*)cIter->first, strlen(cIter->first));
            tcp.send(": ", 2);
            tcp.send((char*)cIter->second, strlen(cIter->second));
            tcp.send("\r\n",2);
        }
        tcp.send("\r\n",2);
    }
    tcp.send((char*)szErrorPage, strlen(szErrorPage));
}

//this is chunked package content length remove
//stream stay open until zero size chunked.
void HTTPRequestHandler::startResponse(int returnCode, HTTPHeaders* header)
{
    tcp.set_blocking(false, 1500);
    sprintf(buffer, "HTTP/1.1 %d OK\r\n", returnCode);
    tcp.send(buffer, strlen(buffer));
    INFO("Sending standard headers !");
    if (header == NULL) {
        tcp.send_all((char*)hdrStandard, strlen(hdrStandard));
    }
    else {
        for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) {
            tcp.send_all((char*)cIter->first, strlen(cIter->first));
            tcp.send_all(": ", 2);
            tcp.send_all((char*)cIter->second, strlen(cIter->second));
            tcp.send_all("\r\n\r\n",2);
        }
        tcp.send_all("\r\n", 2);
    }
    INFO("Proceeding !");
    //  other content must be sent using the 'processResponse' function
}

void HTTPRequestHandler::processResponse(int nLen, char* body)
{
    INFO("Processing Response (%d bytes)!\n",nLen);
    tcp.send_all(body, nLen);
}

void HTTPRequestHandler::endResponse()
{
    tcp.send_all("\0",1);
    INFO("Ending Response !");
}