summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-08-13 14:36:39 +0300
committerimarom <imarom@cisco.com>2015-08-13 14:36:39 +0300
commit324dea63203a5f0f53612651a32003150443ac30 (patch)
treef4562b54c6d6f20f3e61094ea146e12e3f08ca42
parent583ef32a82dcd52cce9c1320f5141f91e40a0056 (diff)
draft - some fixes
-rw-r--r--src/gtest/rpc_test.cpp53
-rw-r--r--src/rpc-server/include/trex_rpc_jsonrpc_v2.h32
-rw-r--r--src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp70
-rw-r--r--src/rpc-server/src/trex_rpc_req_resp.cpp28
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 &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;
}
-
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 <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;
};
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<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 */
}
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<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);
}