Remote Procedure Call (RPC) over Websockets (uses MbedJSONValue)

Dependents:   RPC_mbed_client RPC_Wifly_HelloWorld RPC_Ethernet_HelloWorld

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MbedJSONRpc.cpp Source File

MbedJSONRpc.cpp

00001 #include "MbedJSONRpc.h"
00002 
00003 RPC_TYPE MbedJSONRpc::call(char * fn, char * dest, MbedJSONValue& val, MbedJSONValue& resp) {
00004 
00005     char json[150];
00006     RPC_TYPE t;
00007     string str = val.serialize();
00008     int id = rand() % 100;
00009     MbedJSONValue tmp;
00010 
00011 
00012     sprintf(json, (const char *)MSG_CALL, my_id, dest, id, fn, str.c_str());
00013     webs->send(json);
00014     t = waitAnswer(tmp, id, json);
00015     if (t != CALL_OK)
00016         return t;
00017     resp = tmp["res"];
00018     return CALL_OK;
00019 }
00020 
00021 RPC_TYPE MbedJSONRpc::waitAnswer(MbedJSONValue& v, int id, char * json) {
00022     Timer tmr;
00023 
00024     tmr.start();
00025     while (1) {
00026         if (tmr.read() > 5.0) {
00027         #ifdef DEBUG
00028             printf("timeout\r\n");
00029         #endif
00030             return SERVER_NOT_CONNECTED;
00031         }
00032         if (webs->read(json)) {
00033         #ifdef DEBUG
00034             printf("receive: %s\r\n", json);
00035         #endif
00036             parse(v, json);
00037             return decodeMsg(v, id);
00038         }
00039     }
00040 }
00041 
00042 int MbedJSONRpc::methodAlreadyRegistered(char * s) {
00043     for (int i = 0; i < index; i++)
00044         if (!strcmp(name[i], s))
00045             return i;
00046     return -1;
00047 }
00048 
00049 
00050 int MbedJSONRpc::procAlreadyRegistered(char * s) {
00051     for (int i = 0; i < index_proc; i++)
00052         if (!strcmp(name_proc[i], s))
00053             return i;
00054     return -1;
00055 }
00056 
00057 void MbedJSONRpc::checkMethods(char * dest) {
00058     char json[150];
00059     char name[5];
00060     MbedJSONValue tmp;
00061     int id = rand() % 100;
00062 
00063     sprintf(json, (const char *)MSG_INFO_METHODS, my_id, dest, id);
00064     webs->send(json);
00065     waitAnswer(tmp, id, json);
00066     printf("methods available on %s: ", dest);
00067     for (int i = 0; i < tmp.size() - 1; i++) {
00068         sprintf(name, "fn%d", i);
00069         printf("%s%c ", tmp[name].get<string>().c_str(), (i == tmp.size() - 2) ? ' ' : ',');
00070     }
00071     printf("\r\n");
00072 }
00073 
00074 RPC_TYPE MbedJSONRpc::decodeMsg(MbedJSONValue& v, int id) {
00075 
00076     if (v.hasMember("id_msg"))
00077         if (v["id_msg"].get<int>() != -1 && id != v["id_msg"].get<int>()) {
00078         #ifdef DEBUG
00079             printf("bad id: %d\r\n",v["id_msg"].get<int>() );
00080         #endif
00081             return ERR_ID;
00082         }
00083 
00084     if (v.hasMember("msg")) {
00085         std::string s = v["msg"].get<std::string>();
00086         if (!strcmp(s.c_str(), "RESULT")) {
00087             return CALL_OK;
00088         }
00089         if (!strcmp(s.c_str(), "REGISTER_OK")) {
00090             return REGISTER_OK;
00091         }
00092     }
00093 
00094     //there is an error
00095     if (v.hasMember("cause")) {
00096         std::string s = v["cause"].get<std::string>();
00097         if (!strcmp(s.c_str(), "JSON_PARSE_ERROR"))
00098             return JSON_PARSE_ERROR;
00099         if (!strcmp(s.c_str(), "JSON_RPC_ERROR"))
00100             return RPC_PARSE_ERROR;
00101         else if (!strcmp(s.c_str(), "METHOD_NOT_FOUND"))
00102             return PROC_NOT_FOUND;
00103         else if (!strcmp(s.c_str(), "CLIENT_NOT_CONNECTED"))
00104             return CLIENT_NOT_CONNECTED;
00105     }
00106     return RPC_PARSE_ERROR;
00107 
00108 }
00109 
00110 
00111 RPC_TYPE MbedJSONRpc::registerMethod(const char * public_name, void (*fn)(MbedJSONValue& val, MbedJSONValue& res) ) {
00112     char json[100];
00113     int id = rand() % 100;
00114     MbedJSONValue tmp;
00115     RPC_TYPE t;
00116 
00117     sprintf(json, (const char *)MSG_REGISTER, my_id, id, public_name);
00118     webs->send(json);
00119     t = waitAnswer(tmp, id, json);
00120     if (t != REGISTER_OK)
00121         return t;
00122     if( index_proc == NB_METH )
00123         index_proc = NB_METH - 1;
00124     proc[index_proc] = fn;
00125     name_proc[index_proc++] = public_name;
00126     return REGISTER_OK;
00127 }
00128 
00129 
00130 void MbedJSONRpc::work() {
00131     char json_recv[150];
00132     DigitalOut led4(LED4);
00133     MbedJSONValue v, r;
00134     int i = -1;
00135     while (1) {
00136         wait(0.2);
00137         if (webs->read(json_recv)) {
00138             parse(v, json_recv);
00139             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")) {
00140             
00141                 string s = v["method"].get<std::string>();
00142                 
00143                 if ((i = methodAlreadyRegistered((char *)s.c_str())) != -1) {
00144                 
00145                     obj[i]->execute(v["params"], r);
00146                     sprintf(json_recv, (const char *)MSG_RESULT, my_id,
00147                             v["from"].get<std::string>().c_str(), v["id_msg"].get<int>(), r.serialize().c_str());
00148                     webs->send(json_recv);
00149                     
00150                 } else if ((i = procAlreadyRegistered((char *)s.c_str())) != -1) {
00151                 
00152                     proc[i](v["params"], r);
00153                     sprintf(json_recv, (const char *)MSG_RESULT, my_id,
00154                             v["from"].get<std::string>().c_str(), v["id_msg"].get<int>(), r.serialize().c_str());
00155                     webs->send(json_recv);
00156                     
00157                 }
00158             }
00159 
00160         }
00161         //show that we are alive
00162         led4 = !led4;
00163     }
00164 }