An example HTTP Server library using new Ethernet Interface

Dependents:   HTMLServer_Sample

Files at this revision

API Documentation at this revision

Comitter:
mkilivan
Date:
Tue Dec 23 18:49:25 2014 +0000
Commit message:
forked from http://developer.mbed.org/users/yueee_yt/code/giken9_HTMLServer_Sample/

Changed in this revision

HTTPRequestHandler.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPRequestHandler.h Show annotated file Show diff for this revision Revisions of this file
HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
Handler/FSHandler.cpp Show annotated file Show diff for this revision Revisions of this file
Handler/FSHandler.h Show annotated file Show diff for this revision Revisions of this file
Handler/RPCHandler.cpp Show annotated file Show diff for this revision Revisions of this file
Handler/RPCHandler.h Show annotated file Show diff for this revision Revisions of this file
Handler/SimpleHandler.cpp Show annotated file Show diff for this revision Revisions of this file
Handler/SimpleHandler.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 8e1971a883be HTTPRequestHandler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPRequestHandler.cpp	Tue Dec 23 18:49:25 2014 +0000
@@ -0,0 +1,386 @@
+/*
+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.
+*/
+//#define _DEBUG_REQUEST_HANDLER
+//#pragma O0
+#include "HTTPRequestHandler.h"
+
+#include <string.h>
+
+//#define HTTP_REQUEST_TIMEOUT 5000
+//#define HTTP_POST_REQUEST_TIMEOUT 2000
+#define READ_SIZE 128
+//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)
+{
+#ifdef _DEBUG_REQUEST_HANDLER
+    printf("+++(HTTPRequestHandler) init \r\n");
+#endif
+    req_headers_count=0;
+    resp_headers_count=0;
+    //Read & parse headers
+    readHeaders();
+//*  m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent);
+//*  setTimeout(HTTP_REQUEST_TIMEOUT);
+#ifdef _DEBUG_REQUEST_HANDLER
+    printf("+++(HTTPRequestHandler) init end \r\n");
+#endif
+}
+
+HTTPRequestHandler::~HTTPRequestHandler()
+{
+    close();
+#ifdef _DEBUG_REQUEST_HANDLER
+    printf("+++(HTTPRequestHandler) Destroy end\r\n");
+#endif
+}
+
+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_pTCPSocketConnection->close();
+//* delete m_pTCPSocketConnection; //Can safely destroy socket
+//*  NetService::close();
+}
+
+//map<string, string>& HTTPRequestHandler::reqHeaders() //const
+//{
+//    return m_reqHeaders;
+//}
+void HTTPRequestHandler::reqHeaders(string *key,string *value,unsigned char *count) //const
+{
+    for(int i=0; i<10; i++) {
+        key[i]=req_headers_key[i];
+        value[i]=req_headers_value[i];
+    }
+    *count=req_headers_count;
+//    return m_reqHeaders;
+}
+
+string& HTTPRequestHandler::path() //const
+{
+    return m_path;
+}
+
+int HTTPRequestHandler::dataLen() const
+{
+    int ret=0;
+    if (clength>0) ret=clength;
+    //   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
+    return ret;
+}
+
+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[7] = {0};
+//#ifdef _DEBUG_REQUEST_HANDLER
+    printf( "+++(HTTPRequestHandler)Content-Length %d \r\n", len);
+//#endif
+    sprintf(len_str, "%d", len);
+//    respHeaders()["Content-Length"] = len_str;
+    addRespHeaders("Content-Length",string(len_str));
+}
+
+//map<string, string>& HTTPRequestHandler::respHeaders()
+//{
+//    return m_respHeaders;
+//}
+
+void HTTPRequestHandler::respHeaders(string *key,string *value,unsigned char *count )
+{
+    for(int i=0; i<10; i++) {
+        key[i]=resp_headers_key[i];
+        value[i]=resp_headers_value[i];
+    }
+    *count=resp_headers_count;
+}
+
+
+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];
+    char *p;
+    chunkmode=false;
+    req_headers_count=0;
+    resp_headers_count=0;
+    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 ) {
+#ifdef _DEBUG_REQUEST_HANDLER
+            printf("+++(HTTPRequestHandler)Read header : %s : %s\r\n", key, value);
+#endif
+            //    m_reqHeaders[key] = value;
+            if(req_headers_count<10) {
+                req_headers_key[req_headers_count]=string(key);
+                req_headers_value[req_headers_count]=string(value);
+                req_headers_count++;
+            }
+            //Check Content Length
+            for(p=&key[0]; p<(&key[0]+strlen(key)); p++) {
+                if((*p>0x60)&&(*p<0x7b))*p=*p-0x20;
+            }
+#ifdef _DEBUG_REQUEST_SERVER_H
+            printf("+++(HTTPRequestHandler) HEADER %s\r\n",key);
+#endif
+            if(strcmp(key,"CONTENT-LENGTH")==0) {
+                sscanf(value,"%d",&clength);
+            } else if(strcmp(key,"TRANSFER-ENCODING")==0) {
+                for(p=&value[0]; p<(&value[0]+strlen(value)); p++) {
+                    if((*p>0x60)&&(*p<0x7b))*p=*p-0x20;
+                }
+                if(strcmp(value,"CHUNKED")==0)chunkmode=true;
+            }
+        }
+        //TODO: Impl n==1 case (part 2 of previous header)
+    }
+}
+
+void HTTPRequestHandler::readReqData()
+{
+    int i;
+    //ReadHeader
+#ifdef _DEBUG_REQUEST_SERVER_H
+    printf("+++(HTTPRequestHandler)content-length: %d \r\n",cont_length);
+    if(chunkmode==true)printf("+++(HTTPRequestHandler)CHUNK Transfer \r\n");
+    else printf("+++(HTTPRequestHandler)NO CHUNK Transfer \r\n");
+#endif
+//   m_pTCPSocketConnection->set_blocking(true,HTTP_POST_REQUEST_TIMEOUT);
+    char buffer[READ_SIZE+1];
+    if(chunkmode==false) {
+        //no chunked mode
+        for(;;) {
+            if(clength>READ_SIZE) {
+                i=m_pTCPSocketConnection->receive(buffer,READ_SIZE);
+                buffer[READ_SIZE]=0x0;
+                m_reqData.append(string(buffer));
+                clength-=READ_SIZE;
+            } else {
+                i=m_pTCPSocketConnection->receive(buffer, clength);
+                buffer[clength]=0x0;
+                m_reqData.append(string(buffer));
+                break;
+            }
+        }
+        if(i>0)printf("Success \r\n");
+    } else {
+        //chunked mode
+        int chunk_size;
+
+        for(;;) {
+            i=readLine(buffer,20);
+            printf("chunk :%s:\r\n",buffer);
+            sscanf(buffer,"%x",&chunk_size);
+            printf("chunk_size = %d \r\n",chunk_size);
+            if(chunk_size==0)break;
+            for(;;) {
+                if(chunk_size>READ_SIZE) {
+                    i=m_pTCPSocketConnection->receive(buffer, READ_SIZE);
+                    buffer[READ_SIZE]=0x0;
+                    m_reqData.append(string(buffer));
+                    chunk_size-=READ_SIZE;
+                } else {
+                    i=m_pTCPSocketConnection->receive(buffer, chunk_size);
+                    buffer[chunk_size]=0x0;
+                    m_reqData.append(string(buffer));
+                    break;
+                }
+            }
+            i=m_pTCPSocketConnection->receive(buffer,2); //\r\n ro read
+        }
+//   i=readLine(buffer,20);//dummy
+    }
+//        m_pTCPSocketConnection->set_blocking(false);
+//        while(m_pTCPSocketConnection->receive(buffer,1)>0){}
+//     m_pTCPSocketConnection->set_blocking(false);
+//    printf("%s \r\n",m_reqData.c_str());
+}
+
+void HTTPRequestHandler::writeHeaders() //Called at the first writeData call
+{
+    char line[128]= {0};
+    int i;
+    //Response line
+    //printf("Hdebug e1\r\n");
+    //m_pTCPSocketConnection->receive(line, 1);
+    //printf("%d \r\n",line[0]);
+
+    sprintf(line, "HTTP/1.1 %d OK\r\n", m_errc); //Not a violation of the standard not to include the descriptive text
+    //printf("debug e2 %d:%s \r\n",strlen(line),line);
+    //if(m_pTCPSocketConnection->is_connected()==true) {
+    //    printf("Connect \r\n");
+    //} else {
+    //    printf("disconnected \r\n");
+    //}
+    //return;
+    m_pTCPSocketConnection->send(line, strlen(line));
+//    map<string,string>::iterator it;
+    //printf("%d debug e3 \r\n",resp_headers_count);
+    for(i=0; i<resp_headers_count; i++) {
+//    while( !m_respHeaders.empty() ) {
+//        it = m_respHeaders.begin();
+//        sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() );
+//        printf("debug e\r\n");
+        sprintf(line, "%s: %s\r\n", resp_headers_key[i].c_str(),resp_headers_value[i].c_str());
+//        printf("debug e2 %s %d\r\n",line,strlen(line));
+#ifdef _DEBUG_REQUEST_HANDLER
+        printf("\r\n+++(HTTPRequestHandler)Write header %s \r\n", line);
+#endif
+        m_pTCPSocketConnection->send(line, strlen(line));
+//        m_respHeaders.erase(it);
+    }
+    m_pTCPSocketConnection->send("\r\n",2); //End of head
+}
+
+void HTTPRequestHandler::addRespHeaders(string key,string value)
+{
+    if(resp_headers_count<10) {
+        resp_headers_key[resp_headers_count]=string(key);
+        resp_headers_value[resp_headers_count]=string(value);
+        resp_headers_count++;
+    } else {
+        printf("MAX over resp_headers_num \r\n");
+    }
+}
+
+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;
+  }
+}
+**/
+char* HTTPRequestHandler::getAddress(void)
+{
+    return   m_pTCPSocketConnection->get_address();
+}
+
+string& HTTPRequestHandler::getRequestData(void)
+{
+    return  m_reqData;
+}
+
diff -r 000000000000 -r 8e1971a883be HTTPRequestHandler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPRequestHandler.h	Tue Dec 23 18:49:25 2014 +0000
@@ -0,0 +1,119 @@
+
+/*
+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 "HTTPServer.h"
+
+#include "mbed.h"
+#include "EthernetInterface.h"
+
+#include <string>
+using std::string;
+
+#include <map>
+using std::map;
+
+///HTTP Server's generic request handler
+class HTTPRequestHandler
+{
+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*/;
+    void reqHeaders(string *key,string *value,unsigned char *count);
+    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();
+    void respHeaders(string *key,string *value,unsigned char *count );
+
+    int writeData(const char* buf, int len);
+    char* getAddress(void);
+    string& getRequestData(void);
+    void addRespHeaders(string key,string value);
+
+    void readReqData();
+
+//* 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 req_headers_key[10];
+    string req_headers_value[10];
+    unsigned char req_headers_count;
+    string resp_headers_key[10];
+    string resp_headers_value[10];
+    unsigned char resp_headers_count;
+    string m_rootPath;
+    string m_path;
+    string m_reqData;
+
+    int m_errc; //Response code
+
+//*  Timeout m_watchdog;
+//*  int m_timeout;
+
+    bool m_closed;
+    bool m_headersSent;
+
+    int readLine(char* str, int maxLen);
+int clength;
+bool chunkmode;
+};
+
+#endif
+
+
diff -r 000000000000 -r 8e1971a883be HTTPServer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.h	Tue Dec 23 18:49:25 2014 +0000
@@ -0,0 +1,360 @@
+//#define _DEBUG_HTTP_SERVER_H
+
+#ifndef HTTP_SERVER_H
+#define HTTP_SERVER_H
+
+#define HELLO_PAGE "/hello"
+#define RPC_PAGE "/rpc"
+//#define IEEE1888WSDL_PAGE "/IEEE1888?wsdl"
+//#define IEEE1888_PAGE "/IEEE1888"
+#define FS_PAGE "/"
+
+#include <string>
+using std::string;
+
+#include <map>
+using std::map;
+
+#include "HTTPRequestHandler.h"
+#include "rtos.h"
+#include "mbed.h"
+#include "EthernetInterface.h"
+
+#include "Handler/RPCHandler.h"
+#include "Handler/FSHandler.h"
+#include "Handler/SimpleHandler.h"
+
+#define THREAD_MAX 3
+Thread *threads[THREAD_MAX];
+Thread *xthread;
+
+/*
+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);
+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;
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("Parsing request : %s\r\n", req);
+#endif
+    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;
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("Dispatching req\r\n");
+#endif
+    if( !getRequest(client,&path, &meth ) ) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("dispatchRequest Invalid request\r\n");
+#endif
+        //close();
+        return; //Invalid request
+    }
+    if( !meth.compare("GET") ) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("dispatchRequest HTTP_GET\r\n");
+#endif
+        methCode = HTTP_GET;
+    } else if( !meth.compare("POST") ) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("dispatchRequest HTTP_POST\r\n");
+#endif
+        methCode = HTTP_POST;
+    } else if( !meth.compare("HEAD") ) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("dispatchRequest HTTP_HEAD\r\n");
+#endif
+        methCode = HTTP_HEAD;
+    } else {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("dispatchRequest() Parse error\r\n");
+#endif
+        //close(); //Parse error
+        return;
+    }
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("Looking for a handler\r\n");
+#endif
+    /*
+        map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocketConnection*) >::iterator it;
+        int root_len = 0;
+        for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) {
+    #ifdef _DEBUG_HTTP_SERVER_H
+            printf("Checking %s...\r\n", (*it).first.c_str());
+    #endif
+            root_len = (*it).first.length();
+            if ( root_len &&
+                    !path.compare( 0, root_len, (*it).first ) &&
+                    (path[root_len] == '/' || path[root_len] == '\0')) {
+    #ifdef _DEBUG_HTTP_SERVER_H
+                printf("Found (%s)\r\n", (*it).first.c_str());
+    #endif
+                // Found!
+                break;  // for
+            }
+        }
+        if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) {
+    #ifdef _DEBUG_HTTP_SERVER_H
+            printf("Using default handler\r\n");
+    #endif
+            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()) {
+    #ifdef _DEBUG_HTTP_SERVER_H
+            printf("No handler found\r\n");
+    #endif
+            return;
+        }
+    #ifdef _DEBUG_HTTP_SERVER_H
+        printf("Handler found.\r\n");
+    #endif
+        HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client);
+    */
+    HTTPRequestHandler* pHdlr;
+    if (!path.compare(0,strlen(HELLO_PAGE),HELLO_PAGE)) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("HELLO PAGE CREATE. PATH %s: %s \r\n",HELLO_PAGE, path.c_str() + strlen(HELLO_PAGE));
+#endif
+        pHdlr = new SimpleHandler(HELLO_PAGE, path.c_str() + strlen(HELLO_PAGE), client);
+    }
+    
+#ifdef RPC_PAGE
+    else if (!path.compare(0,strlen(RPC_PAGE),RPC_PAGE)) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("RPC PAGE CREATE. PATH %s: %s \r\n",RPC_PAGE, path.c_str() + strlen(RPC_PAGE));
+#endif
+        pHdlr = new RPCHandler(RPC_PAGE, path.c_str() + strlen(RPC_PAGE), client);
+    }
+#endif
+
+#ifdef IEEE1888WSDL_PAGE
+    else if (!path.compare(0,strlen(IEEE1888WSDL_PAGE),IEEE1888WSDL_PAGE)) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("IEEE1888WSDL_PAGE CREATE. PATH %s: %s \r\n",IEEE1888WSDL_PAGE, path.c_str() + strlen(IEEE1888WSDL_PAGE));
+#endif
+        pHdlr = new IEEE1888WSDLHandler(IEEE1888WSDL_PAGE, path.c_str() + strlen(IEEE1888WSDL_PAGE)-1, client);
+    }
+#endif
+
+#ifdef IEEE1888_PAGE
+    else if (!path.compare(0,strlen(IEEE1888_PAGE),IEEE1888_PAGE)) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("IEEE1888_PAGE CREATE. PATH %s: %s \r\n",IEEE1888_PAGE, path.c_str() + strlen(IEEE1888_PAGE));
+#endif
+        pHdlr = new IEEE1888Handler(IEEE1888_PAGE, path.c_str() + strlen(IEEE1888_PAGE)-1, client);
+    }
+#endif
+
+#ifdef FS_PAGE
+    else if (!path.compare(0,strlen(FS_PAGE),FS_PAGE)) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("FS_PAGE CREATE. PATH %s: %s \r\n",FS_PAGE, path.c_str() + strlen(FS_PAGE));
+#endif
+        pHdlr = new FSHandler(FS_PAGE, path.c_str() + strlen(FS_PAGE)-1, client);
+    }
+#endif
+
+    else {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("No handler found\r\n");
+#endif
+        pHdlr = new SimpleHandler(HELLO_PAGE, path.c_str() + strlen(HELLO_PAGE), client);
+        return;
+    }
+    //****  client = NULL; //We don't own it anymore
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("Handler Created.\r\n");
+#endif
+    switch(methCode) {
+        case HTTP_GET:
+            pHdlr->doGet();
+            break;
+        case HTTP_POST:
+            pHdlr->doPost();
+            break;
+        case HTTP_HEAD:
+            pHdlr->doHead();
+            break;
+    }
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("Handler Delete.\r\n");
+#endif
+    delete pHdlr;
+    // delete client;
+    //delete pTCPSocketConnection;
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("(dispatcherRequest)return\r\n");
+#endif
+    return ;
+}
+
+void HTTPServerChild (void const *arg)
+{
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("HTTPServerChiled Start......\r\n");
+#endif
+    TCPSocketConnection* client = (TCPSocketConnection*)arg;
+
+    for (;;) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("(HTTPServer.h<HTTPServerChild>)Connection from %s\r\n", client->get_address());
+#endif
+        dispatchRequest(client);
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("(HTTPServer.h<HTTPServerChild>)Client->Close %s\r\n", client->get_address());
+#endif
+        client->close();
+#ifdef _DEBUG_HTTP_SERVER_H
+ //       printf("(HTTPServer.h<HTTPServerChild>)Client->reset\r\n");
+#endif
+ //       client->reset_address();
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("(HTTPServer.h<HTTPServerChild>)Thread::signal_wait(1)\r\n");
+#endif        //delete client;
+        Thread::signal_wait(1);
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("(HTTPServer.h<HTTPServerChild>)Return \r\n");
+#endif
+    }
+}
+
+void HTTPServerCloser (void const *arg)
+{
+    TCPSocketConnection *client = (TCPSocketConnection*)arg;
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("HTTPCloser start%s\r\n", client->get_address());
+#endif
+
+    for (;;) {
+        client->close();
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("Close %s\r\n", client->get_address());
+#endif
+        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);
+#ifdef _DEBUG_HTTP_SERVER_H
+    printf("Wait for new connection...\r\n");
+#endif
+    for (;;) {
+#ifdef _DEBUG_HTTP_SERVER_H
+        printf("**Start Loop** \r\n");
+#endif
+        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]);
+                }
+#ifdef _DEBUG_HTTP_SERVER_H
+                printf("Forked %d\r\n", t);
+#endif
+            }
+        } else {
+            if(server.accept(xclient)==0) {
+                // closer process
+                if (xthread) {
+                    xthread->signal_set(1);
+                } else {
+                    xthread = new Thread(HTTPServerCloser, (void*)&xclient);
+                }
+#ifdef _DEBUG_HTTP_SERVER_H
+                printf("Connection full\r\n");
+#endif
+            }
+        }
+
+        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);
+    }
+}
+
+
+#endif
+
+
diff -r 000000000000 -r 8e1971a883be Handler/FSHandler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/FSHandler.cpp	Tue Dec 23 18:49:25 2014 +0000
@@ -0,0 +1,210 @@
+/*
+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.
+*/
+//#define _DEBUG_FS_HANDLER
+
+#include "FSHandler.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()
+{
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler) destroy\r\n");
+#endif
+    if(m_fp) {
+#ifdef _DEBUG_FS_HANDLER
+        printf("++++(FSHandler) fclose start\r\n");
+#endif
+        fclose(m_fp);
+#ifdef _DEBUG_FS_HANDLER
+        printf("+++(FSHandler) fclose end\r\n");
+#endif
+
+    }
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler)Handler destroyed\r\n");
+#endif
+}
+
+//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()
+{
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler)doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str());
+#endif
+    //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;
+    }
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler)Trying to open %s\r\n", filePath.c_str());
+#endif
+    m_fp = fopen(filePath.c_str(), "r"); //FIXME: if null, error 404
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler) opened %s\r\n", filePath.c_str());
+#endif
+
+    if(!m_fp) {
+#ifdef _DEBUG_FS_HANDLER
+        printf("++++(FSHandler)404Error\r\n");
+#endif
+
+        m_err404 = true;
+        setErrCode(404);
+        const char* msg = "File not found.";
+        setContentLen(strlen(msg));
+//        respHeaders()["Content-Type"] = "text/html";
+//        respHeaders()["Connection"] = "close";
+        addRespHeaders("Content-Type", "text/html");
+        addRespHeaders("Connection", "close");
+        writeData(msg,strlen(msg)); //Only send header
+        printf("++++(FSHandler)\r\nExit FSHandler::doGet() w Error 404\r\n");
+        return;
+    }
+  //  printf("++++(FSHandler) Seek start\r\n");
+    //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";
+    addRespHeaders("Connection", "close");
+ //   printf("++++(FSHandler)Write start\r\n");
+    onWriteable();
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler)Exit doGet()\r\n");
+#endif
+}
+
+void FSHandler::doPost()
+{
+
+}
+
+void FSHandler::doHead()
+{
+
+}
+
+void FSHandler::onReadable() //Data has been read
+{
+
+}
+
+void FSHandler::onWriteable() //Data has been written & buf is free
+{
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler)onWriteable() event\r\n");
+#endif
+    if(m_err404) {
+#ifdef _DEBUG_FS_HANDLER
+        printf("++++(FSHandler)m_err404\r\n");
+#endif
+        //Error has been served, now exit
+        close();
+        return;
+    }
+#ifdef _DEBUG_FS_HANDLER
+    printf("++++(FSHandler)not m_err404\r\n");
+#endif
+
+    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
+#ifdef _DEBUG_FS_HANDLER
+                printf("++++(FSHandler) Socket error %d\r\n", writtenLen);
+#endif
+                /**  Not Work
+                                if(writtenLen == TCPSOCKET_MEM) {
+                                    #ifdef _DEBUG_FS_HANDLER
+                printf("FSHandler: Socket error %d\n", writtenLen);
+                #endif
+                                    fseek(m_fp, -len, SEEK_CUR);
+                                    return; //Wait for the queued TCP segments to be transmitted
+                                } else {
+                                    //This is a critical error
+                                    **/
+#ifdef _DEBUG_FS_HANDLER
+                printf("++++(FSHandler)critical error\r\n");
+#endif
+                close();
+                return;
+                /**
+                }
+                **/
+            } else if(writtenLen < len) { //Short write, socket's buffer is full
+#ifdef _DEBUG_FS_HANDLER
+                printf("++++(FSHandler)Short write, socket's buffer is full\r\n");
+#endif
+                fseek(m_fp, writtenLen - len, SEEK_CUR);
+                return;
+            }
+        } else {
+            close(); //Data written, we can close the connection
+            return;
+        }
+    }
+}
+
+void FSHandler::onClose() //Connection is closing
+{
+    /**
+    #ifdef _DEBUG_FS_HANDLER
+        printf("FSHandler: onClose start \r\n");
+    #endif
+    if(m_fp){
+    #ifdef _DEBUG_FS_HANDLER
+        printf("FSHandler: fclose start \r\n");
+    #endif
+    fclose(m_fp);
+    #ifdef _DEBUG_FS_HANDLER
+    printf("FSHandler: fclose end \r\n");
+    #endif
+    }
+    #ifdef _DEBUG_FS_HANDLER
+        printf("FSHandler: onClose end \r\n");
+    #endif
+    **/
+}
+
+
diff -r 000000000000 -r 8e1971a883be Handler/FSHandler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/FSHandler.h	Tue Dec 23 18:49:25 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
diff -r 000000000000 -r 8e1971a883be Handler/RPCHandler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/RPCHandler.cpp	Tue Dec 23 18:49:25 2014 +0000
@@ -0,0 +1,140 @@
+/*
+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.
+*/
+
+//#define _DEBUG_RPC_HANDLER
+
+#include "RPCHandler.h"
+#include "mbed_rpc.h"
+
+#define RPC_DATA_LEN 64
+
+RPCHandler::RPCHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) : HTTPRequestHandler(rootPath, path, pTCPSocketConnection)
+{}
+
+RPCHandler::~RPCHandler()
+{
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)Handler destroyed\r\n");
+#endif
+}
+
+void RPCHandler::doGet()
+{
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)doGet\r\n");
+#endif
+    char resp[RPC_DATA_LEN] = {0};
+    char req[RPC_DATA_LEN] = {0};
+
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)Path : %s\r\n", path().c_str());
+    printf("++++(RPC Handler)Root Path : %s\r\n", rootPath().c_str());
+#endif
+    //Remove path
+    strncpy(req, path().c_str(), RPC_DATA_LEN-1);
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)RPC req(before) : %s\r\n", req);
+#endif
+    //Remove "%20", "+", "," from req
+    cleanReq(req);
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)RPC req(after) : %s\r\n", req);
+#endif
+    //Do RPC Call
+    RPC::call(req, resp); //FIXME: Use bool result
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)Response %s \r\n",resp);
+#endif
+    //Response
+    setContentLen( strlen(resp) );
+
+    //Make sure that the browser won't cache this request
+//    respHeaders()["Cache-control"]="no-cache;no-store";
+//    respHeaders()["Pragma"]="no-cache";
+//    respHeaders()["Expires"]="0";
+ addRespHeaders("Cache-control","no-cache;no-store");
+     addRespHeaders("Pragma","no-cache");
+     addRespHeaders("Expires","0");
+
+    //Write data
+//    respHeaders()["Connection"] = "close";
+    addRespHeaders("Connection", "close");
+    writeData(resp, strlen(resp));
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)Exit RPCHandler::doGet()\r\n");
+#endif
+}
+
+void RPCHandler::doPost()
+{
+
+}
+
+void RPCHandler::doHead()
+{
+
+}
+
+
+void RPCHandler::onReadable() //Data has been read
+{
+
+}
+
+void RPCHandler::onWriteable() //Data has been written & buf is free
+{
+#ifdef _DEBUG_RPC_HANDLER
+    printf("++++(RPC Handler)onWriteable event\r\n");
+#endif
+   // close(); //Data written, we can close the connection
+}
+
+void RPCHandler::onClose() //Connection is closing
+{
+    //Nothing to do
+}
+
+void RPCHandler::cleanReq(char* data)
+{
+    char* p;
+    if((p = strstr(data, "+"))!=NULL)memset((void*) p, ' ', 1);
+    else if((p = strstr(data, ","))!=NULL)memset((void*) p, ' ', 1);
+    else if((p = strstr(data, "%20"))!=NULL) {
+        memset((void*) p, ' ', 1);
+        while(*(p+2)!=NULL) {
+            p++;
+            memset((void*) p,*(p+2),1);
+        }
+    }
+
+    if((p = strstr(data, "+"))!=NULL)memset((void*) p, ' ', 1);
+    else if((p = strstr(data, ","))!=NULL)memset((void*) p, ' ', 1);
+    else if((p = strstr(data, "%20"))!=NULL) {
+        memset((void*) p, ' ', 1);
+        while(*(p+2)!=NULL) {
+            p++;
+            memset((void*) p,*(p+2),1);
+        }
+    }
+}
+
+
+
+
diff -r 000000000000 -r 8e1971a883be Handler/RPCHandler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/RPCHandler.h	Tue Dec 23 18:49:25 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
+
diff -r 000000000000 -r 8e1971a883be Handler/SimpleHandler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/SimpleHandler.cpp	Tue Dec 23 18:49:25 2014 +0000
@@ -0,0 +1,83 @@
+/*
+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.
+*/
+//#define _DEBUG_SIMPLE_HANDLER
+
+#include "SimpleHandler.h"
+
+SimpleHandler::SimpleHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) : HTTPRequestHandler(rootPath, path, pTCPSocketConnection)
+{
+#ifdef _DEBUG_SIMPLE_HANDLER
+    printf("++++(SimpleHeandler)Initialize\r\n");
+#endif
+}
+
+SimpleHandler::~SimpleHandler()
+{
+#ifdef _DEBUG_SIMPLE_HANDLER
+    printf("++++(SimpleHeandler)Handler destroyed\r\n");
+#endif
+}
+
+void SimpleHandler::doGet()
+{
+#ifdef _DEBUG_SIMPLE_HANDLER
+    printf("++++(SimpleHeandler) doGet()\r\n");
+#endif
+    const char* resp = "Hello world !";
+    setContentLen( strlen(resp) );
+    //respHeaders()["Connection"] = "close";
+    addRespHeaders("Connection", "close");
+    writeData(resp, strlen(resp));
+#ifdef _DEBUG_SIMPLE_HANDLER
+    printf("++++(SimpleHeandler) doGet Exit\r\n");
+#endif
+}
+
+void SimpleHandler::doPost()
+{
+
+}
+
+void SimpleHandler::doHead()
+{
+
+}
+
+
+void SimpleHandler::onReadable() //Data has been read
+{
+
+}
+
+void SimpleHandler::onWriteable() //Data has been written & buf is free
+{
+#ifdef _DEBUG_SIMPLE_HANDLER
+    printf("++++(SimpleHeandler)onWriteable() event\r\n");
+#endif
+//    close(); //Data written, we can close the connection
+}
+
+void SimpleHandler::onClose() //Connection is closing
+{
+    //Nothing to do
+}
+
diff -r 000000000000 -r 8e1971a883be Handler/SimpleHandler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/SimpleHandler.h	Tue Dec 23 18:49:25 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