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
14using namespace std;
15using namespace jsonrpc;
16
17RpcProtocolServerV2::RpcProtocolServerV2(IProcedureInvokationHandler &handler) : AbstractProtocolHandler(handler) {}
18
19void 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}
30void 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}
42void 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}
54bool 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
69void 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
75void 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
87void 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
92procedure_t RpcProtocolServerV2::GetRequestType(const Json::Value &request) {
93 if (request.isMember(KEY_REQUEST_ID))
94 return RPC_METHOD;
95 return RPC_NOTIFICATION;
96}
97