Changed RPC sucessful execution code from 1 to 200. Included RpcHandler.h in main header file. Effectively allows RPC through HTTP.
Dependents: RPC_HTTP RPC_HTTP_WIZnetInterface RPC_HTTP rpc_over_http_TL_interrupter_gatePJ
Fork of HTTPServer by
Revision 3:d6224049b3bf, committed 2013-05-28
- Comitter:
- leihen
- Date:
- Tue May 28 01:56:14 2013 +0000
- Parent:
- 2:8653bbcf7e58
- Child:
- 4:d065642c32cc
- Commit message:
- First beta version
Changed in this revision
--- a/HTTPConnection.cpp Sun May 26 23:22:36 2013 +0000 +++ b/HTTPConnection.cpp Tue May 28 01:56:14 2013 +0000 @@ -178,24 +178,22 @@ } -int HTTPConnection::parseHeader(const char *buffer) +int HTTPConnection::parseHeader(char *buffer) { if ((strlen(buffer) <3) || (buffer == NULL)) return -1; // decompose string into a touple of <field name> : <field value> - static char fieldname[256] = {}; - static char fieldvalue[256] = {}; - for (int i = 0 ; i < strlen(buffer)+1 ; i++) { + int value_start = 0; + int buflen = strlen(buffer)+1; + for (int i = 0 ; i < buflen ; i++) { if (buffer[i] == ':') { // touple found - strncpy(fieldname, buffer, i); - fieldname[i] = 0; - strcpy(fieldvalue, &buffer[i+1]); - -// m_Msg.headers[fieldname] = fieldvalue; + buffer[i] = 0; + value_start = i+1; + m_Msg.headers[buffer] = &buffer[value_start]; - INFO("Header name=\"%s\" : value=\"%s\".", fieldname, fieldvalue); + INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]); return 0; } }
--- a/HTTPConnection.h Sun May 26 23:22:36 2013 +0000 +++ b/HTTPConnection.h Tue May 28 01:56:14 2013 +0000 @@ -1,4 +1,25 @@ /* HTTPConnection.h */ +/* +Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ #ifndef __HTTPConnection_H__ #define __HTTPConnection_H__ @@ -10,60 +31,76 @@ class HTTPServer; -enum HTTPRequestType +/** Type HTTPRequestType enumerates request types +*/ +typedef enum { - HTTP_RT_GET, - HTTP_RT_POST, - HTTP_RT_PUT, - HTTP_RT_OPTIONS, - HTTP_RT_HEAD, - HTTP_RT_DELETE, - HTTP_RT_TRACE, - HTTP_RT_CONNECT -}; + HTTP_RT_GET, /*!< GET request */ + HTTP_RT_POST, /*!< POST request */ + HTTP_RT_PUT, /*!< PUT request */ + HTTP_RT_OPTIONS, /*!< OPTIONS request */ + HTTP_RT_HEAD, /*!< HEAD request */ + HTTP_RT_DELETE, /*!< DELETE request */ + HTTP_RT_TRACE, /*!< TRACE request */ + HTTP_RT_CONNECT /*!< CONNECT request */ +} HTTPRequestType; -struct HTTPMessage -{ - HTTPRequestType request; - std::string uri; - std::string version; - std::map<string, string> headers; -}; /** class HTTPConnection, encapsulates one connection being made throught the HTTPServer * */ class HTTPConnection { public: - /** public constructor - * - */ - HTTPConnection (); - ~HTTPConnection(); - - /** function to close this connection. To be called from internally. - */ - void close(); - - /** query if this connection is closed and can be deleted. - @returns true if connection is closed. - */ - bool is_closed(); - - /** - Polling function - @returns -1 if connection is not required anymore. Can happen if a fault occured or if the connection is not needed anymore. - */ - int poll(); + + /** HTTPMessage contains all the details of the request received by external HTTP client. + */ + typedef struct + { + /** Specifies the request type received + */ + HTTPRequestType request; + /** The uri associated with the request. + */ + std::string uri; + /** Contains the HTTP/1.1 or HTTP/1.0 version requested by client. + */ + std::string version; + /** Map of headers provided by the client in the form <HeaderName>:<HeaderValue> + */ + std::map<std::string, std::string> headers; + } HTTPMessage; + /** Public constructor for HTTPConnection objects. + * + */ + HTTPConnection (); + + /** Destructor for HTTPConnection objects. + * + */ + ~HTTPConnection(); + + /** Query if this connection is already closed and can be deleted. + @returns true, if connection is closed. + */ + bool is_closed(); + + /** Polling function for the connection. + * @returns -1 if connection is not required anymore. In the current version of this library this should be the normal case. This may change in future versions. + */ + int poll(); protected: + + /** Function to close this connection. To be called from internally. + */ + void close(); + friend class HTTPServer; TCPSocketConnection m_Tcp; HTTPMessage m_Msg; - int parse(char *buffer); - int parseHeader(const char *buffer); + int parseHeader(char *buffer); int receiveHeaders(const char* buffer, int nBuffSize); int receiveLine(char* szLine, int nMaxLen, int nTimeout = -1, char szLineTerm = '\n');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPFsRequestHandler.cpp Tue May 28 01:56:14 2013 +0000 @@ -0,0 +1,86 @@ +/* HTTPFsRequestHandler.cpp */ +#include "mbed.h" +#include "HTTPFsRequestHandler.h" + + + +#if (1 && !defined(TARGET_LPC11U24)) +#define INFO(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); +#else +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#endif + + +#define MAX_BUFFERSIZE 128 +static char buffer[MAX_BUFFERSIZE]; + + +std::map<const char*, const char*> HTTPFsRequestHandler::m_fsMap; + +HTTPFsRequestHandler::HTTPFsRequestHandler(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp) + : HTTPRequestHandler(Msg, Tcp) +{ + m_rootPath = rootPath; + m_localPath = localPath; + + // Now replace the virtual root path with a mounted device path + std::map<const char*, const char*>::iterator it; + for (it = m_fsMap.begin() ; it != m_fsMap.end() ; it++) { + // find best match (if the given logical path is containted in the root + if (m_rootPath.find( it->second ) == 0) { + m_rootPath = it->first; + break; + } + } + + handleRequest(); +} + +HTTPFsRequestHandler::~HTTPFsRequestHandler() +{ +} + +int HTTPFsRequestHandler::handleGetRequest() +{ + INFO("Handling Get Request."); + int retval = 200; //success + std::string reqPath; + + // Check if we received a directory with the local bath + if ((m_localPath.length() == 0) || (m_localPath.substr( m_localPath.length()-1, 1) == "/")) { + // yes, we shall append the default page name + m_localPath += "index.html"; + } + + reqPath = m_rootPath + m_localPath; + + INFO("Mapping \"%s\" to \"%s\"", msg.uri.c_str(), reqPath.c_str()); + + FILE *fp = fopen(reqPath.c_str(), "r"); + if (fp != NULL) { + // File was found and can be returned + + // first determine the size + fseek(fp, 0, SEEK_END); + long size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + startResponse(200, size); + while(!feof(fp) && !ferror(fp)) { + int cnt = fread(buffer, 1, MAX_BUFFERSIZE , fp); + processResponse(cnt, buffer); + } + endResponse(); + fclose(fp); + } + else { + retval = 404; + ERR("Requested file was not found !"); + } + + return retval; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPFsRequestHandler.h Tue May 28 01:56:14 2013 +0000 @@ -0,0 +1,50 @@ +/* HTTPFsRequestHandler.h */ +/* +Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#ifndef __HTTPFSREQUESTHANDLER_H__ +#define __HTTPFSREQUESTHANDLER_H__ + +#include "mbed.h" +#include "HTTPRequestHandler.h" + +#include <map> +#include <string> + +class HTTPFsRequestHandler : public HTTPRequestHandler +{ + std::string m_rootPath; + std::string m_localPath; + + public: + HTTPFsRequestHandler(const char* roottPath, const char* localPath, HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp); + virtual ~HTTPFsRequestHandler(); + + static inline HTTPRequestHandler* create(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp) { return new HTTPFsRequestHandler(rootPath, localPath, msg, tcp); } + + /** Handler function to serve GET requests + */ + virtual int handleGetRequest(); + + static std::map<const char*, const char*> m_fsMap; + static void mount(const char* requestPath, const char* localPath) { m_fsMap[requestPath] = localPath; } +}; +#endif // __HTTPFSREQUESTHANDLER_H__ \ No newline at end of file
--- a/HTTPRequestHandler.cpp Sun May 26 23:22:36 2013 +0000 +++ b/HTTPRequestHandler.cpp Tue May 28 01:56:14 2013 +0000 @@ -2,11 +2,119 @@ #include "mbed.h" #include "HTTPRequestHandler.h" +#if (1 && !defined(TARGET_LPC11U24)) +#define INFO(x, ...) std::printf("[HTTPRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[HTTPRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[HTTPRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); +#else +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#endif -HTTPRequestHandler::HTTPRequestHandler() +static char buffer[128]; + +HTTPRequestHandler::HTTPRequestHandler(HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp) + : msg(Msg), tcp(Tcp) { + msg = Msg; + tcp = Tcp; } HTTPRequestHandler::~HTTPRequestHandler() { -} \ No newline at end of file +} + +void HTTPRequestHandler::handleRequest() +{ + int err = 0; + + switch (msg.request) { + case HTTP_RT_GET: + INFO("Dispatching GET Request."); + err = handleGetRequest(); + break; + +// case HTTP_RT_POST: +// err = handlePostRequest(); +// break; + +// case HTTP_RT_PUT: +// err = handlePutRequest(); +// break; + + default: + INFO("Error in handleRequest, unhandled request type."); + err = 404; + 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 %d</h1><P>HTTPServer Error<P></BODY></HTML>\r\n\r\n"; + +void HTTPRequestHandler::handleError(int errorCode, HTTPHeaders* header) +{ + INFO("Handling error !"); + tcp.set_blocking(true, 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)); +} + + +void HTTPRequestHandler::startResponse(int returnCode, int nLen, HTTPHeaders* header) +{ + INFO("Starting response !"); + tcp.set_blocking(true, 1500); + sprintf(buffer, "HTTP/1.1 %d OK\r\n", returnCode); + tcp.send(buffer, strlen(buffer)); + sprintf(buffer, "Content-Length: %d\r\n", nLen + 2); // Add 2 chars for the terminating CR+LF + tcp.send(buffer, strlen(buffer)); + if (header == NULL) { + sprintf(buffer, "Content-Type: text/html\r\nServer: mbed embedded\r\n\r\n"); + 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\r\n",2); + } + tcp.send("\r\n", 2); + } + // other content must be sent using the 'processResponse' function +} + +void HTTPRequestHandler::processResponse(int nLen, char* body) +{ + INFO("Processing Response !"); + tcp.send(body, nLen); +} + +void HTTPRequestHandler::endResponse() +{ + INFO("Ending Response !"); + tcp.send("\r\n", 2); +} +
--- a/HTTPRequestHandler.h Sun May 26 23:22:36 2013 +0000 +++ b/HTTPRequestHandler.h Tue May 28 01:56:14 2013 +0000 @@ -1,26 +1,91 @@ /* HTTPRequestHandler.h */ +/* +Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ #ifndef __HTTPREQUESTHANDLER_H__ #define __HTTPREQUESTHANDLER_H__ #include "mbed.h" #include "HTTPConnection.h" +#include <map> + +typedef std::map<const char*,const char*> HTTPHeaders; + +/** class HTTPRequestHandler is the base class for HTTP Handler request implementations. +* +*/ class HTTPRequestHandler { + protected: + HTTPConnection::HTTPMessage& msg; + TCPSocketConnection& tcp; + public: - /** - public constructor + /** Constructor for HTTPRequestHandler objects. */ - HTTPRequestHandler(); + HTTPRequestHandler(HTTPConnection::HTTPMessage&, TCPSocketConnection&); + + /** Destructor for HTTPRequestHandler objects. + */ + virtual ~HTTPRequestHandler(); + + /** Handler function which will be used by the HTTPServer to serve requests. + * @param msg : Request Message information. + * @param tcp : The socket which represents the active connection to the client. + */ + virtual void handleRequest(); - /** - destructor - */ - ~HTTPRequestHandler(); + /** Handler function which will handle errors and return errors correctly + * @param errorCode : The error code returned by the HTTP Server to represent the error condition. + * @param msg : Request Message information. + * @param tcp : The socket which represents the active connection to the client. + */ + virtual void handleError(int errorCode, HTTPHeaders* header = NULL); + + /** Function sends the response header which consists of the return code and the headers section + * the response header also contains the length (in bytes) of the body. You need to send the body + * right after calling this function. Please note that you do not need to consider the terminating + * CR+LF after your last CR+LF. This will be sent automatically once \c endResponse is called. Also + * the Length given in \c nLen does not need to consider this additional chars. It will also be + * automatically added in \c startResponse. if you need to change the headers, please do NOT + * specify the \c Content-Length Header. This is done automatically be the function. + */ + void startResponse(int returnCode, int nLen, HTTPHeaders* header = NULL); + void processResponse(int nLen, char* body ); + void endResponse(); + + protected: + /** Handler function to serve GET requests + */ + virtual int handleGetRequest() = 0; + /** Handler function to serve PUT requests + */ +// virtual int handlePutRequest() = 0; - void HandleRequest(HTTPMessage& ); - + /** Handler function to serve POST requests + */ +// virtual int handlePostRequest() = 0; + }; #endif // __HTTPREQUESTHANDLER_H__ \ No newline at end of file
--- a/HTTPServer.cpp Sun May 26 23:22:36 2013 +0000 +++ b/HTTPServer.cpp Tue May 28 01:56:14 2013 +0000 @@ -6,7 +6,7 @@ DigitalOut led3(LED3); DigitalOut led4(LED4); -#if (0 && !defined(TARGET_LPC11U24)) +#if (1 && !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__); @@ -16,9 +16,9 @@ #define ERR(x, ...) #endif -HTTPServer::HTTPServer(Serial* pDbg) +HTTPServer::HTTPServer(Serial *dbg) { - m_pDbg = pDbg; + m_pDbg = dbg; m_pSvr = NULL; m_bServerListening = false; m_pErrorHandler = StdErrorHandler; @@ -36,7 +36,7 @@ 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(HTTPMessage& msg, TCPSocketConnection& tcp) +void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp) { char echoHeader[512]; @@ -132,7 +132,39 @@ return 0; } -void HTTPServer::HandleRequest(HTTPMessage& msg, TCPSocketConnection& tcp) +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; + + 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) { + // handler found + 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 { + INFO("Routing webrequest !"); + + HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp); + if (phdl != NULL) + delete phdl; + } + +} +/* +void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp) { map<string, HTTPRequestHandlerFunction>::iterator it; @@ -149,4 +181,5 @@ INFO("Routing webrequest !"); (it->second)(msg, tcp); } -} \ No newline at end of file +} +*/ \ No newline at end of file
--- a/HTTPServer.h Sun May 26 23:22:36 2013 +0000 +++ b/HTTPServer.h Tue May 28 01:56:14 2013 +0000 @@ -1,4 +1,25 @@ /* HTTPServer.cpp */ +/* +Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ #ifndef __HTTPSERVER_H__ #define __HTTPSERVER_H__ #include "mbed.h" @@ -13,30 +34,66 @@ #include <TCPSocketConnection.h> #include <TCPSocketServer.h> -typedef void (*HTTPRequestHandlerFunction)(HTTPMessage&, TCPSocketConnection&); +/** Typedefinition for a handler function +*/ +typedef void (*HTTPRequestHandlerFunction)(HTTPConnection::HTTPMessage&, TCPSocketConnection&); + -/** Class HTTPServer for WiFly Interface Library - * - */ - class HTTPServer - { - +/** Class HTTPServer for use with <a href="http://mbed.org/users/samux/code/WiflyInterface/">WiflyInterface</a>. +* This class is a simple implementation of an HTTP Server for use with the WiFly interface. +* The class will listen for incoming connections on the (configurable) HTTP port. For each +* incoming connection, one request will be processed. +* After instantiating this class, add all required handlers using the \c addHandler function, +* replace the default error handler using \c addErrorHandler if needed and call the \c start +* method to initialize the class. +* You need to continuously poll for any new incoming connections after one request has been +* served using the \c poll member function. +* +* \b Example: +* @code +* #include "mbed.h" +* #include "HTTPServer.h" +* #include "LocalFileSystem.h" +* +* LocalFileSystem local("local"); +* WiflyInterface wifly(p9, p10, p25, p26, "<your access point>", "<your password>", WPA); +* +* void main(void) +* { +* HTTPServer svr; + svr.mount("/local/", "/"); +* svr.addHandler<HTTPFsRequestHandler>( "/" ); +* svr.start(); +* while(1) +* { +* if (svr.poll() < 0) +* exit(0); +* } +* } +* @endcode +*/ +class HTTPServer +{ public: - HTTPServer(Serial* pDbg = NULL); + /** Constructor for HTTPServer objects. + */ + HTTPServer(Serial* dbg = NULL); + + /** Destructor for HTTPServer objects. + */ ~HTTPServer(); - struct handlersComp //Used to order handlers in the right way { bool operator() (const string& handler1, const string& handler2) const { - //The first handler is longer than the second one - if (handler1.length() > handler2.length()) - return true; //Returns true if handler1 is to appear before handler2 - else if (handler1.length() < handler2.length()) - return false; - else //To avoid the == case, sort now by address - return ((&handler1)>(&handler2)); + //The first handler is longer than the second one + if (handler1.length() > handler2.length()) + return true; //Returns true if handler1 is to appear before handler2 + else if (handler1.length() < handler2.length()) + return false; + else //To avoid the == case, sort now by address + return ((&handler1)>(&handler2)); } }; @@ -46,43 +103,42 @@ @param T : class which will be instanciated to serve these requests @param path : requests starting with this path will be served using this handler */ -// template<typename T> -// void addHandler(const char* path) //Template decl in header -// { m_pHandlers[path] = &T::inst; } - - void addHandler(const char* path, HTTPRequestHandlerFunction hdlFunc) - { m_pHandlers[path] = hdlFunc; } + template<typename T> + void addHandler(const char* path) + { m_lpHandlers[path] = &T::create; } + /** + Replaces the standard error Handler. The error Handler will be called everytime a request is not + handled by a handler from the handler list. + @param hdlFunc: Handler which serves an error condition. + */ void addErrorHandler(HTTPRequestHandlerFunction hdlFunc) { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; } - ///Starts listening - /** - Binds server to a specific port and starts listening. This member prepares the internal variables and the server socket - and terminates after successfull initialization - @param port : port on which to listen for incoming connections - @returns : -1 if an unrecoverable error occured, or 0 if everything was ok. + + /** Binds server to a specific port and starts listening. This member prepares the internal variables and the server socket + * and terminates after successfull initialization + * @param port : port on which to listen for incoming connections + * @returns : -1 if an unrecoverable error occured, or 0 if everything was ok. */ int start(int port = 80); - /** - 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. + /** 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. */ int poll(); -private: - - static void StdErrorHandler(HTTPMessage&, TCPSocketConnection&); - - TCPSocketServer* m_pSvr; - bool m_bServerListening; + private: + static void StdErrorHandler(HTTPConnection::HTTPMessage&, TCPSocketConnection&); - Serial* m_pDbg; - void HandleRequest(HTTPMessage& con, TCPSocketConnection&); - - map<string, HTTPRequestHandlerFunction> m_pHandlers; - HTTPRequestHandlerFunction m_pErrorHandler; + TCPSocketServer* m_pSvr; + bool m_bServerListening; + + Serial* m_pDbg; + void HandleRequest(HTTPConnection::HTTPMessage& con, TCPSocketConnection&); + map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp> m_lpHandlers; + HTTPRequestHandlerFunction m_pErrorHandler; + }; #endif //__HTTPSERVER_H__ \ No newline at end of file