1 | /************************************************************************* |
2 | * libjson-rpc-cpp |
3 | ************************************************************************* |
4 | * @file rpcprotocolserverv2.cpp |
5 | * @date 31.12.2012 |
6 | * @author Peter Spiess-Knafl <dev@spiessknafl.at> |
7 | * @license See attached LICENSE.txt |
8 | ************************************************************************/ |
9 | |
10 | #include "rpcprotocolserverv2.h" |
11 | #include <iostream> |
12 | #include <jsonrpccpp/common/errors.h> |
13 | |
14 | using namespace std; |
15 | using namespace jsonrpc; |
16 | |
17 | RpcProtocolServerV2::RpcProtocolServerV2(IProcedureInvokationHandler &handler) : AbstractProtocolHandler(handler) {} |
18 | |
19 | void RpcProtocolServerV2::HandleJsonRequest(const Json::Value &req, Json::Value &response) { |
20 | // It could be a Batch Request |
21 | if (req.isArray()) { |
22 | this->HandleBatchRequest(req, response); |
23 | } // It could be a simple Request |
24 | else if (req.isObject()) { |
25 | this->HandleSingleRequest(req, response); |
26 | } else { |
27 | this->WrapError(Json::nullValue, Errors::ERROR_RPC_INVALID_REQUEST, Errors::GetErrorMessage(Errors::ERROR_RPC_INVALID_REQUEST), response); |
28 | } |
29 | } |
30 | void RpcProtocolServerV2::HandleSingleRequest(const Json::Value &req, Json::Value &response) { |
31 | int error = this->ValidateRequest(req); |
32 | if (error == 0) { |
33 | try { |
34 | this->ProcessRequest(req, response); |
35 | } catch (const JsonRpcException &exc) { |
36 | this->WrapException(req, exc, response); |
37 | } |
38 | } else { |
39 | this->WrapError(req, error, Errors::GetErrorMessage(error), response); |
40 | } |
41 | } |
42 | void RpcProtocolServerV2::HandleBatchRequest(const Json::Value &req, Json::Value &response) { |
43 | if (req.empty()) |
44 | this->WrapError(Json::nullValue, Errors::ERROR_RPC_INVALID_REQUEST, Errors::GetErrorMessage(Errors::ERROR_RPC_INVALID_REQUEST), response); |
45 | else { |
46 | for (unsigned int i = 0; i < req.size(); i++) { |
47 | Json::Value result; |
48 | this->HandleSingleRequest(req[i], result); |
49 | if (result != Json::nullValue) |
50 | response.append(result); |
51 | } |
52 | } |
53 | } |
54 | bool RpcProtocolServerV2::ValidateRequestFields(const Json::Value &request) { |
55 | if (!request.isObject()) |
56 | return false; |
57 | if (!(request.isMember(KEY_REQUEST_METHODNAME) && request[KEY_REQUEST_METHODNAME].isString())) |
58 | return false; |
59 | if (!(request.isMember(KEY_REQUEST_VERSION) && request[KEY_REQUEST_VERSION].isString() && request[KEY_REQUEST_VERSION].asString() == JSON_RPC_VERSION2)) |
60 | return false; |
61 | if (request.isMember(KEY_REQUEST_ID) && !(request[KEY_REQUEST_ID].isIntegral() || request[KEY_REQUEST_ID].isString() || request[KEY_REQUEST_ID].isNull())) |
62 | return false; |
63 | if (request.isMember(KEY_REQUEST_PARAMETERS) && |
64 | !(request[KEY_REQUEST_PARAMETERS].isObject() || request[KEY_REQUEST_PARAMETERS].isArray() || request[KEY_REQUEST_PARAMETERS].isNull())) |
65 | return false; |
66 | return true; |
67 | } |
68 | |
69 | void RpcProtocolServerV2::WrapResult(const Json::Value &request, Json::Value &response, Json::Value &result) { |
70 | response[KEY_REQUEST_VERSION] = JSON_RPC_VERSION2; |
71 | response[KEY_RESPONSE_RESULT] = result; |
72 | response[KEY_REQUEST_ID] = request[KEY_REQUEST_ID]; |
73 | } |
74 | |
75 | void RpcProtocolServerV2::WrapError(const Json::Value &request, int code, const string &message, Json::Value &result) { |
76 | result["jsonrpc" ] = "2.0" ; |
77 | result["error" ]["code" ] = code; |
78 | result["error" ]["message" ] = message; |
79 | |
80 | if (request.isObject() && request.isMember("id" ) && (request["id" ].isNull() || request["id" ].isIntegral() || request["id" ].isString())) { |
81 | result["id" ] = request["id" ]; |
82 | } else { |
83 | result["id" ] = Json::nullValue; |
84 | } |
85 | } |
86 | |
87 | void RpcProtocolServerV2::WrapException(const Json::Value &request, const JsonRpcException &exception, Json::Value &result) { |
88 | this->WrapError(request, exception.GetCode(), exception.GetMessage(), result); |
89 | result["error" ]["data" ] = exception.GetData(); |
90 | } |
91 | |
92 | procedure_t RpcProtocolServerV2::GetRequestType(const Json::Value &request) { |
93 | if (request.isMember(KEY_REQUEST_ID)) |
94 | return RPC_METHOD; |
95 | return RPC_NOTIFICATION; |
96 | } |
97 | |