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

Dependents:   RPC_mbed_client RPC_Wifly_HelloWorld RPC_Ethernet_HelloWorld

Revision:
0:a53d1c86196c
Child:
2:af408b5cae75
diff -r 000000000000 -r a53d1c86196c MbedJSONRpc.cpp
--- /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;
+    }
+}