draft - some fixes
authorimarom <[email protected]>
Thu, 13 Aug 2015 11:36:39 +0000 (14:36 +0300)
committerimarom <[email protected]>
Thu, 13 Aug 2015 11:36:39 +0000 (14:36 +0300)
src/gtest/rpc_test.cpp
src/rpc-server/include/trex_rpc_jsonrpc_v2.h
src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp
src/rpc-server/src/trex_rpc_req_resp.cpp

index f1510ef..f80ebd5 100644 (file)
@@ -97,38 +97,37 @@ TEST_F(RpcTest, basic_rpc_test) {
     EXPECT_TRUE(response["id"] == 482);
     EXPECT_TRUE(response["error"]["code"] == -32600);
 
-    #if 0
-    
-    
-
-    int id = 1;
-    request["jsonrpc"] = "2.0";
-    //request["method"]  = "test_func";
+}
 
-    Json::Value &params = request["params"];
-    params["num"] = 12;
-    params["msg"] = "hello, method test_func";
+TEST_F(RpcTest, batch_rpc_test) {
+    Json::Value request;
+    Json::Value response;
+    Json::Reader reader;
 
-    for (int request_nbr = 0; request_nbr != 1; request_nbr++) {
-        //request["id"] = "itay_id";
+    string req_str;
+    string resp_str;
 
-        stringstream ss;
-        ss << request;
+    req_str = "[ \
+            {\"jsonrpc\": \"2.0\", \"method\": \"sum\", \"params\": [1,2,4], \"id\": \"1\"}, \
+            {\"jsonrpc\": \"2.0\", \"method\": \"notify_hello\", \"params\": [7]}, \
+            {\"jsonrpc\": \"2.0\", \"method\": \"subtract\", \"params\": [42,23], \"id\": \"2\"}, \
+            {\"foo\": \"boo\"}, \
+            {\"jsonrpc\": \"2.0\", \"method\": \"foo.get\", \"params\": {\"name\": \"myself\"}, \"id\": \"5\"}, \
+            {\"jsonrpc\": \"2.0\", \"method\": \"get_data\", \"id\": \"9\"} \
+               ]";
 
-        cout << "Sending : '" << ss.str() << "'\n";
-        
-        zmq_send (requester, ss.str().c_str(), ss.str().size(), 0);
+    resp_str = send_msg(req_str);
+    cout << resp_str;
+    EXPECT_TRUE(reader.parse(resp_str, response, false));
+    EXPECT_TRUE(response.isArray());
 
-        int len = zmq_recv (requester, buffer, 250, 0);
-        string resp(buffer, buffer + len);
-        cout << "Got: " << resp << "\n";
-    }
-    zmq_close (requester);
-    zmq_ctx_destroy (context);
+    // message 1
+    EXPECT_TRUE(response[0]["jsonrpc"] == "2.0");
+    EXPECT_TRUE(response[0]["id"] == "1");
 
-    sleep(1);
+    // message 2
+    EXPECT_TRUE(response[1]["jsonrpc"] == "2.0");
+    EXPECT_TRUE(response[1]["id"] == "2");
 
-    rpc.stop();
-    #endif
+    return;
 }
-
index 5a88f75..ac04fb9 100644 (file)
@@ -23,6 +23,8 @@ limitations under the License.
 #define __TREX_RPC_JSONRPC_V2_H__
 
 #include <string>
+#include <vector>
+#include <json/json.h>
 
 /**
  * JSON RPC V2 command
@@ -31,7 +33,24 @@ limitations under the License.
  */
 class TrexJsonRpcV2Command {
 public:
-    virtual void execute(std::string &response) = 0;
+
+    TrexJsonRpcV2Command(const Json::Value &msg_id);
+
+    /**
+     * main function to execute the command
+     * 
+     */
+    void execute(Json::Value &response);
+
+protected:
+
+    /**
+     * instance private implementation
+     * 
+     */
+    virtual void _execute(Json::Value &response) = 0;
+
+    Json::Value   m_msg_id;
 };
 
 /**
@@ -53,13 +72,20 @@ public:
     TrexJsonRpcV2Parser(const std::string &msg);
 
     /**
-     * parses the string to a executable command
+     * parses the string to a executable commands vector
      * 
      * @author imarom (12-Aug-15)
      */
-    TrexJsonRpcV2Command * parse();
+    void parse(std::vector<TrexJsonRpcV2Command *> &commands);
 
 private:
+
+    /**
+     * handle a single request
+     * 
+     */
+    void parse_single_request(Json::Value &request, std::vector<TrexJsonRpcV2Command *> &commands);
+
     std::string m_msg;
 };
 
index 2083ab2..f28bcbd 100644 (file)
@@ -39,11 +39,25 @@ enum {
 /* dummy command */
 class DumymCommand : public TrexJsonRpcV2Command {
 public:
-    virtual void execute(std::string &response) {
-        std::cout << "dummy here\n";
+    virtual void _execute(Json::Value &response) {
     }
 };
 
+/*************** JSON RPC command base type ************/
+
+TrexJsonRpcV2Command::TrexJsonRpcV2Command(const Json::Value &msg_id) : m_msg_id(msg_id) {
+
+}
+
+void TrexJsonRpcV2Command::execute(Json::Value &response) {
+    /* common fields */
+    response["jsonrpc"] = "2.0";
+    response["id"]      = m_msg_id;
+
+    /* call the underlying implementation to add the reset of the sections */
+    _execute(response);
+}
+
 /**
  * describes the parser error 
  * 
@@ -51,26 +65,18 @@ public:
 class JsonRpcError : public TrexJsonRpcV2Command {
 public:
 
-    JsonRpcError(const Json::Value &msg_id, int code, const std::string &msg) : m_msg_id(msg_id), m_code(code), m_msg(msg) {
+    JsonRpcError(const Json::Value &msg_id, int code, const std::string &msg) : TrexJsonRpcV2Command(msg_id), m_code(code), m_msg(msg) {
 
     }
 
-    virtual void execute(std::string &response) {
-        Json::Value response_json;
-        Json::FastWriter writer;
-
-        response_json["jsonrpc"] = "2.0";
-        response_json["id"]      = m_msg_id;
-
-        response_json["error"]["code"]    = m_code;
-        response_json["error"]["message"] = m_msg;
+    virtual void _execute(Json::Value &response) {
 
-        /* encode to string */
-        response = writer.write(response_json);
+        response["error"]["code"]    = m_code;
+        response["error"]["message"] = m_msg;
+        
     }
 
 private:
-    Json::Value   m_msg_id;
     int           m_code;
     std::string   m_msg;
 };
@@ -80,31 +86,51 @@ TrexJsonRpcV2Parser::TrexJsonRpcV2Parser(const std::string &msg) : m_msg(msg) {
 
 }
 
-TrexJsonRpcV2Command * TrexJsonRpcV2Parser::parse() {
+void TrexJsonRpcV2Parser::parse(std::vector<TrexJsonRpcV2Command *> &commands) {
+
     Json::Reader reader;
     Json::Value  request;
 
     /* basic JSON parsing */
     bool rc = reader.parse(m_msg, request, false);
     if (!rc) {
-        return new JsonRpcError(Json::Value::null, JSONRPC_V2_ERR_PARSE, "Bad JSON Format");
+        commands.push_back(new JsonRpcError(Json::Value::null, JSONRPC_V2_ERR_PARSE, "Bad JSON Format"));
+        return;
+    }
+
+    /* request can be an array of requests */
+    if (request.isArray()) {
+        /* handle each command */
+        for (auto single_request : request) {
+            parse_single_request(single_request, commands);
+        }
+    } else {
+        /* handle single command */
+        parse_single_request(request, commands);
     }
 
+  
+}
+
+
+void TrexJsonRpcV2Parser::parse_single_request(Json::Value &request, 
+                                               std::vector<TrexJsonRpcV2Command *> &commands) {
+
     Json::Value msg_id = request["id"];
 
     /* check version */
     if (request["jsonrpc"] != "2.0") {
-        return new JsonRpcError(msg_id, JSONRPC_V2_ERR_INVALID_REQ, "Invalid JSONRPC Version");
+        commands.push_back(new JsonRpcError(msg_id, JSONRPC_V2_ERR_INVALID_REQ, "Invalid JSONRPC Version"));
+        return;
     }
 
     /* check method name */
     std::string method_name = request["method"].asString();
     if (method_name == "") {
-        return new JsonRpcError(msg_id, JSONRPC_V2_ERR_INVALID_REQ, "Missing Method Name");
+        commands.push_back(new JsonRpcError(msg_id, JSONRPC_V2_ERR_INVALID_REQ, "Missing Method Name"));
+        return;
     }
 
-    TrexJsonRpcV2Command *command = new DumymCommand();
-
-    return (command);
+    /* TODO - add commands */
 }
 
index b423c8e..feb57b4 100644 (file)
@@ -85,14 +85,34 @@ void TrexRpcServerReqRes::_stop_rpc_thread() {
 }
 
 void TrexRpcServerReqRes::handle_request(const std::string &request) {
-    std::string   response;
+    std::vector<TrexJsonRpcV2Command *> commands;
+    Json::FastWriter writer;
+    Json::Value response;
 
     TrexJsonRpcV2Parser rpc_request(request);
 
-    TrexJsonRpcV2Command *rpc_command = rpc_request.parse();
+    rpc_request.parse(commands);
 
-    rpc_command->execute(response);
+    int index = 0;
 
-    zmq_send(m_socket, response.c_str(), response.size(), 0);
+    for (auto command : commands) {
+        Json::Value single_response;
+
+        command->execute(single_response);
+
+        response[index++] = single_response;
+
+    }
+
+    /* write the JSON to string and sever on ZMQ */
+    std::string reponse_str;
+
+    if (response.size() == 1) {
+        reponse_str = writer.write(response[0]);
+    } else {
+        reponse_str = writer.write(response);
+    }
+    
+    zmq_send(m_socket, reponse_str.c_str(), reponse_str.size(), 0);
     
 }