danicoin/src/Rpc/JsonRpc.h
2016-01-18 15:33:29 +00:00

224 lines
4.9 KiB
C++
Executable file

// Copyright (c) 2011-2016 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <functional>
#include "CoreRpcServerCommandsDefinitions.h"
#include <Common/JsonValue.h>
#include "Serialization/ISerializer.h"
#include "Serialization/SerializationTools.h"
namespace CryptoNote {
class HttpClient;
namespace JsonRpc {
const int errParseError = -32700;
const int errInvalidRequest = -32600;
const int errMethodNotFound = -32601;
const int errInvalidParams = -32602;
const int errInternalError = -32603;
class JsonRpcError: public std::exception {
public:
JsonRpcError();
JsonRpcError(int c);
JsonRpcError(int c, const std::string& msg);
#ifdef _MSC_VER
virtual const char* what() const override {
#else
virtual const char* what() const noexcept override {
#endif
return message.c_str();
}
void serialize(ISerializer& s) {
s(code, "code");
s(message, "message");
}
int code;
std::string message;
};
typedef boost::optional<Common::JsonValue> OptionalId;
class JsonRpcRequest {
public:
JsonRpcRequest() : psReq(Common::JsonValue::OBJECT) {}
bool parseRequest(const std::string& requestBody) {
try {
psReq = Common::JsonValue::fromString(requestBody);
} catch (std::exception&) {
throw JsonRpcError(errParseError);
}
if (!psReq.contains("method")) {
throw JsonRpcError(errInvalidRequest);
}
method = psReq("method").getString();
if (psReq.contains("id")) {
id = psReq("id");
}
return true;
}
template <typename T>
bool loadParams(T& v) const {
loadFromJsonValue(v, psReq.contains("params") ?
psReq("params") : Common::JsonValue(Common::JsonValue::NIL));
return true;
}
template <typename T>
bool setParams(const T& v) {
psReq.set("params", storeToJsonValue(v));
return true;
}
const std::string& getMethod() const {
return method;
}
void setMethod(const std::string& m) {
method = m;
}
const OptionalId& getId() const {
return id;
}
std::string getBody() {
psReq.set("jsonrpc", std::string("2.0"));
psReq.set("method", method);
return psReq.toString();
}
private:
Common::JsonValue psReq;
OptionalId id;
std::string method;
};
class JsonRpcResponse {
public:
JsonRpcResponse() : psResp(Common::JsonValue::OBJECT) {}
void parse(const std::string& responseBody) {
try {
psResp = Common::JsonValue::fromString(responseBody);
} catch (std::exception&) {
throw JsonRpcError(errParseError);
}
}
void setId(const OptionalId& id) {
if (id.is_initialized()) {
psResp.insert("id", id.get());
}
}
void setError(const JsonRpcError& err) {
psResp.set("error", storeToJsonValue(err));
}
bool getError(JsonRpcError& err) const {
if (!psResp.contains("error")) {
return false;
}
loadFromJsonValue(err, psResp("error"));
return true;
}
std::string getBody() {
psResp.set("jsonrpc", std::string("2.0"));
return psResp.toString();
}
template <typename T>
bool setResult(const T& v) {
psResp.set("result", storeToJsonValue(v));
return true;
}
template <typename T>
bool getResult(T& v) const {
if (!psResp.contains("result")) {
return false;
}
loadFromJsonValue(v, psResp("result"));
return true;
}
private:
Common::JsonValue psResp;
};
void invokeJsonRpcCommand(HttpClient& httpClient, JsonRpcRequest& req, JsonRpcResponse& res);
template <typename Request, typename Response>
void invokeJsonRpcCommand(HttpClient& httpClient, const std::string& method, const Request& req, Response& res) {
JsonRpcRequest jsReq;
JsonRpcResponse jsRes;
jsReq.setMethod(method);
jsReq.setParams(req);
invokeJsonRpcCommand(httpClient, jsReq, jsRes);
jsRes.getResult(res);
}
template <typename Request, typename Response, typename Handler>
bool invokeMethod(const JsonRpcRequest& jsReq, JsonRpcResponse& jsRes, Handler handler) {
Request req;
Response res;
if (!std::is_same<Request, CryptoNote::EMPTY_STRUCT>::value && !jsReq.loadParams(req)) {
throw JsonRpcError(JsonRpc::errInvalidParams);
}
bool result = handler(req, res);
if (result) {
if (!jsRes.setResult(res)) {
throw JsonRpcError(JsonRpc::errInternalError);
}
}
return result;
}
typedef std::function<bool(void*, const JsonRpcRequest& req, JsonRpcResponse& res)> JsonMemberMethod;
template <typename Class, typename Params, typename Result>
JsonMemberMethod makeMemberMethod(bool (Class::*handler)(const Params&, Result&)) {
return [handler](void* obj, const JsonRpcRequest& req, JsonRpcResponse& res) {
return JsonRpc::invokeMethod<Params, Result>(
req, res, std::bind(handler, static_cast<Class*>(obj), std::placeholders::_1, std::placeholders::_2));
};
}
}
}