Adaptation of the HttpServer by user yueee_yt. This version has improved handling of the HTTP headers (**NOTE**: There are limitations with this implementation and it is not fully functional. Use it only as a starting point.)
Dependents: DMSupport DMSupport DMSupport DMSupport
Fork of DM_HttpServer by
Revision 0:fdf9c2c5200f, committed 2014-02-20
- Comitter:
- yueee_yt
- Date:
- Thu Feb 20 05:36:19 2014 +0000
- Child:
- 1:f5f79412e1aa
- Commit message:
- Initialize version
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPRequestDispatcher.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,78 @@ + +/* +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 HTTP_REQUEST_DISPATCHER_H +#define HTTP_REQUEST_DISPATCHER_H + +//class HTTPServer; + +//*#include "api/TCPSocket.h" +//#include "HTTPServer.h" +//*#include "core/netservice.h" + +#include "mbed.h" +#include "EthernetInterface.h" +#include "HTTPRequestHandler.h" +#include "HTTPServer2.h" +#define HTTP_REQUEST_TIMEOUT 5000 + +#include <string> +using std::string; +#include <map> +using std::map; + +//struct handlersComp; + +class HTTPRequestDispatcher //: public NetService +{ +public: + HTTPRequestDispatcher(map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > lpHandlers,TCPSocketConnection* client); + virtual ~HTTPRequestDispatcher(); + +private: + + enum HTTP_METH + { + HTTP_GET, + HTTP_POST, + HTTP_HEAD + }; + + void dispatchRequest(); + + virtual void close(); //Close TCPSocket and destroy data + +//* void onTCPSocketEvent(/**TCPSocketEvent e**/); + + void onTimeout(); //Connection has timed out + + bool getRequest(string* path, string* meth); + + //HTTPServer* m_pSvr; + TCPSocketConnection* m_pTCPSocketConnection; + map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers; + Timeout m_watchdog; + bool m_closed; +}; + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPRequestDispatcher.txt Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,217 @@ +/* +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. +*/ + +//*#include "core/netservice.h" +#include "HTTPRequestDispatcher.h" +#include "HTTPRequestHandler.h" +#include <string> +using std::string; + +#include <map> +using std::map; + + +//#define __DEBUG +#include "dbg/dbg.h" + +HTTPRequestDispatcher::HTTPRequestDispatcher(map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > lpHandlers,TCPSocketConnection* client) : /*NetService(), m_pSvr(pSvr),m_watchdog(),*/m_pTCPSocketConnection(client), m_closed(false), m_lpHandlers(lpHandlers) +{ +//* m_pTCPSocket->setOnEvent(this, &HTTPRequestDispatcher::onTCPSocketEvent); *// +//* m_watchdog.attach_us<HTTPRequestDispatcher>(this, &HTTPRequestDispatcher::onTimeout, HTTP_REQUEST_TIMEOUT * 1000); *// + printf("(Dispatcher)Connection from %s\r\n", client->get_address()); + dispatchRequest(); +} + +HTTPRequestDispatcher::~HTTPRequestDispatcher() +{ + close(); +} + +void HTTPRequestDispatcher::dispatchRequest() +{ + string path; + string meth; + HTTP_METH methCode; + + printf("Dispatching req\r\n"); + + if( !getRequest(&path, &meth ) ) + { + printf("HTTPRequestDispatcher::dispatchRequest() Invalid request\r\n"); + close(); + return; //Invalid request + } + + if( !meth.compare("GET") ) + { + printf("HTTPRequestDispatcher::dispatchRequest() HTTP_GET\r\n"); + methCode = HTTP_GET; + } + else if( !meth.compare("POST") ) + { + printf("HTTPRequestDispatcher::dispatchRequest() HTTP_POST\r\n"); + methCode = HTTP_POST; + } + else if( !meth.compare("HEAD") ) + { + printf("HTTPRequestDispatcher::dispatchRequest() HTTP_HEAD\r\n"); + methCode = HTTP_HEAD; + } + else + { + printf("HTTPRequestDispatcher::dispatchRequest() Parse error\r\n"); + close(); //Parse error + return; + } + + printf("Looking for a handler\r\n"); + map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocketConnection*) >::iterator it; +// it = m_pSvr->m_lpHandlers.find(rootPath); //We are friends so we can do that +// NEW CODE START: + int root_len = 0; +//** for (it = m_pSvr->m_lpHandlers.begin(); it != m_pSvr->m_lpHandlers.end(); it++) + for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) + { + printf("Checking %s...\r\n", (*it).first.c_str()); + root_len = (*it).first.length(); + if ( root_len && + !path.compare( 0, root_len, (*it).first ) && + (path[root_len] == '/' || path[root_len] == '\0')) + { + printf("Found (%s)\r\n", (*it).first.c_str()); + // Found! + break; // for + } + } +// NEW CODE END +//** if((it == m_pSvr->m_lpHandlers.end()) && !(m_pSvr->m_lpHandlers.empty())) + if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) + { + printf("Using default handler\r\n"); +//** it = m_pSvr->m_lpHandlers.end(); + it = m_lpHandlers.end(); + it--; //Get the last element + if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler +//** it = m_pSvr->m_lpHandlers.end(); + it = m_lpHandlers.end(); + root_len = 0; + } +//** if(it == m_pSvr->m_lpHandlers.end()) + if(it == m_lpHandlers.end()) + { + printf("No handler found\r\n"); + close(); //No handler found + return; + } + printf("Handler found.\r\n"); + +//HTTPRequestHandler* pHdlr = (*it).second(rootPath.c_str(), subPath.c_str(), m_pTCPSocket); +//NEW CODE 1 LINE: + HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, m_pTCPSocketConnection); + m_pTCPSocketConnection = NULL; //We don't own it anymore + + switch(methCode) + { + case HTTP_GET: + pHdlr->doGet(); + break; + case HTTP_POST: + pHdlr->doPost(); + break; + case HTTP_HEAD: + pHdlr->doHead(); + break; + } + + printf("Req handled (or being handled)\r\n"); + close(); + //delete pHdlr; + //delete m_pTCPSocketConnection; +} + +void HTTPRequestDispatcher::close() //Close socket and destroy data +{ + if(m_closed) + return; + m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else + m_watchdog.detach(); + /** + if(m_pTCPSocket) //m_pTCPSocket Should only be destroyed if ownership not passed to an handler + { + m_pTCPSocket->resetOnEvent(); + m_pTCPSocket->close(); + delete m_pTCPSocket; //This fn might have been called by this socket (through an event), so DO NOT DESTROY IT HERE + } + NetService::close(); + **/ +} + + +void HTTPRequestDispatcher::onTimeout() //Connection has timed out +{ + close(); +} + +bool HTTPRequestDispatcher::getRequest(string* path, string* meth) +{ + char req[128]; + char c_path[128]; + char c_meth[128]; + const int maxLen = 128; + char* p = req; + //Read Line + int ret; + int len = 0; + for(int i = 0; i < maxLen - 1; i++) + { + ret = m_pTCPSocketConnection->receive(p, 1); + if(!ret) + { + break; + } + if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) + { + p--; + len-=2; + break; + } + else if( *p=='\n' ) + { + len--; + break; + } + p++; + len++; + } + *p = 0; + + DBG("Parsing request : %s\r\n", req); + + ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path); + if(ret !=2) + return false; + + *meth = string(c_meth); +// NEW CODE (old code removed): + *path = string(c_path); + return true; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPRequestHandler.cpp Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,230 @@ +/* +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. +*/ + +//#include "core/netservice.h" +#include "HTTPRequestHandler.h" + +#include <string.h> + +//#define __DEBUG +//#include "dbg/dbg.h" + +#define HTTP_REQUEST_TIMEOUT 5000 + +//HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : NetService(), +// m_pTCPSocketConnection(pTCPSocketConnection), m_reqHeaders(), m_respHeaders(), +// m_rootPath(rootPath), m_path(path), m_errc(200), +// m_watchdog(), m_timeout(0),**/ m_closed(false), m_headersSent(false) //OK +HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) : + m_pTCPSocketConnection(pTCPSocketConnection), m_reqHeaders(), m_respHeaders(), + m_rootPath(rootPath), m_path(path), m_errc(200), m_closed(false), m_headersSent(false) +{ + printf("+++(HTTPRequestHandler) init \r\n"); + //Read & parse headers + readHeaders(); +//* m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent); +//* setTimeout(HTTP_REQUEST_TIMEOUT); + printf("+++(HTTPRequestHandler) init end \r\n"); +} + +HTTPRequestHandler::~HTTPRequestHandler() +{ + close(); + printf("+++(HTTPRequestHandler) Destroy end\r\n"); +} + +void HTTPRequestHandler::onTimeout() //Connection has timed out +{ + close(); +} + +void HTTPRequestHandler::close() //Close socket and destroy data +{ + if(m_closed) + return; + m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else + /** m_watchdog.detach(); **/ +//* onClose(); +//* m_pTCPSocket->resetOnEvent(); +//* m_pTCPSocket->close(); +//* delete m_pTCPSocket; //Can safely destroy socket +//* NetService::close(); +} + +map<string, string>& HTTPRequestHandler::reqHeaders() //const +{ + return m_reqHeaders; +} + +string& HTTPRequestHandler::path() //const +{ + return m_path; +} + +int HTTPRequestHandler::dataLen() const +{ + map<string,string>::iterator it; + it = m_reqHeaders.find("Content-Length"); + if( it == m_reqHeaders.end() ) { + return 0; + } + return atoi((*it).second.c_str()); //return 0 if parse fails, so that's fine +} + +int HTTPRequestHandler::readData(char* buf, int len) +{ + return m_pTCPSocketConnection->receive(buf, len); +} + +string& HTTPRequestHandler::rootPath() //const +{ + return m_rootPath; +} + +void HTTPRequestHandler::setErrCode(int errc) +{ + m_errc = errc; +} + +void HTTPRequestHandler::setContentLen(int len) +{ + char len_str[6] = {0}; + sprintf(len_str, "%d", len); + respHeaders()["Content-Length"] = len_str; +} + +map<string, string>& HTTPRequestHandler::respHeaders() +{ + return m_respHeaders; +} + +int HTTPRequestHandler::writeData(const char* buf, int len) +{ + if(!m_headersSent) { + m_headersSent = true; + writeHeaders(); + } + return m_pTCPSocketConnection->send((char *)buf, len); +} +/** +void HTTPRequestHandler::setTimeout(int ms) +{ + m_timeout = 1000*ms; + resetTimeout(); +} +**/ +/** +void HTTPRequestHandler::resetTimeout() +{ + m_watchdog.detach(); + m_watchdog.attach_us<HTTPRequestHandler>(this, &HTTPRequestHandler::onTimeout, m_timeout); +} +**/ + +void HTTPRequestHandler::readHeaders() +{ + static char line[128]; + static char key[128]; + static char value[128]; + while( readLine(line, 128) > 0) { //if == 0, it is an empty line = end of headers + int n = sscanf(line, "%[^:]: %[^\n]", key, value); + if ( n == 2 ) { + printf("\r\n+++(HTTPRequestHandler)Read header : %s : %s\r\n", key, value); + m_reqHeaders[key] = value; + } + //TODO: Impl n==1 case (part 2 of previous header) + } +} + +void HTTPRequestHandler::writeHeaders() //Called at the first writeData call +{ + static char line[128]; + + //Response line + sprintf(line, "HTTP/1.1 %d MbedInfo\r\n", m_errc); //Not a violation of the standard not to include the descriptive text + m_pTCPSocketConnection->send(line, strlen(line)); + + map<string,string>::iterator it; + while( !m_respHeaders.empty() ) { + it = m_respHeaders.begin(); + sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() ); + printf("\r\n+++(HTTPRequestHandler)%s", line); + m_pTCPSocketConnection->send(line, strlen(line)); + m_respHeaders.erase(it); + } + m_pTCPSocketConnection->send("\r\n",2); //End of head +} + +int HTTPRequestHandler::readLine(char* str, int maxLen) +{ + int ret; + int len = 0; + for(int i = 0; i < maxLen - 1; i++) { + ret = m_pTCPSocketConnection->receive(str, 1); + if(!ret) { + break; + } + if( (len > 1) && *(str-1)=='\r' && *str=='\n' ) { + str--; + len-=2; + break; + } else if( *str=='\n' ) { + len--; + break; + } + str++; + len++; + } + *str = 0; + return len; +} +/** +void HTTPRequestHandler::onTCPSocketEvent(TCPSocketEvent e) +{ + //printf("\r\nEvent %d in HTTPRequestHandler\r\n", e); + printf("\r\n+++(HTTPRequestHandler)Event in HTTPRequestHandler\r\n"); + + if(m_closed) + { + printf("\r\n+++(HTTPRequestHandler)WARN: Discarded\r\n"); + return; + } + + switch(e) + { + case TCPSOCKET_READABLE: + resetTimeout(); + onReadable(); + break; + case TCPSOCKET_WRITEABLE: + resetTimeout(); + onWriteable(); + break; + case TCPSOCKET_CONTIMEOUT: + case TCPSOCKET_CONRST: + case TCPSOCKET_CONABRT: + case TCPSOCKET_ERROR: + case TCPSOCKET_DISCONNECTED: + DBG("\r\nConnection error in handler\r\n"); + close(); + break; + } +} +**/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPRequestHandler.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,102 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +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. +*/ + +/** +HTTP Request Handler header file. +*/ + +#ifndef HTTP_REQUEST_HANDLER_H +#define HTTP_REQUEST_HANDLER_H + +//*#include "api/TCPSocket.h" +//#include "HTTPServer.h" + +#include "mbed.h" +#include "EthernetInterface.h" +//*#include "core/netservice.h" + +#include <string> +using std::string; + +#include <map> +using std::map; + +///HTTP Server's generic request handler +class HTTPRequestHandler //*: public NetService +{ +public: + ///Instantiated by the HTTP Server + HTTPRequestHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection); + virtual ~HTTPRequestHandler(); + +//protected: + virtual void doGet() = 0; + virtual void doPost() = 0; + virtual void doHead() = 0; + + virtual void onReadable() = 0; //Data has been read + virtual void onWriteable() = 0; //Data has been written & buf is free + virtual void onTimeout(); //Connection has timed out + virtual void onClose() = 0; //Connection is closing + + virtual void close(); //Close socket and destroy data + +protected: + map<string, string>& reqHeaders() /*const*/; + string& path() /*const*/; + int dataLen() const; + int readData(char* buf, int len); + string& rootPath() /*const*/; + + void setErrCode(int errc); + void setContentLen(int len); + + map<string, string>& respHeaders(); + int writeData(const char* buf, int len); + +//* void setTimeout(int ms); +//* void resetTimeout(); + +private: + void readHeaders(); //Called at instanciation + void writeHeaders(); //Called at the first writeData call + //**void onTCPSocketEvent(/**TCPSocketEvent e**/); + + TCPSocketConnection* m_pTCPSocketConnection; + map<string, string> m_reqHeaders; + map<string, string> m_respHeaders; + string m_rootPath; + string m_path; + int m_errc; //Response code + +//* Timeout m_watchdog; +//* int m_timeout; + + bool m_closed; + bool m_headersSent; + + int readLine(char* str, int maxLen); + +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPServer.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,244 @@ +#ifndef HTTP_SERVER_H +#define HTTP_SERVER_H + +#include <string> +using std::string; + +#include <map> +using std::map; + +#include "HTTPRequestHandler.h" +#include "rtos.h" +#include "mbed.h" +#include "EthernetInterface.h" +//#include "HTTPRequestDispatcher.h" + +//#include "dbg/dbg.h" + +#define THREAD_MAX 5 +Thread *threads[THREAD_MAX]; +Thread *xthread; +//#include "HTTPServer2.h" + +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)); + } +}; + +map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers; +template<typename T> +void HTTPServerAddHandler(const char* path) //Template decl in header +{ + m_lpHandlers[path] = &T::inst; +} + +void ListenThread(void const *args); +//DigitalOut _led(LED4); +//bool serverIsListened; +//bool clientIsConnected; +enum HTTP_METH { + HTTP_GET, + HTTP_POST, + HTTP_HEAD +}; + +bool getRequest(TCPSocketConnection* client,string* path, string* meth) +{ + char req[128]; + char c_path[128]; + char c_meth[128]; + const int maxLen = 128; + char* p = req; + //Read Line + int ret; + int len = 0; + for(int i = 0; i < maxLen - 1; i++) { + ret = client->receive(p, 1); + if(!ret) { + break; + } + if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) { + p--; + len-=2; + break; + } else if( *p=='\n' ) { + len--; + break; + } + p++; + len++; + } + *p = 0; + + printf("Parsing request : %s\r\n", req); + ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path); + if(ret !=2) return false; + *meth = string(c_meth); + *path = string(c_path); + return true; +} + +void dispatchRequest(TCPSocketConnection* client) +{ + string path; + string meth; + HTTP_METH methCode; + + printf("Dispatching req\r\n"); + + if( !getRequest(client,&path, &meth ) ) { + printf("dispatchRequest Invalid request\r\n"); + //close(); + return; //Invalid request + } + if( !meth.compare("GET") ) { + printf("dispatchRequest HTTP_GET\r\n"); + methCode = HTTP_GET; + } else if( !meth.compare("POST") ) { + printf("dispatchRequest HTTP_POST\r\n"); + methCode = HTTP_POST; + } else if( !meth.compare("HEAD") ) { + printf("dispatchRequest HTTP_HEAD\r\n"); + methCode = HTTP_HEAD; + } else { + printf("dispatchRequest() Parse error\r\n"); + //close(); //Parse error + return; + } + + printf("Looking for a handler\r\n"); + map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocketConnection*) >::iterator it; + int root_len = 0; + for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) { + printf("Checking %s...\r\n", (*it).first.c_str()); + root_len = (*it).first.length(); + if ( root_len && + !path.compare( 0, root_len, (*it).first ) && + (path[root_len] == '/' || path[root_len] == '\0')) { + printf("Found (%s)\r\n", (*it).first.c_str()); + // Found! + break; // for + } + } + if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) { + printf("Using default handler\r\n"); + it = m_lpHandlers.end(); + it--; //Get the last element + if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler + it = m_lpHandlers.end(); + root_len = 0; + } + if(it == m_lpHandlers.end()) { + printf("No handler found\r\n"); + return; + } + printf("Handler found.\r\n"); + + HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client); + //**** client = NULL; //We don't own it anymore + switch(methCode) { + case HTTP_GET: + pHdlr->doGet(); + break; + case HTTP_POST: + pHdlr->doPost(); + break; + case HTTP_HEAD: + pHdlr->doHead(); + break; + } + delete pHdlr; + // delete client; + // delete m_pTCPSocketConnection; + printf("(dispatcherRequest)return\r\n"); + return ; +} + +void HTTPServerChild (void const *arg) +{ + printf("HTTPServerChiled Start......\r\n"); + TCPSocketConnection* client = (TCPSocketConnection*)arg; + + for (;;) { + printf("(HTTPServer.h<HTTPServerChild>)Connection from %s\r\n", client->get_address()); + dispatchRequest(client); + printf("(HTTPServer.h<HTTPServerChild>)Close %s\r\n", client->get_address()); + client->close(); + client->reset_address(); + //delete client; + Thread::signal_wait(1); + } +} + +void HTTPServerCloser (void const *arg) +{ + TCPSocketConnection *client = (TCPSocketConnection*)arg; + + for (;;) { + client->close(); + printf("Close %s\r\n", client->get_address()); + Thread::signal_wait(1); + } +} + +void HTTPServerStart(int port = 80) +{ + int i, t = 0; + TCPSocketConnection clients[THREAD_MAX]; + TCPSocketConnection xclient; + + for (i = 0; i < THREAD_MAX; i ++) { + threads[i] = NULL; + } + xthread = NULL; + + TCPSocketServer server; + server.bind(port); + server.listen(); + // server.set_blocking(false); + printf("Wait for new connection...\r\n"); + for (;;) { + printf("**Start Loop** \r\n"); + if (t >= 0) { + if(server.accept(clients[t])==0) { + // fork child process + if (threads[t]) { + threads[t]->signal_set(1); + } else { + threads[t] = new Thread(HTTPServerChild, (void*)&clients[t]); + } + printf("Forked %d\r\n", t); + } + } else { + if(server.accept(xclient)==0) { + // closer process + if (xthread) { + xthread->signal_set(1); + } else { + xthread = new Thread(HTTPServerCloser, (void*)&xclient); + } + printf("Connection full\r\n"); + } + } + + t = -1; + for (i = 0; i < THREAD_MAX; i ++) { + if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingAnd) { + if (t < 0) t = i; // next empty thread + } + } + Thread::wait(100); + } +} +#include "Handler/RPCHandler.h" +#include "Handler/FSHandler.h" +#include "Handler/SimpleHandler.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPServer.txt Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,186 @@ + +/* +Copyright (c) 2014 Yasushi TAUCHI + +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. +*/ +#include "rtos.h" +#include "mbed.h" +#include "EthernetInterface.h" +#include "HTTPRequestDispatcher.h" +#include "HTTPServer2.h" + +#define THREAD_MAX 5 +Thread *threads[THREAD_MAX]; +Thread *xthread; + + + +//#define __DEBUG +#include "dbg/dbg.h" +void ListenThread(void const *args); +DigitalOut _led(LED4); + +//class HTTPRequestDispatcher; +// TCPSocketServer TcpSocketServer; +bool serverIsListened; +// TCPSocketConnection client; +bool clientIsConnected; +void onTCPSocketEvent(/**TCPSocketEvent e**/); +/** +map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers; +template<typename T> +void HTTPServerAddHandler(const char* path) //Template decl in header +{ + m_lpHandlers[path] = &T::inst; +} +**/ +//* TCPSocket* m_pTCPSocket; +//map< string, HTTPRequestHandler*(*)(const char*, const char* /**, TCPSocket* **/), handlersComp > m_lpHandlers; +/** +template<typename T> +void HTTPServerAddHandler(const char* path) //Template decl in header +{ + m_lpHandlers[path] = &T::inst; +} +**/ +void HTTPServerChild (void const *arg) +{ + int i; + char buf[256]; + TCPSocketConnection* client = (TCPSocketConnection*)arg; + + for (;;) { + printf("Connection from %s\r\n", client->get_address()); +// client->set_blocking(false, 1500); // Timeout after (1.5)s +// printf("\r\nHTTPServer::onTCPSocketEvent : Event %d\r\n", e); + //TCPSocket* pTCPSocket; + //Host client; + +// if( !!m_pTCPSocket->accept(&client, &pTCPSocket) ) + // { + // DBG("\r\nHTTPServer::onTCPSocketEvent : Could not accept connection.\r\n"); + // return; //Error in accept, discard connection + // } + + // HTTPRequestDispatcher* pDispatcher = new HTTPRequestDispatcher(this, client); //TCPSocket ownership is passed to dispatcher + HTTPRequestDispatcher* pDispatcher ; + pDispatcher= new HTTPRequestDispatcher(m_lpHandlers,client); //TCPSocket ownership is passed to dispatcher + //The dispatcher object will destroy itself when done, or will be destroyed on Server destruction + + /** + for (;;) { + i = client->receive(buf, sizeof(buf)); + if (i < 0) break; + if (i == 0) continue; + buf[i] = 0; + printf("Recv '%s'\r\n", buf); + if (client->send(buf, i) < 0) break; + } + **/ + delete pDispatcher; + client->close(); + printf("Close %s\r\n", client->get_address()); + + Thread::signal_wait(1); + } +} + +void HTTPServerCloser (void const *arg) +{ + TCPSocketConnection *client = (TCPSocketConnection*)arg; + + for (;;) { + client->close(); + printf("Close %s\r\n", client->get_address()); + + Thread::signal_wait(1); + } +} + +void HTTPServerStart(int port /*= 80*/) +{ + int i, t = 0; + TCPSocketConnection clients[THREAD_MAX]; + TCPSocketConnection xclient; + + for (i = 0; i < THREAD_MAX; i ++) { + threads[i] = NULL; + } + xthread = NULL; + + TCPSocketServer server; + server.bind(port); + server.listen(); + + printf("Wait for new connection...\r\n"); + for (;;) { + if (t >= 0) { + server.accept(clients[t]); + // fork child process + if (threads[t]) { + threads[t]->signal_set(1); + } else { + threads[t] = new Thread(HTTPServerChild, (void*)&clients[t]); + } + printf("Forked %d\r\n", t); + } else { + server.accept(xclient); + // closer process + if (xthread) { + xthread->signal_set(1); + } else { + xthread = new Thread(HTTPServerCloser, (void*)&xclient); + } + printf("Connection full\r\n"); + } + + t = -1; + for (i = 0; i < THREAD_MAX; i ++) { + if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingAnd) { + if (t < 0) t = i; // next empty thread + } + } + } +} + +//void HTTPServer::onTCPSocketEvent(/**TCPSocketEvent e**/) +/** +void HTTPServerOnTCPSocketEvent(TCPSocketEvent e) +{ + + DBG("\r\nHTTPServer::onTCPSocketEvent : Event %d\r\n", e); + if(e==TCPSOCKET_ACCEPT) + { + TCPSocket* pTCPSocket; + Host client; + + if( !!m_pTCPSocket->accept(&client, &pTCPSocket) ) + { + DBG("\r\nHTTPServer::onTCPSocketEvent : Could not accept connection.\r\n"); + return; //Error in accept, discard connection + } + + HTTPRequestDispatcher* pDispatcher = new HTTPRequestDispatcher(this, pTCPSocket); //TCPSocket ownership is passed to dispatcher + //The dispatcher object will destroy itself when done, or will be destroyed on Server destruction + + } +} + **/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPServer2.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,109 @@ +/* +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. +*/ + +/** \file +HTTP Server header file +*/ + +#ifndef HTTP_SERVER_2_H +#define HTTP_SERVER_2_H + +//class HTTPRequestHandler; +//class HTTPRequestDispatcher; + +//*#include "core/net.h" +#include "HTTPRequestHandler.h" +#include "HTTPRequestDispatcher.h" +#include "EthernetInterface.h" + +#include <string> +using std::string; + +#include <map> +using std::map; + + +///A simple HTTP server implementation +/** +The HTTPServer is composed of: +- The actual server (HTTPServer) +- A request dispatcher, instanciated on each request (HTTPRequestDispatcher) +- Request handlers instanciated by the dispatcher(deriving from HTTPRequestHandler) +*/ +//class HTTPServer +//{ +//public: +// ///Instantiates the HTTP Server +// HTTPServer(); +// ~HTTPServer(); + + +///Adds a handler +/** +Appends a handler to the handlers list +@param T : class which will be instanciated to serve these requests +@param path : requests starting with this path will be served using this handler +*/ + +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)); + } +}; + +/* +template<typename T> +void HTTPServerAddHandler(const char* path) //Template decl in header +{ + m_lpHandlers[path] = &T::inst; +} +*/ + +//map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers; +/** +template<typename T> +void HTTPServerAddHandler(const char* path) //Template decl in header +{ + m_lpHandlers[path] = &T::inst; +} +**/ +///Starts listening +/** +Binds server to a specific port and starts listening +@param port : port on which to listen for incoming connections +*/ + + + +//}; + +//Including handlers here for more convenience +#include "Handler/RPCHandler.h" +#include "Handler/FSHandler.h" +#include "Handler/SimpleHandler.h" + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handler/FSHandler.cpp Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,161 @@ +/* +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. +*/ + +#include "FSHandler.h" + +//#define __DEBUG +//#include "dbg/dbg.h" + +#define CHUNK_SIZE 128 + +#define DEFAULT_PAGE "/index.htm" + +//*FSHandler::FSHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket), m_err404(false) +FSHandler::FSHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) : HTTPRequestHandler(rootPath, path, pTCPSocketConnection), m_err404(false) +{} + +FSHandler::~FSHandler() +{ + if(m_fp) + fclose(m_fp); + printf("\r\nHandler destroyed\r\n"); +} + +//static init +map<string,string> FSHandler::m_lFsPath = map<string,string>(); + +void FSHandler::mount(const string& fsPath, const string& rootPath) +{ + m_lFsPath[rootPath]=fsPath; +} + +void FSHandler::doGet() +{ + printf("\r\nIn FSHandler::doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str()); + //FIXME: Translate path to local/path + string checkedRootPath = rootPath(); + if(checkedRootPath.empty()) + checkedRootPath="/"; + string filePath = m_lFsPath[checkedRootPath]; + if (path().size() > 1) + { + filePath += path(); + } + else + { + filePath += DEFAULT_PAGE; + } + + printf("Trying to open %s\n", filePath.c_str()); + + m_fp = fopen(filePath.c_str(), "r"); //FIXME: if null, error 404 + + if(!m_fp) + { + m_err404 = true; + setErrCode(404); + const char* msg = "File not found."; + setContentLen(strlen(msg)); + respHeaders()["Content-Type"] = "text/html"; + respHeaders()["Connection"] = "close"; + writeData(msg,strlen(msg)); //Only send header + printf("\r\nExit FSHandler::doGet() w Error 404\r\n"); + return; + } + + //Seek EOF to get length + fseek(m_fp, 0, SEEK_END); + setContentLen( ftell(m_fp) ); + fseek(m_fp, 0, SEEK_SET); //Goto SOF + + respHeaders()["Connection"] = "close"; + onWriteable(); + printf("\r\nExit SimpleHandler::doGet()\r\n"); +} + +void FSHandler::doPost() +{ + +} + +void FSHandler::doHead() +{ + +} + +void FSHandler::onReadable() //Data has been read +{ + +} + +void FSHandler::onWriteable() //Data has been written & buf is free +{ + printf("\r\nFSHandler::onWriteable() event\r\n"); + if(m_err404) + { + //Error has been served, now exit + close(); + return; + } + + static char rBuf[CHUNK_SIZE]; + while(true) + { + int len = fread(rBuf, 1, CHUNK_SIZE, m_fp); + if(len>0) + { + int writtenLen = writeData(rBuf, len); + if(writtenLen < 0) //Socket error + { + printf("FSHandler: Socket error %d\n", writtenLen); + /** + if(writtenLen == TCPSOCKET_MEM) + { + fseek(m_fp, -len, SEEK_CUR); + return; //Wait for the queued TCP segments to be transmitted + } + else + { + //This is a critical error + close(); + return; + } + **/ + } + else if(writtenLen < len) //Short write, socket's buffer is full + { + fseek(m_fp, writtenLen - len, SEEK_CUR); + return; + } + } + else + { + close(); //Data written, we can close the connection + return; + } + } +} + +void FSHandler::onClose() //Connection is closing +{ + if(m_fp) + fclose(m_fp); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handler/FSHandler.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,58 @@ +/* +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 FS_HANDLER_H +#define FS_HANDLER_H + +#include "../HTTPRequestHandler.h" +#include "mbed.h" +#include "EthernetInterface.h" +#include <map> +using std::map; + +#include <string> +using std::string; + +class FSHandler : public HTTPRequestHandler +{ +public: + FSHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection); + virtual ~FSHandler(); + + static void mount(const string& fsPath, const string& rootPath); + +//protected: + static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) { return new FSHandler(rootPath, path, pTCPSocketConnection); } //if we ever could do static virtual functions, this would be one + + virtual void doGet(); + virtual void doPost(); + virtual void doHead(); + + virtual void onReadable(); //Data has been read + virtual void onWriteable(); //Data has been written & buf is free + virtual void onClose(); //Connection is closing + +private: + FILE* m_fp; + bool m_err404; + static map<string,string> m_lFsPath; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handler/RPCHandler.cpp Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,111 @@ +/* +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. +*/ + +#include "RPCHandler.h" +#include "rpc.h" + +//#define __DEBUG +//#include "dbg/dbg.h" + +#define RPC_DATA_LEN 128 + +RPCHandler::RPCHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) : HTTPRequestHandler(rootPath, path, pTCPSocketConnection) +{} + +RPCHandler::~RPCHandler() +{ + printf("\r\nHandler destroyed\r\n"); +} + +void RPCHandler::doGet() +{ + printf("\r\nIn RPCHandler::doGet()\r\n"); + char resp[RPC_DATA_LEN] = {0}; + char req[RPC_DATA_LEN] = {0}; + + printf("\r\nPath : %s\r\n", path().c_str()); + printf("\r\nRoot Path : %s\r\n", rootPath().c_str()); + + //Remove path + strncpy(req, path().c_str(), RPC_DATA_LEN-1); + printf("\r\nRPC req : %s\r\n", req); + + //Remove %20, +, from req + cleanReq(req); + printf("\r\nRPC req : %s\r\n", req); + + //Do RPC Call + //* mbed::rpc(req, resp); //FIXME: Use bool result + + //Response + setContentLen( strlen(resp) ); + + //Make sure that the browser won't cache this request + respHeaders()["Cache-control"]="no-cache;no-store"; + // respHeaders()["Cache-control"]="no-store"; + respHeaders()["Pragma"]="no-cache"; + respHeaders()["Expires"]="0"; + + //Write data + respHeaders()["Connection"] = "close"; + writeData(resp, strlen(resp)); + printf("\r\nExit RPCHandler::doGet()\r\n"); +} + +void RPCHandler::doPost() +{ + +} + +void RPCHandler::doHead() +{ + +} + + +void RPCHandler::onReadable() //Data has been read +{ + +} + +void RPCHandler::onWriteable() //Data has been written & buf is free +{ + printf("\r\nRPCHandler::onWriteable() event\r\n"); + close(); //Data written, we can close the connection +} + +void RPCHandler::onClose() //Connection is closing +{ + //Nothing to do +} + +void RPCHandler::cleanReq(char* data) +{ + char* p; + static const char* lGarbage[2] = {"%20", "+"}; + for(int i = 0; i < 2; i++) + { + while( p = strstr(data, lGarbage[i]) ) + { + memset((void*) p, ' ', strlen(lGarbage[i])); + } + } +} + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handler/RPCHandler.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,51 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +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 RPC_HANDLER_H +#define RPC_HANDLER_H + +#include "../HTTPRequestHandler.h" + +class RPCHandler : public HTTPRequestHandler +{ +public: + RPCHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection); + virtual ~RPCHandler(); + +//protected: + static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) { return new RPCHandler(rootPath, path, pTCPSocketConnection); } //if we ever could do static virtual functions, this would be one + + virtual void doGet(); + virtual void doPost(); + virtual void doHead(); + + virtual void onReadable(); //Data has been read + virtual void onWriteable(); //Data has been written & buf is free + virtual void onClose(); //Connection is closing + +protected: + void cleanReq(char* data); +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handler/SimpleHandler.cpp Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,74 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +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. +*/ + +#include "SimpleHandler.h" + +//#define __DEBUG +//#include "dbg/dbg.h" + +SimpleHandler::SimpleHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) : HTTPRequestHandler(rootPath, path, pTCPSocketConnection) +{ + printf("++++(SimpleHeader)Initialize\r\n"); +} + +SimpleHandler::~SimpleHandler() +{ + printf("++++(SimpleHeader)Handler destroyed\r\n"); +} + +void SimpleHandler::doGet() +{ + printf("++++(SimpleHeader) doGet()\r\n"); + const char* resp = "Hello world !"; + setContentLen( strlen(resp) ); + respHeaders()["Connection"] = "close"; + writeData(resp, strlen(resp)); + printf("++++(SimpleHeader) doGet Exit\r\n"); +} + +void SimpleHandler::doPost() +{ + +} + +void SimpleHandler::doHead() +{ + +} + + +void SimpleHandler::onReadable() //Data has been read +{ + +} + +void SimpleHandler::onWriteable() //Data has been written & buf is free +{ + printf("\r\n++++SimpleHandler::onWriteable() event\r\n"); + close(); //Data written, we can close the connection +} + +void SimpleHandler::onClose() //Connection is closing +{ + //Nothing to do +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handler/SimpleHandler.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,47 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +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 SIMPLE_HANDLER_H +#define SIMPLE_HANDLER_H + +#include "../HTTPRequestHandler.h" + +class SimpleHandler : public HTTPRequestHandler +{ +public: + SimpleHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection); + virtual ~SimpleHandler(); + +//protected: + static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) { return new SimpleHandler(rootPath, path, pTCPSocketConnection); } //if we ever could do static virtual functions, this would be one + + virtual void doGet(); + virtual void doPost(); + virtual void doHead(); + + virtual void onReadable(); //Data has been read + virtual void onWriteable(); //Data has been written & buf is free + virtual void onClose(); //Connection is closing +}; + +#endif