This programme Sets a web server using light weigh ip (using Donatien Garnier's server code) which reads a voltage and saves it value in an htm file to be displayed on local page. Server 2 2nd edition Two issues here 1 ) the compiler throws a warning about assignment in RPCHandler.cpp and 2) the local .htm file created on the mbed flash memory is always date stamped with the default date 01/01/2008 11:00
Dependencies: EthernetNetIf NTPClient_NetServices mbed
Revision 0:03e1db2fe866, committed 2010-08-08
- Comitter:
- pmr1
- Date:
- Sun Aug 08 22:00:39 2010 +0000
- Commit message:
Changed in this revision
diff -r 000000000000 -r 03e1db2fe866 EthernetNetIf.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetNetIf.lib Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
diff -r 000000000000 -r 03e1db2fe866 NTPClient.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient.lib Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/NTPClient/#7c3f1199256a
diff -r 000000000000 -r 03e1db2fe866 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da
diff -r 000000000000 -r 03e1db2fe866 pmr_svr3.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pmr_svr3.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,101 @@ +#include "mbed.h" +#include "EthernetNetIf.h" +#include "HTTPServer.h" +#include "NTPClient.h" + +DigitalOut led1(LED1, "led1"); +DigitalOut led2(LED2, "led2"); +DigitalOut led3(LED3, "led3"); +DigitalOut led4(LED4, "led4"); + +AnalogIn Voltmeter (p20); + +LocalFileSystem fs("webfs"); // this could be any name + +EthernetNetIf eth; +HTTPServer svr; +NTPClient ntp; + +int updateVolts(time_t ctTime) + { + + FILE *fp = fopen("/webfs/volts.htm", "w"); // Open local filename + // it ignores path and date defaults 1/1/2008 becausse RTC not set + // if I call ithe localfilesystem www rather than 'local' it writes and is seen when drive is refreshed + fprintf(fp, "<title> Volt meter test page </title>\n"); + fprintf(fp,"<h1>Volts of the day from port 1</h1>"); + fprintf(fp, "volts %f V at %s \r\n",Voltmeter.read(), ctime(&ctTime)); + fclose(fp); + return(0); + } + + long int loadTime(void) + { + time_t ctTime; + ctTime = time(NULL); + char locTime[32]; +// printf("Current time is (UTC): %s\n\r", ctime(&ctTime)); + + Host server(IpAddr(), 123, "0.uk.pool.ntp.org"); + ntp.setTime(server); + + ctTime = time(NULL); + set_time (ctTime); // sets local rtc + time_t seconds = time(NULL); + strftime(locTime,32, "%I:%M %p\r\n",localtime(&seconds)); + printf("RTC Time is now (UTC): %s\n\r",locTime ); + return (ctTime); + } + + +int main() { + + time_t systemTime; + Base::add_rpc_class<DigitalOut>(); + + printf("Setting up...\n"); + EthernetErr ethErr = eth.setup(); + if(ethErr) + { + printf("Error %d in setup.\n", ethErr); + return -1; + } + printf("Setup OK\n"); + +// FSHandler::mount("/webfs", "/files"); //Mount /wwww path on /files web path - this has no meaning + FSHandler::mount("/webfs", "/"); //Mount /wwww path on web root path + + +// svr.addHandler<SimpleHandler>("/"); hard code for Hello world + + + systemTime=loadTime(); + + printf("System is now (UTC): %s\n\r", ctime(&systemTime)); + Timer tm; + tm.start(); + + + svr.addHandler<RPCHandler>("/rpc"); // sets up the remote procedure call handler + svr.addHandler<FSHandler>("/files");// this does not see the subdirectory + svr.addHandler<FSHandler>("/"); //Default handler + svr.bind(80); + updateVolts(systemTime); + printf("Listening...\n\r"); + //Listen indefinitely + while(true) + { + Net::poll(); + if(tm.read()>0.5) + { + led1=!led1; //Show that we are alive + // writing to this file continually updates the drive as attached as a usb drive to the host and generates errors so not good + // and even at 2 second interval the auto play continually brings up windows + // updateVolts(); + tm.start(); + } + } + + return 0; + +} \ No newline at end of file
diff -r 000000000000 -r 03e1db2fe866 server/HTTPRequestDispatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/HTTPRequestDispatcher.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,231 @@ + +/* +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 "core/netservice.h" +#include "HTTPRequestDispatcher.h" +#include "HTTPRequestHandler.h" +#include <string.h> + +//#define __DEBUG +#include "dbg/dbg.h" + +HTTPRequestDispatcher::HTTPRequestDispatcher(HTTPServer* pSvr, TCPSocket* pTCPSocket) : NetService(), m_pSvr(pSvr), m_pTCPSocket(pTCPSocket), m_watchdog(), m_closed(false) +{ + m_pTCPSocket->setOnEvent(this, &HTTPRequestDispatcher::onTCPSocketEvent); + m_watchdog.attach_us<HTTPRequestDispatcher>(this, &HTTPRequestDispatcher::onTimeout, HTTP_REQUEST_TIMEOUT * 1000); +} + +HTTPRequestDispatcher::~HTTPRequestDispatcher() +{ + close(); +} + +void HTTPRequestDispatcher::dispatchRequest() +{ + string path; + string meth; + HTTP_METH methCode; + + DBG("Dispatching req\r\n"); + + if( !getRequest(&path, &meth ) ) + { + close(); + return; //Invalid request + } + + if( !meth.compare("GET") ) + { + methCode = HTTP_GET; + } + else if( !meth.compare("POST") ) + { + methCode = HTTP_POST; + } + else if( !meth.compare("HEAD") ) + { + methCode = HTTP_HEAD; + } + else + { + close(); //Parse error + return; + } + + DBG("Looking for a handler\r\n"); + + map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*) >::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++) + { + DBG("Checking %s...\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')) + { + DBG("Found (%s)\n", (*it).first.c_str()); + // Found! + break; // for + } + } +// NEW CODE END + if((it == m_pSvr->m_lpHandlers.end()) && !(m_pSvr->m_lpHandlers.empty())) + { + DBG("Using default handler\n"); + it = m_pSvr->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(); + root_len = 0; + } + if(it == m_pSvr->m_lpHandlers.end()) + { + DBG("No handler found\n"); + close(); //No handler found + return; + } + + DBG("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_pTCPSocket); + m_pTCPSocket = 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; + } + + DBG("Req handled (or being handled)\r\n"); + close(); +} + +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_pTCPSocket->recv(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; +} + + + +void HTTPRequestDispatcher::onTCPSocketEvent(TCPSocketEvent e) +{ + + DBG("\r\nEvent %d\r\n", e); + + if(m_closed) + { + DBG("\r\nWARN: Discarded\r\n"); + return; + } + + switch(e) + { + case TCPSOCKET_READABLE: + m_watchdog.detach(); + m_pTCPSocket->resetOnEvent(); + //Req arrived, dispatch : + dispatchRequest(); + break; + case TCPSOCKET_CONTIMEOUT: + case TCPSOCKET_CONRST: + case TCPSOCKET_CONABRT: + case TCPSOCKET_ERROR: + case TCPSOCKET_DISCONNECTED: + close(); + break; + } + +}
diff -r 000000000000 -r 03e1db2fe866 server/HTTPRequestDispatcher.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/HTTPRequestDispatcher.h Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,72 @@ + +/* +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 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" + +#define HTTP_REQUEST_TIMEOUT 5000 + +#include <string> +using std::string; + +class HTTPRequestDispatcher : public NetService +{ +public: + HTTPRequestDispatcher(HTTPServer* pSvr, TCPSocket* pTCPSocket); + 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; + TCPSocket* m_pTCPSocket; + + Timeout m_watchdog; + bool m_closed; +}; + +#endif
diff -r 000000000000 -r 03e1db2fe866 server/HTTPRequestHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/HTTPRequestHandler.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,237 @@ + +/* +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 "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_pTCPSocket(pTCPSocket), 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 +{ + //Read & parse headers + readHeaders(); + m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent); + setTimeout(HTTP_REQUEST_TIMEOUT); +} + +HTTPRequestHandler::~HTTPRequestHandler() +{ + close(); +} + +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_pTCPSocket->recv(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_pTCPSocket->send(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 ) + { + DBG("\r\nRead 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_pTCPSocket->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() ); + DBG("\r\n%s", line); + m_pTCPSocket->send(line, strlen(line)); + m_respHeaders.erase(it); + } + m_pTCPSocket->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_pTCPSocket->recv(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) +{ + + DBG("\r\nEvent %d in HTTPRequestHandler\r\n", e); + + if(m_closed) + { + DBG("\r\nWARN: 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; + } + +}
diff -r 000000000000 -r 03e1db2fe866 server/HTTPRequestHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/HTTPRequestHandler.h Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,101 @@ + +/* +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 "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, TCPSocket* pTCPSocket); + 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); + + TCPSocket* m_pTCPSocket; + 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
diff -r 000000000000 -r 03e1db2fe866 server/HTTPServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/HTTPServer.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,77 @@ + +/* +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 "HTTPServer.h" + +//#define __DEBUG +#include "dbg/dbg.h" + +HTTPServer::HTTPServer() +{ + m_pTCPSocket = new TCPSocket; + m_pTCPSocket->setOnEvent(this, &HTTPServer::onTCPSocketEvent); +} + +HTTPServer::~HTTPServer() +{ + delete m_pTCPSocket; +} + +void HTTPServer::bind(int port /*= 80*/) +{ + Host h(IpAddr(127,0,0,1), port, "localhost"); + m_pTCPSocket->bind(h); + m_pTCPSocket->listen(); //Listen +} + +#if 0 //Just for clarity +template<typename T> +void HTTPServer::addHandler(const char* path) +{ + m_lpHandlers[path] = &T::inst; + +} +#endif + +void HTTPServer::onTCPSocketEvent(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 + + } + +}
diff -r 000000000000 -r 03e1db2fe866 server/HTTPServer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/HTTPServer.h Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,104 @@ + +/* +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. +*/ + +/** \file +HTTP Server header file +*/ + +#ifndef HTTP_SERVER_H +#define HTTP_SERVER_H + +class HTTPRequestHandler; +class HTTPRequestDispatcher; + +#include "core/net.h" +#include "HTTPRequestHandler.h" +#include "HTTPRequestDispatcher.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(); + + 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)); + } + }; + + ///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 + */ + template<typename T> + void addHandler(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 + */ + void bind(int port = 80); + +private: + friend class HTTPRequestDispatcher; + + void onTCPSocketEvent(TCPSocketEvent e); + + TCPSocket* m_pTCPSocket; + map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*), handlersComp > m_lpHandlers; + +}; + +//Including handlers here for more convenience +#include "impl/RPCHandler.h" +#include "impl/FSHandler.h" +#include "impl/SimpleHandler.h" + +#endif
diff -r 000000000000 -r 03e1db2fe866 server/impl/FSHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/impl/FSHandler.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,160 @@ + +/* +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 "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() +{ + if(m_fp) + fclose(m_fp); + DBG("\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() +{ + DBG("\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; + } + + DBG("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 + DBG("\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(); + DBG("\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 +{ + DBG("\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 + { + DBG("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); +}
diff -r 000000000000 -r 03e1db2fe866 server/impl/FSHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/impl/FSHandler.h Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,61 @@ + +/* +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 FS_HANDLER_H +#define FS_HANDLER_H + +#include "../HTTPRequestHandler.h" +#include "mbed.h" + +#include <map> +using std::map; + +#include <string> +using std::string; + +class FSHandler : public HTTPRequestHandler +{ +public: + FSHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket); + virtual ~FSHandler(); + + static void mount(const string& fsPath, const string& rootPath); + +//protected: + static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket) { return new FSHandler(rootPath, path, pTCPSocket); } //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
diff -r 000000000000 -r 03e1db2fe866 server/impl/RPCHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/impl/RPCHandler.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,115 @@ + +/* +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 "RPCHandler.h" +#include "rpc.h" + +//#define __DEBUG +#include "dbg/dbg.h" + +#define RPC_DATA_LEN 128 + +RPCHandler::RPCHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket) +{} + +RPCHandler::~RPCHandler() +{ + DBG("\r\nHandler destroyed\r\n"); +} + +void RPCHandler::doGet() +{ + DBG("\r\nIn RPCHandler::doGet()\r\n"); + char resp[RPC_DATA_LEN] = {0}; + char req[RPC_DATA_LEN] = {0}; + + DBG("\r\nPath : %s\r\n", path().c_str()); + DBG("\r\nRoot Path : %s\r\n", rootPath().c_str()); + + //Remove path + strncpy(req, path().c_str(), RPC_DATA_LEN-1); + DBG("\r\nRPC req : %s\r\n", req); + + //Remove %20, +, from req + cleanReq(req); + DBG("\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)); + DBG("\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 +{ + DBG("\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])); + } + } +} + +
diff -r 000000000000 -r 03e1db2fe866 server/impl/RPCHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/impl/RPCHandler.h Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,50 @@ + +/* +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, TCPSocket* pTCPSocket); + virtual ~RPCHandler(); + +//protected: + static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket) { return new RPCHandler(rootPath, path, pTCPSocket); } //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
diff -r 000000000000 -r 03e1db2fe866 server/impl/SimpleHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/impl/SimpleHandler.cpp Sun Aug 08 22:00:39 2010 +0000 @@ -0,0 +1,72 @@ + +/* +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, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket) +{} + +SimpleHandler::~SimpleHandler() +{ + DBG("\r\nHandler destroyed\r\n"); +} + +void SimpleHandler::doGet() +{ + DBG("\r\nIn SimpleHandler::doGet()\r\n"); + const char* resp = "Hello world !"; + setContentLen( strlen(resp) ); + respHeaders()["Connection"] = "close"; + writeData(resp, strlen(resp)); + DBG("\r\nExit SimpleHandler::doGet()\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 +{ + DBG("\r\nSimpleHandler::onWriteable() event\r\n"); + close(); //Data written, we can close the connection +} + +void SimpleHandler::onClose() //Connection is closing +{ + //Nothing to do +}
diff -r 000000000000 -r 03e1db2fe866 server/impl/SimpleHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/impl/SimpleHandler.h Sun Aug 08 22:00:39 2010 +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, TCPSocket* pTCPSocket); + virtual ~SimpleHandler(); + +//protected: + static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket) { return new SimpleHandler(rootPath, path, pTCPSocket); } //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