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.
Dependents: HTTP-RPCServerExample
Fork of HTTPServer by
HTTPServer.cpp
- Committer:
- leihen
- Date:
- 2013-06-02
- Revision:
- 11:3943841e1798
- Parent:
- 9:c2a1462b9b71
- Child:
- 12:ba81cc117fb6
File content as of revision 11:3943841e1798:
#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;
}
}
