From 324dea63203a5f0f53612651a32003150443ac30 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 13 Aug 2015 14:36:39 +0300 Subject: draft - some fixes --- src/gtest/rpc_test.cpp | 53 +++++++++++---------- src/rpc-server/include/trex_rpc_jsonrpc_v2.h | 32 +++++++++++-- src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp | 70 +++++++++++++++++++--------- src/rpc-server/src/trex_rpc_req_resp.cpp | 28 +++++++++-- 4 files changed, 127 insertions(+), 56 deletions(-) diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index f1510ef2..f80ebd5d 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -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 ¶ms = 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; } - diff --git a/src/rpc-server/include/trex_rpc_jsonrpc_v2.h b/src/rpc-server/include/trex_rpc_jsonrpc_v2.h index 5a88f756..ac04fb99 100644 --- a/src/rpc-server/include/trex_rpc_jsonrpc_v2.h +++ b/src/rpc-server/include/trex_rpc_jsonrpc_v2.h @@ -23,6 +23,8 @@ limitations under the License. #define __TREX_RPC_JSONRPC_V2_H__ #include +#include +#include /** * 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 &commands); private: + + /** + * handle a single request + * + */ + void parse_single_request(Json::Value &request, std::vector &commands); + std::string m_msg; }; diff --git a/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp b/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp index 2083ab2a..f28bcbd8 100644 --- a/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp +++ b/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp @@ -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 &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 &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 */ } diff --git a/src/rpc-server/src/trex_rpc_req_resp.cpp b/src/rpc-server/src/trex_rpc_req_resp.cpp index b423c8e7..feb57b44 100644 --- a/src/rpc-server/src/trex_rpc_req_resp.cpp +++ b/src/rpc-server/src/trex_rpc_req_resp.cpp @@ -85,14 +85,34 @@ void TrexRpcServerReqRes::_stop_rpc_thread() { } void TrexRpcServerReqRes::handle_request(const std::string &request) { - std::string response; + std::vector 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); } -- cgit 1.2.3-korg