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

Files at this revision

API Documentation at this revision

Comitter:
pmr1
Date:
Sun Aug 08 22:00:39 2010 +0000
Commit message:

Changed in this revision

EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
NTPClient.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
pmr_svr3.cpp Show annotated file Show diff for this revision Revisions of this file
server/HTTPRequestDispatcher.cpp Show annotated file Show diff for this revision Revisions of this file
server/HTTPRequestDispatcher.h Show annotated file Show diff for this revision Revisions of this file
server/HTTPRequestHandler.cpp Show annotated file Show diff for this revision Revisions of this file
server/HTTPRequestHandler.h Show annotated file Show diff for this revision Revisions of this file
server/HTTPServer.cpp Show annotated file Show diff for this revision Revisions of this file
server/HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
server/impl/FSHandler.cpp Show annotated file Show diff for this revision Revisions of this file
server/impl/FSHandler.h Show annotated file Show diff for this revision Revisions of this file
server/impl/RPCHandler.cpp Show annotated file Show diff for this revision Revisions of this file
server/impl/RPCHandler.h Show annotated file Show diff for this revision Revisions of this file
server/impl/SimpleHandler.cpp Show annotated file Show diff for this revision Revisions of this file
server/impl/SimpleHandler.h Show annotated file Show diff for this revision Revisions of this file
--- /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
--- /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
--- /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
--- /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
--- /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;
+  }
+  
+}
--- /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
--- /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;
+  }
+  
+}
--- /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
--- /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
+   
+  }
+  
+}
--- /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
--- /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);
+}
--- /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
--- /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]));
+    }
+  }
+}
+  
+  
--- /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
--- /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
+}
--- /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