Remote Procedure Call (RPC) over Websockets (uses MbedJSONValue)
Dependents: RPC_mbed_client RPC_Wifly_HelloWorld RPC_Ethernet_HelloWorld
MbedJSONRpc.cpp
- Committer:
- samux
- Date:
- 2012-08-23
- Revision:
- 7:067cb01b491e
- Parent:
- 2:af408b5cae75
File content as of revision 7:067cb01b491e:
#include "MbedJSONRpc.h" RPC_TYPE MbedJSONRpc::call(char * fn, char * dest, MbedJSONValue& val, MbedJSONValue& resp) { char json[150]; RPC_TYPE t; string str = val.serialize(); int id = rand() % 100; MbedJSONValue 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(MbedJSONValue& 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]; MbedJSONValue 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(MbedJSONValue& 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)(MbedJSONValue& val, MbedJSONValue& res) ) { char json[100]; int id = rand() % 100; MbedJSONValue 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); MbedJSONValue 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; } }