Modified to run on Renesas GR Peach board
Fork of HTTP-Server by
Revision 0:9e4bcb10b3e3, committed 2013-07-17
- Comitter:
- feb11
- Date:
- Wed Jul 17 10:15:05 2013 +0000
- Child:
- 1:2efb8b4cc4bc
- Commit message:
- Initial import
Changed in this revision
--- /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