From ffb38cc6153c7938f02d9eb524bf3e58f0d4336b Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 17 Aug 2015 10:59:36 +0300 Subject: some MV actions --- src/rpc-server/include/trex_rpc_jsonrpc_v2.h | 99 ----------- .../include/trex_rpc_jsonrpc_v2_parser.h | 99 +++++++++++ src/rpc-server/include/trex_rpc_req_resp.h | 51 ------ src/rpc-server/include/trex_rpc_req_resp_server.h | 51 ++++++ src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp | 184 --------------------- src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp | 184 +++++++++++++++++++++ src/rpc-server/src/trex_rpc_req_resp.cpp | 141 ---------------- src/rpc-server/src/trex_rpc_req_resp_server.cpp | 141 ++++++++++++++++ src/rpc-server/src/trex_rpc_server.cpp | 2 +- 9 files changed, 476 insertions(+), 476 deletions(-) delete mode 100644 src/rpc-server/include/trex_rpc_jsonrpc_v2.h create mode 100644 src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h delete mode 100644 src/rpc-server/include/trex_rpc_req_resp.h create mode 100644 src/rpc-server/include/trex_rpc_req_resp_server.h delete mode 100644 src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp create mode 100644 src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp delete mode 100644 src/rpc-server/src/trex_rpc_req_resp.cpp create mode 100644 src/rpc-server/src/trex_rpc_req_resp_server.cpp diff --git a/src/rpc-server/include/trex_rpc_jsonrpc_v2.h b/src/rpc-server/include/trex_rpc_jsonrpc_v2.h deleted file mode 100644 index a9b6faa3..00000000 --- a/src/rpc-server/include/trex_rpc_jsonrpc_v2.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - Itay Marom - Cisco Systems, Inc. -*/ - -/* -Copyright (c) 2015-2015 Cisco Systems, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#ifndef __TREX_RPC_JSONRPC_V2_H__ -#define __TREX_RPC_JSONRPC_V2_H__ - -#include -#include -#include - -class TrexRpcCommand; - -/** - * JSON RPC V2 parsed object - * - * @author imarom (12-Aug-15) - */ -class TrexJsonRpcV2ParsedObject { -public: - - TrexJsonRpcV2ParsedObject(const Json::Value &msg_id, bool force); - virtual ~TrexJsonRpcV2ParsedObject() {} - - /** - * main function to execute the command - * - */ - void execute(Json::Value &response); - -protected: - - /** - * instance private implementation - * should provide implementation with response - * and without response value - */ - virtual void _execute(Json::Value &response) = 0; - virtual void _execute() = 0; - - Json::Value m_msg_id; - bool m_respond; -}; - -/** - * JSON RPC V2 parser - * - * @author imarom (12-Aug-15) - */ -class TrexJsonRpcV2Parser { - -public: - - /** - * creates a JSON-RPC object from a string - * - * @author imarom (12-Aug-15) - * - * @param msg - */ - TrexJsonRpcV2Parser(const std::string &msg); - - /** - * parses the string to a executable commands vector - * - * @author imarom (12-Aug-15) - */ - void parse(std::vector &commands); - -private: - - /** - * handle a single request - * - */ - void parse_single_request(Json::Value &request, std::vector &commands); - - std::string m_msg; -}; - -#endif /* __TREX_RPC_JSONRPC_V2_H__ */ - diff --git a/src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h b/src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h new file mode 100644 index 00000000..1f26b92f --- /dev/null +++ b/src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h @@ -0,0 +1,99 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef __TREX_RPC_JSONRPC_V2_PARSER_H__ +#define __TREX_RPC_JSONRPC_V2_PARSER_H__ + +#include +#include +#include + +class TrexRpcCommand; + +/** + * JSON RPC V2 parsed object + * + * @author imarom (12-Aug-15) + */ +class TrexJsonRpcV2ParsedObject { +public: + + TrexJsonRpcV2ParsedObject(const Json::Value &msg_id, bool force); + virtual ~TrexJsonRpcV2ParsedObject() {} + + /** + * main function to execute the command + * + */ + void execute(Json::Value &response); + +protected: + + /** + * instance private implementation + * should provide implementation with response + * and without response value + */ + virtual void _execute(Json::Value &response) = 0; + virtual void _execute() = 0; + + Json::Value m_msg_id; + bool m_respond; +}; + +/** + * JSON RPC V2 parser + * + * @author imarom (12-Aug-15) + */ +class TrexJsonRpcV2Parser { + +public: + + /** + * creates a JSON-RPC object from a string + * + * @author imarom (12-Aug-15) + * + * @param msg + */ + TrexJsonRpcV2Parser(const std::string &msg); + + /** + * parses the string to a executable commands vector + * + * @author imarom (12-Aug-15) + */ + void parse(std::vector &commands); + +private: + + /** + * handle a single request + * + */ + void parse_single_request(Json::Value &request, std::vector &commands); + + std::string m_msg; +}; + +#endif /* __TREX_RPC_JSONRPC_V2_PARSER_H__ */ + diff --git a/src/rpc-server/include/trex_rpc_req_resp.h b/src/rpc-server/include/trex_rpc_req_resp.h deleted file mode 100644 index f12d0540..00000000 --- a/src/rpc-server/include/trex_rpc_req_resp.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Itay Marom - Cisco Systems, Inc. -*/ - -/* -Copyright (c) 2015-2015 Cisco Systems, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#ifndef __TREX_RPC_REQ_RESP_API_H__ -#define __TREX_RPC_REQ_RESP_API_H__ - -#include - -/** - * request-response RPC server - * - * @author imarom (11-Aug-15) - */ -class TrexRpcServerReqRes : public TrexRpcServerInterface { -public: - - TrexRpcServerReqRes(const TrexRpcServerConfig &cfg); - -protected: - void _rpc_thread_cb(); - void _stop_rpc_thread(); - -private: - void handle_request(const std::string &request); - - static const int RPC_MAX_MSG_SIZE = 2048; - void *m_context; - void *m_socket; - uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE]; -}; - - -#endif /* __TREX_RPC_REQ_RESP_API_H__ */ diff --git a/src/rpc-server/include/trex_rpc_req_resp_server.h b/src/rpc-server/include/trex_rpc_req_resp_server.h new file mode 100644 index 00000000..f12d0540 --- /dev/null +++ b/src/rpc-server/include/trex_rpc_req_resp_server.h @@ -0,0 +1,51 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef __TREX_RPC_REQ_RESP_API_H__ +#define __TREX_RPC_REQ_RESP_API_H__ + +#include + +/** + * request-response RPC server + * + * @author imarom (11-Aug-15) + */ +class TrexRpcServerReqRes : public TrexRpcServerInterface { +public: + + TrexRpcServerReqRes(const TrexRpcServerConfig &cfg); + +protected: + void _rpc_thread_cb(); + void _stop_rpc_thread(); + +private: + void handle_request(const std::string &request); + + static const int RPC_MAX_MSG_SIZE = 2048; + void *m_context; + void *m_socket; + uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE]; +}; + + +#endif /* __TREX_RPC_REQ_RESP_API_H__ */ diff --git a/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp b/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp deleted file mode 100644 index 53811d70..00000000 --- a/src/rpc-server/src/trex_rpc_jsonrpc_v2.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - Itay Marom - Cisco Systems, Inc. -*/ - -/* -Copyright (c) 2015-2015 Cisco Systems, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -#include -#include -#include -#include - -#include - -#include - -/** - * error as described in the RFC - */ -enum { - JSONRPC_V2_ERR_PARSE = -32700, - JSONRPC_V2_ERR_INVALID_REQ = -32600, - JSONRPC_V2_ERR_METHOD_NOT_FOUND = -32601, - JSONRPC_V2_ERR_INVALID_PARAMS = -32602, - JSONRPC_V2_ERR_INTERNAL_ERROR = -32603 -}; - - -/*************** JSON RPC parsed object base type ************/ - -TrexJsonRpcV2ParsedObject::TrexJsonRpcV2ParsedObject(const Json::Value &msg_id, bool force = false) : m_msg_id(msg_id) { - /* if we have msg_id or a force was issued - write resposne */ - m_respond = (msg_id != Json::Value::null) || force; -} - -void TrexJsonRpcV2ParsedObject::execute(Json::Value &response) { - - /* common fields */ - if (m_respond) { - response["jsonrpc"] = "2.0"; - response["id"] = m_msg_id; - _execute(response); - } else { - _execute(); - } -} - -/****************** valid method return value **************/ -class JsonRpcMethod : public TrexJsonRpcV2ParsedObject { -public: - JsonRpcMethod(const Json::Value &msg_id, TrexRpcCommand *cmd, const Json::Value ¶ms) : TrexJsonRpcV2ParsedObject(msg_id), m_cmd(cmd), m_params(params) { - - } - - virtual void _execute(Json::Value &response) { - Json::Value result; - - TrexRpcCommand::rpc_cmd_rc_e rc = m_cmd->run(m_params, result); - - switch (rc) { - case TrexRpcCommand::RPC_CMD_OK: - response["result"] = result["result"]; - break; - - case TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR: - case TrexRpcCommand::RPC_CMD_PARAM_PARSE_ERR: - response["error"]["code"] = JSONRPC_V2_ERR_INVALID_PARAMS; - response["error"]["message"] = "Bad paramters for method"; - break; - } - - } - - virtual void _execute() { - Json::Value result; - m_cmd->run(m_params, result); - } - -private: - TrexRpcCommand *m_cmd; - Json::Value m_params; -}; - -/******************* RPC error **************/ - -/** - * describes the parser error - * - */ -class JsonRpcError : public TrexJsonRpcV2ParsedObject { -public: - - JsonRpcError(const Json::Value &msg_id, int code, const std::string &msg, bool force = false) : TrexJsonRpcV2ParsedObject(msg_id, force), m_code(code), m_msg(msg) { - - } - - virtual void _execute(Json::Value &response) { - response["error"]["code"] = m_code; - response["error"]["message"] = m_msg; - } - - virtual void _execute() { - /* nothing to do with no response */ - } - -private: - int m_code; - std::string m_msg; -}; - - -TrexJsonRpcV2Parser::TrexJsonRpcV2Parser(const std::string &msg) : m_msg(msg) { - -} - -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) { - commands.push_back(new JsonRpcError(Json::Value::null, JSONRPC_V2_ERR_PARSE, "Bad JSON Format", true)); - 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") { - 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 == "") { - commands.push_back(new JsonRpcError(msg_id, JSONRPC_V2_ERR_INVALID_REQ, "Missing Method Name")); - return; - } - - /* lookup the method in the DB */ - TrexRpcCommand * rpc_cmd = TrexRpcCommandsTable::get_instance().lookup(method_name); - if (!rpc_cmd) { - commands.push_back(new JsonRpcError(msg_id, JSONRPC_V2_ERR_METHOD_NOT_FOUND, "Method not registered")); - return; - } - - /* create a method object */ - commands.push_back(new JsonRpcMethod(msg_id, rpc_cmd, request["params"])); -} - diff --git a/src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp b/src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp new file mode 100644 index 00000000..6fb210bd --- /dev/null +++ b/src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp @@ -0,0 +1,184 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include +#include +#include +#include + +#include + +#include + +/** + * error as described in the RFC + */ +enum { + JSONRPC_V2_ERR_PARSE = -32700, + JSONRPC_V2_ERR_INVALID_REQ = -32600, + JSONRPC_V2_ERR_METHOD_NOT_FOUND = -32601, + JSONRPC_V2_ERR_INVALID_PARAMS = -32602, + JSONRPC_V2_ERR_INTERNAL_ERROR = -32603 +}; + + +/*************** JSON RPC parsed object base type ************/ + +TrexJsonRpcV2ParsedObject::TrexJsonRpcV2ParsedObject(const Json::Value &msg_id, bool force = false) : m_msg_id(msg_id) { + /* if we have msg_id or a force was issued - write resposne */ + m_respond = (msg_id != Json::Value::null) || force; +} + +void TrexJsonRpcV2ParsedObject::execute(Json::Value &response) { + + /* common fields */ + if (m_respond) { + response["jsonrpc"] = "2.0"; + response["id"] = m_msg_id; + _execute(response); + } else { + _execute(); + } +} + +/****************** valid method return value **************/ +class JsonRpcMethod : public TrexJsonRpcV2ParsedObject { +public: + JsonRpcMethod(const Json::Value &msg_id, TrexRpcCommand *cmd, const Json::Value ¶ms) : TrexJsonRpcV2ParsedObject(msg_id), m_cmd(cmd), m_params(params) { + + } + + virtual void _execute(Json::Value &response) { + Json::Value result; + + TrexRpcCommand::rpc_cmd_rc_e rc = m_cmd->run(m_params, result); + + switch (rc) { + case TrexRpcCommand::RPC_CMD_OK: + response["result"] = result["result"]; + break; + + case TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR: + case TrexRpcCommand::RPC_CMD_PARAM_PARSE_ERR: + response["error"]["code"] = JSONRPC_V2_ERR_INVALID_PARAMS; + response["error"]["message"] = "Bad paramters for method"; + break; + } + + } + + virtual void _execute() { + Json::Value result; + m_cmd->run(m_params, result); + } + +private: + TrexRpcCommand *m_cmd; + Json::Value m_params; +}; + +/******************* RPC error **************/ + +/** + * describes the parser error + * + */ +class JsonRpcError : public TrexJsonRpcV2ParsedObject { +public: + + JsonRpcError(const Json::Value &msg_id, int code, const std::string &msg, bool force = false) : TrexJsonRpcV2ParsedObject(msg_id, force), m_code(code), m_msg(msg) { + + } + + virtual void _execute(Json::Value &response) { + response["error"]["code"] = m_code; + response["error"]["message"] = m_msg; + } + + virtual void _execute() { + /* nothing to do with no response */ + } + +private: + int m_code; + std::string m_msg; +}; + + +TrexJsonRpcV2Parser::TrexJsonRpcV2Parser(const std::string &msg) : m_msg(msg) { + +} + +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) { + commands.push_back(new JsonRpcError(Json::Value::null, JSONRPC_V2_ERR_PARSE, "Bad JSON Format", true)); + 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") { + 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 == "") { + commands.push_back(new JsonRpcError(msg_id, JSONRPC_V2_ERR_INVALID_REQ, "Missing Method Name")); + return; + } + + /* lookup the method in the DB */ + TrexRpcCommand * rpc_cmd = TrexRpcCommandsTable::get_instance().lookup(method_name); + if (!rpc_cmd) { + commands.push_back(new JsonRpcError(msg_id, JSONRPC_V2_ERR_METHOD_NOT_FOUND, "Method not registered")); + return; + } + + /* create a method object */ + commands.push_back(new JsonRpcMethod(msg_id, rpc_cmd, request["params"])); +} + diff --git a/src/rpc-server/src/trex_rpc_req_resp.cpp b/src/rpc-server/src/trex_rpc_req_resp.cpp deleted file mode 100644 index f5fad461..00000000 --- a/src/rpc-server/src/trex_rpc_req_resp.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - Itay Marom - Cisco Systems, Inc. -*/ - -/* -Copyright (c) 2015-2015 Cisco Systems, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -/** - * ZMQ based request-response server - * - */ -TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg) : TrexRpcServerInterface(cfg) { - /* ZMQ is not thread safe - this should be outside */ - m_context = zmq_ctx_new(); -} - -/** - * main entry point for the server - * this function will be created on a different thread - * - * @author imarom (17-Aug-15) - */ -void TrexRpcServerReqRes::_rpc_thread_cb() { - std::stringstream ss; - - /* create a socket based on the configuration */ - - m_socket = zmq_socket (m_context, ZMQ_REP); - - switch (m_cfg.get_protocol()) { - case TrexRpcServerConfig::RPC_PROT_TCP: - ss << "tcp://*:"; - break; - default: - throw TrexRpcException("unknown protocol for RPC"); - } - - ss << m_cfg.get_port(); - - /* bind the scoket */ - int rc = zmq_bind (m_socket, ss.str().c_str()); - if (rc != 0) { - throw TrexRpcException("Unable to start ZMQ server at: " + ss.str()); - } - - /* server main loop */ - while (m_is_running) { - int msg_size = zmq_recv (m_socket, m_msg_buffer, sizeof(m_msg_buffer), 0); - - /* msg_size of -1 is an error - decode it */ - if (msg_size == -1) { - /* normal shutdown and zmq_term was called */ - if (errno == ETERM) { - break; - } else { - throw TrexRpcException("Unhandled error of zmq_recv"); - } - } - - /* transform it to a string */ - std::string request((const char *)m_msg_buffer, msg_size); - handle_request(request); - } - - /* must be done from the same thread */ - zmq_close(m_socket); -} - -/** - * stops the ZMQ based RPC server - * - */ -void TrexRpcServerReqRes::_stop_rpc_thread() { - /* by calling zmq_term we signal the blocked thread to exit */ - zmq_term(m_context); - -} - -/** - * handles a request given to the server - * respondes to the request - */ -void TrexRpcServerReqRes::handle_request(const std::string &request) { - std::vector commands; - Json::FastWriter writer; - Json::Value response; - - /* first parse the request using JSON RPC V2 parser */ - TrexJsonRpcV2Parser rpc_request(request); - rpc_request.parse(commands); - - int index = 0; - - /* for every command parsed - launch it */ - for (auto command : commands) { - Json::Value single_response; - - command->execute(single_response); - delete command; - - 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); - -} diff --git a/src/rpc-server/src/trex_rpc_req_resp_server.cpp b/src/rpc-server/src/trex_rpc_req_resp_server.cpp new file mode 100644 index 00000000..e40f5554 --- /dev/null +++ b/src/rpc-server/src/trex_rpc_req_resp_server.cpp @@ -0,0 +1,141 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +/** + * ZMQ based request-response server + * + */ +TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg) : TrexRpcServerInterface(cfg) { + /* ZMQ is not thread safe - this should be outside */ + m_context = zmq_ctx_new(); +} + +/** + * main entry point for the server + * this function will be created on a different thread + * + * @author imarom (17-Aug-15) + */ +void TrexRpcServerReqRes::_rpc_thread_cb() { + std::stringstream ss; + + /* create a socket based on the configuration */ + + m_socket = zmq_socket (m_context, ZMQ_REP); + + switch (m_cfg.get_protocol()) { + case TrexRpcServerConfig::RPC_PROT_TCP: + ss << "tcp://*:"; + break; + default: + throw TrexRpcException("unknown protocol for RPC"); + } + + ss << m_cfg.get_port(); + + /* bind the scoket */ + int rc = zmq_bind (m_socket, ss.str().c_str()); + if (rc != 0) { + throw TrexRpcException("Unable to start ZMQ server at: " + ss.str()); + } + + /* server main loop */ + while (m_is_running) { + int msg_size = zmq_recv (m_socket, m_msg_buffer, sizeof(m_msg_buffer), 0); + + /* msg_size of -1 is an error - decode it */ + if (msg_size == -1) { + /* normal shutdown and zmq_term was called */ + if (errno == ETERM) { + break; + } else { + throw TrexRpcException("Unhandled error of zmq_recv"); + } + } + + /* transform it to a string */ + std::string request((const char *)m_msg_buffer, msg_size); + handle_request(request); + } + + /* must be done from the same thread */ + zmq_close(m_socket); +} + +/** + * stops the ZMQ based RPC server + * + */ +void TrexRpcServerReqRes::_stop_rpc_thread() { + /* by calling zmq_term we signal the blocked thread to exit */ + zmq_term(m_context); + +} + +/** + * handles a request given to the server + * respondes to the request + */ +void TrexRpcServerReqRes::handle_request(const std::string &request) { + std::vector commands; + Json::FastWriter writer; + Json::Value response; + + /* first parse the request using JSON RPC V2 parser */ + TrexJsonRpcV2Parser rpc_request(request); + rpc_request.parse(commands); + + int index = 0; + + /* for every command parsed - launch it */ + for (auto command : commands) { + Json::Value single_response; + + command->execute(single_response); + delete command; + + 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); + +} diff --git a/src/rpc-server/src/trex_rpc_server.cpp b/src/rpc-server/src/trex_rpc_server.cpp index bdbab5cf..34e60c96 100644 --- a/src/rpc-server/src/trex_rpc_server.cpp +++ b/src/rpc-server/src/trex_rpc_server.cpp @@ -20,7 +20,7 @@ limitations under the License. */ #include -#include +#include #include #include #include -- cgit 1.2.3-korg