Server that executes RPC commands through HTTP.

Dependencies:   EthernetInterface mbed-rpc mbed-rtos mbed

Import programHTTP-Server

Server that executes RPC commands through HTTP.

Overview

This program is a small HTTP Server that can execute RPC commands sent through HTTP and sends back a reply. This reply can be either a line of text or an HTML page.

HTTP Request

The server will only read the first line of the HTTP header. It does not check that the header is correct and it does not attempt to read the body. Hence, the server is only interested in the type of the request and the path. Instead of requesting a file, the path contains the RPC command.

RPC command encoding

Information

The RPC command must be encoded in a special way because no spaces are allowed in the path.

Thus, the RPC command is encoded in this way :

/<obj name or type>/<func name>?arg1_name=arg1_val&arg2_name=arg2_val

or, if the RPC command does not have any arguments :

/<obj name or type>/<func name>

So, a complete URL might be :

http://10.2.200.116/led2/write?val=1

The name of the arguments does not appear in the final RPC command. So these 3 urls will do exactly the same thing :

http://10.2.200.116/led2/write?val=1
http://10.2.200.116/led2/write?test=1
http://10.2.200.116/led2/write?blabla=1

Also, the order of the arguments are preserved.

Request handlers

To process requests, the server relies on RequestHandler. Each RequestHandler is assigned to a request type. Each type of request is assigned to a certain role :

  • PUT requests to create new objects
  • DELETE requests to delete objects
  • GET requests to call a function of an object

However, there is a RequestHandler that accepts only GET requests but it can create/delete/call a function. This was necessary to provide an interactive web page that allows creation and deletion of objects.

Reply

The reply depends on the formatter. Currently, three formatters are available :

  • The most basic one does not modify the RPC reply. Hence, if you consider sending request from python scripts, this formatter is the most appropriate one.
  • A simple HTML formatter will allow the user to view the RPC reply and a list of RPC objects currently alive from a browser.
  • Finally, a more complex HTML formatter creates an entire web page where the user can create and delete an object as well as calling functions on these objects.

Configure the server

The configuration of the server consists on choosing the formatter and adding one or more request handlers to the server. The main function initializes the server in order to produce HTML code and to receive data only using GET requests. If you want to use a simpler and different version of the server you can change the content of the main function (located in main.cpp) by this code :

main

    RPCType::instance().register_types();    

    EthernetInterface eth;
    eth.init();
    eth.connect();
    printf("IP Address is %s\n", eth.getIPAddress());
    
    HTTPServer srv = create_simple_server();

    if(!srv.init(SERVER_PORT))
    {
        printf("Error while initializing the server\n");
        eth.disconnect();
        return -1;
    }

    srv.run();

    return 0;

However, this configuration will not work with the following examples.

Examples

I assume that the server is using the InteractiveHTMLFormatter (which should be the case if you did not make any changes).

Using a browser

Here is a quick guide how to run this program :

  1. Compiles this program and copies it to the mbed
  2. Open TeraTerm (install it if you don't have it), select serial and choose the port named "mbed Serial Port"
  3. Reset your mbed
  4. The IP address should appear in teraterm. In this example, I will use 10.2.200.116.
  5. Open your browser and go to http://10.2.200.116/.
  6. If everything is ok, you should see a webpage.

Now, let's switch on a led. First, we need to create an object to control a led :

Then, let's write an RPC command to switch on led :


Using python

This program creates and switches on led2.

Sending RPC commands over HTTP with Python

import httplib

SERVER_ADDRESS = '10.2.200.38'

h = httplib.HTTPConnection(SERVER_ADDRESS)
h.request("GET", "/DigitalOut/new?arg=LED2&name=led2")
r = h.getresponse()
print r.read()

h.request("GET", "/led2/write?arg=1")
r = h.getresponse()
print r.read()

h.close()

Of course, you might have to change the server address in order to make it work.

Files at this revision

API Documentation at this revision

Comitter:
feb11
Date:
Wed Jul 17 10:15:05 2013 +0000
Child:
1:2efb8b4cc4bc
Commit message:
Initial import

Changed in this revision

EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
Formatter.cpp Show annotated file Show diff for this revision Revisions of this file
Formatter.h Show annotated file Show diff for this revision Revisions of this file
HTTPServer.cpp 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
RPCCommand.cpp Show annotated file Show diff for this revision Revisions of this file
RPCCommand.h Show annotated file Show diff for this revision Revisions of this file
RPCObjectManager.cpp Show annotated file Show diff for this revision Revisions of this file
RPCObjectManager.h Show annotated file Show diff for this revision Revisions of this file
RPCType.cpp Show annotated file Show diff for this revision Revisions of this file
RPCType.h Show annotated file Show diff for this revision Revisions of this file
RequestHandler.cpp Show annotated file Show diff for this revision Revisions of this file
RequestHandler.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rpc.lib Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetInterface.lib	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/EthernetInterface/#f533841d34cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Formatter.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,181 @@
+#include "Formatter.h"
+#include "mbed.h"
+#include "RPCObjectManager.h"
+#include "EthernetInterface.h"
+
+const char *SIMPLE_HTML_CODE = "\
+<!DOCTYPE html>\
+<html>\
+    <head>\
+        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\
+        <title>TCP Server</title>\
+    </head>\
+    <body>";
+
+
+const char* INTERACTIVE_HTML_CODE_1 = "\
+<!DOCTYPE html>\
+<html>\
+    <head>\
+        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\
+        <title>TCP Server</title>\
+        <script type=\"text/javascript\">\
+            var ip = \"%s\";\
+            function submitCreateForm()\
+            {\
+                var list = document.getElementById(\"type\");\
+                var type = list.options[list.selectedIndex].value;\
+                var name = document.getElementById(\"name\").value;\
+                var arg = document.getElementById(\"arg\").value;\
+                var url;\
+                if(arg === \"\")\
+                    url = \"http://\" + ip + type + \"new?name=\" + name;\
+                else\
+                    url = \"http://\" + ip + type + \"new?arg=\" + arg + \"&name=\" + name;\
+                location.href= url;\
+            }\
+            function submitCallFuncForm()\
+            {\
+                var command = document.getElementById(\"command\").value;\
+                var tmp = command.split(\' \');\
+                var url = tmp[0];\
+                if(tmp.length > 1)\
+                    url += \"?\";\
+                for(var i = 1; i < tmp.length; ++i)\
+                {\
+                    url += \"arg\" + i + \"=\" + tmp[i];\
+                    if(i+1 < tmp.length)\
+                        url += \"&\";\
+                }\
+                location.href = url;\
+            }\
+        </script>\
+    </head> \
+<body>";
+    
+const char* INTERACTIVE_HTML_CODE_2 = "<h3>Create Object :</h3>\
+    <form id=\"create\" method=\"get\">\
+    Type: <select id=\"type\">\
+        <option value=\"/DigitalOut/\">DigitalOut</option>\
+        <option value=\"/DigitalIn/\">DigitalIn</option>\
+        <option value=\"/DigitalInOut/\">DigitalInOut</option>\
+        <option value=\"/PwmOut/\">PwmOut</option>\
+        <option value=\"/Timer/\">Timer</option>\
+        </select><br>\
+    name: <input type=\"text\" id=\"name\"><br>\
+    arg(optional): <input type=\"text\" id=\"arg\">\
+    <p><input type=\"button\" value=\"Create\" onclick=\"javascript:submitCreateForm();\"></p>\
+    </form> \
+    \
+    <h3>Call a function :</h3>\
+    <p>Enter an RPC command.</p>\
+    <form method=\"get\">\
+    Command: <input type= \"text\" id=\"command\"><br>\
+    <input type=\"button\" value=\"Send\" onclick=\"javascript:submitCallFuncForm();\"><br>\
+    </form>\
+    </body> \
+</html>";
+
+static char chunk[1024];
+        
+Formatter::Formatter(int nb):
+currentChunk(0),
+nbChunk(nb)
+{
+}    
+
+char* Formatter::get_page(char *reply)
+{
+    chunk[0] = '\0';
+
+    if(currentChunk < nbChunk)
+    {
+        get_chunk(currentChunk, reply);
+        currentChunk++;
+    }
+    else
+        currentChunk = 0;
+    
+    return chunk;
+}    
+
+void Formatter::get_chunk(const int c, char *reply)
+{
+    strcat(chunk, reply);
+}
+
+SimpleHTMLFormatter::SimpleHTMLFormatter():
+Formatter()
+{
+}
+
+void SimpleHTMLFormatter::get_chunk(const int c, char* reply)
+{
+    strcat(chunk, SIMPLE_HTML_CODE);
+    
+    if(reply != NULL && strlen(reply) != 0)
+    {
+        strcat(chunk, "RPC reply : ");
+        strcat(chunk, reply);
+    }
+        
+    if(!RPCObjectManager::instance().is_empty())
+    {
+        strcat(chunk, "<ul>");
+        for(std::list<char*>::iterator itor = RPCObjectManager::instance().begin();
+            itor != RPCObjectManager::instance().end();
+            ++itor)
+        {
+            strcat(chunk, "<li>");
+            strcat(chunk, *itor);
+            strcat(chunk, "</li>");
+        }
+        strcat(chunk, "</ul>");
+    }
+    
+    strcat(chunk, "</body></html>");
+}
+
+InteractiveHTMLFormatter::InteractiveHTMLFormatter():
+Formatter(3)
+{
+}
+
+void InteractiveHTMLFormatter::get_chunk(const int c, char *reply)
+{
+    if(c == 0)
+        sprintf(chunk, INTERACTIVE_HTML_CODE_1, EthernetInterface::getIPAddress());
+    else if(c == 1)
+    {
+        if(reply != NULL && strlen(reply) != 0)
+        {
+            strcat(chunk, "RPC reply : ");
+            strcat(chunk, reply);
+        }
+        if(!RPCObjectManager::instance().is_empty())
+        {
+            strcat(chunk, "<p>Objects created :</p>");
+
+            strcat(chunk, "<ul>");
+            for(std::list<char*>::iterator itor = RPCObjectManager::instance().begin();
+                itor != RPCObjectManager::instance().end();
+                ++itor)
+            {
+                strcat(chunk, "<li>");
+                strcat(chunk, *itor);
+                strcat(chunk, " (<a href=\"http://");
+                strcat(chunk, EthernetInterface::getIPAddress());
+                strcat(chunk, "/");
+                strcat(chunk, *itor);
+                strcat(chunk, "/delete\">delete</a>)");
+                strcat(chunk, "</li>");
+            }
+            strcat(chunk, "</ul>");
+        }
+        strcat(chunk, " ");
+    }
+    else if(c == 2)
+        strcat(chunk, INTERACTIVE_HTML_CODE_2);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Formatter.h	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,48 @@
+#ifndef FORMATTER
+#define FORMATTER
+
+
+class Formatter
+{
+    public :
+        
+        Formatter(int nbChunk = 1);
+        
+        char* get_page(char *reply);
+        
+    protected :
+    
+        virtual void get_chunk(const int c, char *reply);
+        
+    private :
+    
+        int currentChunk;
+        int nbChunk;
+};
+
+class SimpleHTMLFormatter : public Formatter
+{        
+    public :
+    
+        SimpleHTMLFormatter();
+        
+    protected :
+    
+        virtual void get_chunk(const int c, char *reply);
+
+};
+
+class InteractiveHTMLFormatter : public Formatter
+{
+    public :
+    
+        InteractiveHTMLFormatter();
+
+    protected :
+        
+        virtual void get_chunk(const int c, char *reply);
+};
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,110 @@
+#include "HTTPServer.h"
+
+#define INVALID_FORMATTER "No valid formatter specified"
+
+bool cmp(char* a, char* b)
+{
+    return strcmp(a,b) < 0;
+}
+const char *TEST = "\
+<!DOCTYPE html>\
+<html>\
+    <head>\
+        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\
+        <title>TCP Server</title>\
+    </head>\
+    <body>Hello World !</body></html>";
+HTTPServer::HTTPServer(Formatter *f):
+socket(),
+handlers(&cmp),
+formatter(f),
+reply(),
+command()
+{
+}
+
+HTTPServer::~HTTPServer()
+{
+    for(std::map<char*, RequestHandler*>::iterator itor = handlers.begin();
+        itor != handlers.end();
+        ++itor)
+        delete itor->second;
+    
+    if(formatter)
+        delete formatter;
+}
+
+bool HTTPServer::init(int port)
+{
+    socket.set_blocking(true);
+    return !socket.bind(port) && !socket.listen();
+}
+
+void HTTPServer::run()
+{
+    TCPSocketConnection c;
+    while(true)
+    {
+        while(socket.accept(c));
+        c.set_blocking(false, 1000);
+        while(c.is_connected())
+        {
+            char buffer[512];
+            int n = c.receive_all(buffer, sizeof(buffer)-1);
+            if(n == 0)
+            {
+                c.close();
+                break;
+            }
+            else if(n != -1)
+            {
+                buffer[n] = '\0';
+                handle_request(buffer);
+                if(formatter != NULL)
+                {
+                    char *page = formatter->get_page(reply);
+                    do
+                    {
+                        c.send(page, strlen(page)+1);
+                        page = formatter->get_page(reply);
+                    }while(strlen(page)>0);
+                }
+                else
+                    c.send(INVALID_FORMATTER, strlen(INVALID_FORMATTER)+1);
+            }
+        }
+    }
+}
+
+void HTTPServer::handle_request(char *buffer)
+{
+    char *request_type = strtok(buffer, " ");
+    char *request = strtok(NULL, " ");
+
+    reply[0] = '\0';
+    if(!strcmp(request, "/"))
+        return;    
+    
+    if(!command.decode(request))
+    {
+        strcat(reply, "Malformed request");
+        return;
+    }
+    
+    std::map<char*, RequestHandler*>::iterator itor = handlers.find(request_type);
+    if(itor == handlers.end())
+    {
+        strcat(reply, "Only PUT, DELETE and GET requests are accepted.");
+        return;
+    }
+    if(itor->second != NULL)
+        itor->second->handle(command, reply);
+    else
+        strcat(reply, "Invalid request handler");
+}
+
+void HTTPServer::add_request_handler(char *name, RequestHandler* handler)
+{
+    handlers[name] = handler;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.h	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,39 @@
+#ifndef HTTP_SERVER
+#define HTTP_SERVER
+
+#include <map>
+
+#include "mbed.h"
+#include "mbed_rpc.h"
+#include "RequestHandler.h"
+#include "Formatter.h"
+#include "EthernetInterface.h"
+#include "RPCCommand.h"
+
+
+class HTTPServer
+{
+    public :
+    
+        HTTPServer(Formatter *f = new Formatter());
+        virtual ~HTTPServer();
+        
+        bool init(int port);
+
+        void run();
+        
+        void add_request_handler(char *name, RequestHandler* handler);
+        
+    private :
+
+        void handle_request(char *buffer);
+        
+        TCPSocketServer socket;
+        std::map<char*, RequestHandler*, bool(*)(char*, char*)> handlers;
+        Formatter *formatter;
+        char reply[RPC_MAX_STRING];
+        RPCCommand command;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCCommand.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,130 @@
+#include "RPCCommand.h"
+#include "mbed.h"
+#include "RPCType.h"
+
+
+RPCCommand::RPCCommand():
+cmd(),
+obj_name(NULL),
+func_name(NULL)
+{
+
+}
+
+bool RPCCommand::decode(char *buffer)
+{
+    if(buffer == NULL)
+        return false;
+    if(buffer[0] != '/')
+        return false;
+    
+    ++buffer;
+    char *tmp = strchr(buffer ,'/');
+
+    if(tmp == NULL)
+        return false;
+    if(tmp == buffer)
+        return false;
+    
+    tmp[0] = '\0';
+    obj_name = buffer;
+    
+    buffer = tmp+1;
+    
+    if(buffer[0] == '\0' || buffer[0] == '?')
+        return false;
+    
+    func_name = buffer;
+    
+    tmp = strchr(buffer, '?');
+    if(tmp != NULL)
+    {
+        if(tmp[1] == '\0')
+            return false;
+        tmp[0] = '\0';
+    }
+    
+    cmd[0] = '\0';
+    strcat(cmd, "/");
+    strcat(cmd, obj_name);
+    strcat(cmd, "/");
+    strcat(cmd, func_name);
+
+    if(tmp == NULL)
+        return true;
+    
+    buffer = tmp+1;
+    do
+    {
+        tmp = strchr(buffer, '&');
+        
+        if(tmp != NULL)
+        {
+            if(tmp[1] == '\0' || buffer == tmp)
+                return false;
+            tmp[0] = '\0';
+        }
+
+        char *sep = strchr(buffer, '=');
+        if(sep == NULL)
+            return false;
+        if(sep == buffer)
+            return false;
+        if(sep[1] == '\0' || sep[1] == '&')
+            return false;
+        
+        strcat(cmd, " ");
+        strcat(cmd, sep+1);
+        
+        if(tmp != NULL)
+            buffer = tmp+1;
+        else
+            buffer = NULL;
+    }while(buffer);
+    
+    return true;
+}
+
+
+
+char* RPCCommand::get_cmd() const
+{
+    return (char*)cmd;
+}
+
+RPC_COMMAND_TYPE RPCCommand::get_type() const
+{
+    if(!strcmp(func_name, "new") && RPCType::instance().is_supported_type(obj_name))
+        return CREATE;
+    
+    RPC* r = RPC::lookup(obj_name);
+    if(r == NULL)
+        return INVALID;
+    
+    if(!strcmp(func_name, "delete"))
+        return DELETE;
+        
+    const struct rpc_method *methods = r->get_rpc_methods();
+    int i = 0;
+    while(methods[i].name != NULL)
+    {
+        if(!strcmp(func_name, methods[i].name))
+        {
+            return FUNCTION_CALL;
+        }
+        ++i;
+    }
+    
+    return INVALID;
+}
+
+char* RPCCommand::get_obj_name() const
+{
+    return obj_name;
+}
+
+char* RPCCommand::get_func_name() const
+{
+    return func_name;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCCommand.h	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,36 @@
+#ifndef RPCCOMMAND
+#define RPCCOMMAND
+
+#include <list>
+#include "mbed_rpc.h"
+
+enum RPC_COMMAND_TYPE { INVALID, CREATE, DELETE, FUNCTION_CALL };
+
+struct rpc_arg
+{
+    char *name;
+    char *val;
+};
+
+class RPCCommand
+{
+    public :
+    
+        RPCCommand();
+
+        bool decode(char *buffer);
+
+        char* get_cmd() const;
+        RPC_COMMAND_TYPE get_type() const;
+        char* get_obj_name() const;
+        char* get_func_name() const;
+
+    private :
+        
+        char cmd[RPC_MAX_STRING];
+        char* obj_name;
+        char* func_name;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCObjectManager.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,68 @@
+#include "RPCObjectManager.h"
+#include "mbed.h"
+
+RPCObjectManager& RPCObjectManager::instance()
+{
+    static RPCObjectManager om;
+    return om;
+}
+
+RPCObjectManager::RPCObjectManager():
+objects()
+{
+}
+
+RPCObjectManager::~RPCObjectManager()
+{
+    for(std::list<char*>::iterator itor = objects.begin();
+        itor != objects.end();
+        ++itor)
+        delete *itor;
+}
+
+void RPCObjectManager::store_object(char *obj_name)
+{
+    char *obj = new char[strlen(obj_name)+1];
+    strcpy(obj, obj_name);
+    obj[strlen(obj_name)] = '\0';
+    objects.push_back(obj);
+}
+
+void RPCObjectManager::remove_object(char *obj_name)
+{
+    for(std::list<char*>::iterator itor = objects.begin();
+        itor != objects.end();
+        ++itor)
+        if(!strcmp(obj_name, *itor))
+        {
+            delete *itor;
+            objects.erase(itor);
+            break;
+        }
+}
+
+bool RPCObjectManager::lookup_object(char *obj_name)
+{
+    for(std::list<char*>::iterator itor = objects.begin();
+        itor != objects.end();
+        ++itor)
+        if(!strcmp(obj_name, *itor))
+            return true;
+    return false;
+}
+
+bool RPCObjectManager::is_empty()
+{
+    return objects.empty();
+}
+
+std::list<char*>::iterator RPCObjectManager::begin()
+{
+    return objects.begin();
+}
+
+std::list<char*>::iterator RPCObjectManager::end()
+{
+    return objects.end();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCObjectManager.h	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,29 @@
+#ifndef RPCOBJECTMANAGER
+#define RPCOBJECTMANAGER
+
+#include <list>
+
+class RPCObjectManager
+{
+    public :
+        
+        static RPCObjectManager& instance();
+        
+        void store_object(char *obj_name);
+        void remove_object(char *obj_name);
+        bool lookup_object(char *obj_name);
+        
+        std::list<char*>::iterator begin();
+        std::list<char*>::iterator end();
+
+        bool is_empty();
+        
+    private :
+    
+        RPCObjectManager();
+        ~RPCObjectManager();
+        
+        std::list<char*> objects;
+};
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCType.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,55 @@
+#include "mbed.h"
+#include "mbed_rpc.h"
+#include "RPCType.h"
+
+
+RPCType::RPCType():
+supported_types()
+{
+}
+
+RPCType& RPCType::instance()
+{
+    static RPCType t;
+    return t;
+}
+
+void RPCType::register_types()
+{
+    RPCType &t = instance();
+    
+    RPC::add_rpc_class<RpcDigitalOut>();
+    t.supported_types.push_back("DigitalOut");
+    RPC::add_rpc_class<RpcDigitalIn>();
+    t.supported_types.push_back("DigitalIn");
+    RPC::add_rpc_class<RpcDigitalInOut>();
+    t.supported_types.push_back("DigitalInOut");
+
+    #if DEVICE_PWMOUT
+    RPC::add_rpc_class<RpcPwmOut>();
+    t.supported_types.push_back("PwmOut");
+    #endif
+    #if DEVICE_SPI
+    t.supported_types.push_back("SPI");
+    RPC::add_rpc_class<RpcSPI>();
+    #endif
+    #if DEVICE_SERIAL
+    t.supported_types.push_back("Serial");
+    RPC::add_rpc_class<RpcSerial>();
+    #endif
+    RPC::add_rpc_class<RpcTimer>();
+    t.supported_types.push_back("Timer");
+}
+
+bool RPCType::is_supported_type(char *type)
+{
+    for(std::list<char*>::iterator itor = instance().supported_types.begin();
+        itor != instance().supported_types.end();
+        ++itor)
+        if(!strcmp(*itor,type))
+            return true;
+
+    return false;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCType.h	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,23 @@
+#ifndef RPCTYPE_H
+#define RPCTYPE_H
+
+#include <list>
+
+class RPCType
+{
+    public :
+        
+        static RPCType& instance();
+        
+        void register_types();
+        
+        bool is_supported_type(char *type);
+        
+    private :
+
+        RPCType();
+        std::list<char*> supported_types;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RequestHandler.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,91 @@
+#include "RequestHandler.h"
+#include "mbed_rpc.h"
+#include "RPCObjectManager.h"
+#include "RPCCommand.h"
+
+void GetRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case DELETE:
+            strcat(reply, "You must send a DELETE request to remove an object ");
+            break;
+        case FUNCTION_CALL:
+            RPC::call(cmd.get_cmd(), reply);
+            break;
+        case CREATE:
+            strcat(reply, "You must send a PUT request to call a function");
+            break;
+        default:
+            strcat(reply, "Invalid RPC command");
+            break;
+    }
+}
+
+void PutRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case DELETE:
+            strcat(reply, "You must send a DELETE request to remove an object ");
+            break;
+        case FUNCTION_CALL:
+            strcat(reply, "You must send a GET request to call a function");
+            break;
+        case CREATE:
+            RPC::call(cmd.get_cmd(), reply);
+            if(strlen(reply) > 0)
+            {
+                RPCObjectManager::instance().store_object(reply);
+                strcat(reply, " has been created");
+            }
+            else
+                strcat(reply, "Error while creating object.");
+            break;
+        default:
+            strcat(reply, "Invalid RPC command");
+            break;
+    }
+}
+
+void DeleteRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case CREATE:
+            strcat(reply, "You must send a PUT request to remove an object ");
+            break;
+        case FUNCTION_CALL:
+            strcat(reply, "You must send a GET request to call a function");
+            break;
+        case DELETE:
+            RPC::call(cmd.get_cmd(), reply);
+            RPCObjectManager::instance().remove_object(cmd.get_obj_name());
+            strcat(reply, "Deleted object ");
+            strcat(reply, cmd.get_obj_name());
+            break;
+        default:
+            strcat(reply, "Invalid RPC command");
+            break;
+    }
+}
+
+void ComplexRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case CREATE :
+            putHandler.handle(cmd, reply);
+            break;
+        case DELETE :
+            deleteHandler.handle(cmd, reply);
+            break;
+        case FUNCTION_CALL :
+            getHandler.handle(cmd, reply);
+            break;
+        default :
+            strcat(reply, "Invalid RPC command");
+            break;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RequestHandler.h	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,51 @@
+#ifndef REQUEST_HANDLER
+#define REQUEST_HANDLER
+
+#include "RPCCommand.h"
+
+class RequestHandler
+{
+    public :
+        
+        virtual void handle(const RPCCommand& cmd, char* reply) = 0;
+};
+
+class GetRequestHandler : public RequestHandler
+{
+    public :
+    
+        virtual void handle(const RPCCommand& cmd, char* reply);
+};
+
+class PutRequestHandler : public RequestHandler
+{
+    public :
+        
+        virtual void handle(const RPCCommand& cmd, char* reply);
+
+};
+
+
+class DeleteRequestHandler : public RequestHandler
+{
+    public :
+            
+        virtual void handle(const RPCCommand& cmd, char* reply);
+
+};
+
+class ComplexRequestHandler : public RequestHandler
+{
+    public :
+        
+        virtual void handle(const RPCCommand& cmd, char* reply);
+        
+    private :
+        
+        GetRequestHandler getHandler;
+        PutRequestHandler putHandler;
+        DeleteRequestHandler deleteHandler;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,50 @@
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include "mbed_rpc.h"
+#include "RPCCommand.h"
+#include "HTTPServer.h"
+#include "Formatter.h"
+#include "RequestHandler.h"
+#include "RPCType.h"
+
+#define SERVER_PORT 80
+
+HTTPServer create_simple_server()
+{    
+    HTTPServer srv;
+    srv.add_request_handler("DELETE", new DeleteRequestHandler());
+    srv.add_request_handler("GET", new GetRequestHandler());
+    srv.add_request_handler("PUT", new PutRequestHandler());
+    return srv;
+}
+
+HTTPServer create_interactive_server()
+{
+    HTTPServer srv(new InteractiveHTMLFormatter());
+    srv.add_request_handler("GET", new ComplexRequestHandler());
+    return srv;
+}
+
+int main(void)
+{
+    RPCType::instance().register_types();    
+
+    EthernetInterface eth;
+    eth.init();
+    eth.connect();
+    printf("IP Address is %s\n", eth.getIPAddress());
+    
+    HTTPServer srv = create_simple_server();
+
+    if(!srv.init(SERVER_PORT))
+    {
+        printf("Error while initializing the server\n");
+        eth.disconnect();
+        return -1;
+    }
+
+    srv.run();
+
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rpc.lib	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rpc/#1ecadde1c929
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#58b30ac3f00e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jul 17 10:15:05 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/b3110cd2dd17
\ No newline at end of file