Remote Procedure Call (RPC) over Websockets (uses MbedJSONValue)
Dependents: RPC_mbed_client RPC_Wifly_HelloWorld RPC_Ethernet_HelloWorld
Diff: MbedJSONRpc.cpp
- Revision:
- 0:a53d1c86196c
- Child:
- 2:af408b5cae75
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MbedJSONRpc.cpp Thu Sep 22 10:14:52 2011 +0000 @@ -0,0 +1,164 @@ +#include "MbedJSONRpc.h" + +RPC_TYPE MbedJSONRpc::call(char * fn, char * dest, MbedRpcValue& val, MbedRpcValue& resp) { + + char json[150]; + RPC_TYPE t; + string str = val.serialize(); + int id = rand() % 100; + MbedRpcValue tmp; + + + sprintf(json, (const char *)MSG_CALL, my_id, dest, id, fn, str.c_str()); + webs->Send(json); + t = waitAnswer(tmp, id, json); + if (t != CALL_OK) + return t; + resp = tmp["res"]; + return CALL_OK; +} + +RPC_TYPE MbedJSONRpc::waitAnswer(MbedRpcValue& v, int id, char * json) { + Timer tmr; + + tmr.start(); + while (1) { + if (tmr.read() > 5.0) { + #ifdef DEBUG + printf("timeout\r\n"); + #endif + return SERVER_NOT_CONNECTED; + } + if (webs->read(json)) { + #ifdef DEBUG + printf("receive: %s\r\n", json); + #endif + parse(v, json); + return decodeMsg(v, id); + } + } +} + +int MbedJSONRpc::methodAlreadyRegistered(char * s) { + for (int i = 0; i < index; i++) + if (!strcmp(name[i], s)) + return i; + return -1; +} + + +int MbedJSONRpc::procAlreadyRegistered(char * s) { + for (int i = 0; i < index_proc; i++) + if (!strcmp(name_proc[i], s)) + return i; + return -1; +} + +void MbedJSONRpc::checkMethods(char * dest) { + char json[150]; + char name[5]; + MbedRpcValue tmp; + int id = rand() % 100; + + sprintf(json, (const char *)MSG_INFO_METHODS, my_id, dest, id); + webs->Send(json); + waitAnswer(tmp, id, json); + printf("methods available on %s: ", dest); + for (int i = 0; i < tmp.size() - 1; i++) { + sprintf(name, "fn%d", i); + printf("%s%c ", tmp[name].get<string>().c_str(), (i == tmp.size() - 2) ? ' ' : ','); + } + printf("\r\n"); +} + +RPC_TYPE MbedJSONRpc::decodeMsg(MbedRpcValue& v, int id) { + + if (v.hasMember("id_msg")) + if (v["id_msg"].get<int>() != -1 && id != v["id_msg"].get<int>()) { + #ifdef DEBUG + printf("bad id: %d\r\n",v["id_msg"].get<int>() ); + #endif + return ERR_ID; + } + + if (v.hasMember("msg")) { + std::string s = v["msg"].get<std::string>(); + if (!strcmp(s.c_str(), "RESULT")) { + return CALL_OK; + } + if (!strcmp(s.c_str(), "REGISTER_OK")) { + return REGISTER_OK; + } + } + + //there is an error + if (v.hasMember("cause")) { + std::string s = v["cause"].get<std::string>(); + if (!strcmp(s.c_str(), "JSON_PARSE_ERROR")) + return JSON_PARSE_ERROR; + if (!strcmp(s.c_str(), "JSON_RPC_ERROR")) + return RPC_PARSE_ERROR; + else if (!strcmp(s.c_str(), "METHOD_NOT_FOUND")) + return PROC_NOT_FOUND; + else if (!strcmp(s.c_str(), "CLIENT_NOT_CONNECTED")) + return CLIENT_NOT_CONNECTED; + } + return RPC_PARSE_ERROR; + +} + + +RPC_TYPE MbedJSONRpc::registerMethod(const char * public_name, void (*fn)(MbedRpcValue& val, MbedRpcValue& res) ) { + char json[100]; + int id = rand() % 100; + MbedRpcValue tmp; + RPC_TYPE t; + + sprintf(json, (const char *)MSG_REGISTER, my_id, id, public_name); + webs->Send(json); + t = waitAnswer(tmp, id, json); + if (t != REGISTER_OK) + return t; + if( index_proc == NB_METH ) + index_proc = NB_METH - 1; + proc[index_proc] = fn; + name_proc[index_proc++] = public_name; + return REGISTER_OK; +} + + +void MbedJSONRpc::work() { + char json_recv[150]; + DigitalOut led4(LED4); + MbedRpcValue v, r; + int i = -1; + while (1) { + wait(0.2); + if (webs->read(json_recv)) { + parse(v, json_recv); + if (v.hasMember("method") && v.hasMember("from") && v.hasMember("id_msg") && v.hasMember("params") && v.hasMember("msg") && !strcmp(v["msg"].get<std::string>().c_str(), "CALL")) { + + string s = v["method"].get<std::string>(); + + if ((i = methodAlreadyRegistered((char *)s.c_str())) != -1) { + + obj[i]->execute(v["params"], r); + sprintf(json_recv, (const char *)MSG_RESULT, my_id, + v["from"].get<std::string>().c_str(), v["id_msg"].get<int>(), r.serialize().c_str()); + webs->Send(json_recv); + + } else if ((i = procAlreadyRegistered((char *)s.c_str())) != -1) { + + proc[i](v["params"], r); + sprintf(json_recv, (const char *)MSG_RESULT, my_id, + v["from"].get<std::string>().c_str(), v["id_msg"].get<int>(), r.serialize().c_str()); + webs->Send(json_recv); + + } + } + + } + //show that we are alive + led4 = !led4; + } +}