danicoin/src/rpc/JsonRpc.h

236 lines
5.4 KiB
C
Raw Normal View History

2015-05-27 12:08:46 +00:00
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <functional>
2015-07-15 12:23:00 +00:00
#include "serialization/ISerializer.h"
#include "serialization/SerializationTools.h"
#include <Common/JsonValue.h>
2015-05-27 12:08:46 +00:00
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();
}
2015-07-15 12:23:00 +00:00
void serialize(ISerializer& s) {
s(code, "code");
s(message, "message");
}
2015-05-27 12:08:46 +00:00
int code;
std::string message;
};
2015-07-15 12:23:00 +00:00
typedef boost::optional<Common::JsonValue> OptionalId;
2015-05-27 12:08:46 +00:00
class JsonRpcRequest {
public:
2015-07-15 12:23:00 +00:00
JsonRpcRequest() : psReq(Common::JsonValue::OBJECT) {}
2015-05-27 12:08:46 +00:00
bool parseRequest(const std::string& requestBody) {
2015-07-15 12:23:00 +00:00
try {
psReq = Common::JsonValue::fromString(requestBody);
} catch (std::exception&) {
2015-05-27 12:08:46 +00:00
throw JsonRpcError(errParseError);
}
2015-07-15 12:23:00 +00:00
if (!psReq.contains("method")) {
throw JsonRpcError(errInvalidRequest);
2015-05-27 12:08:46 +00:00
}
2015-07-15 12:23:00 +00:00
method = psReq("method").getString();
if (psReq.contains("id")) {
id = psReq("id");
2015-05-27 12:08:46 +00:00
}
return true;
}
template <typename T>
bool loadParams(T& v) const {
2015-07-15 12:23:00 +00:00
loadFromJsonValue(v, psReq.contains("params") ?
psReq("params") : Common::JsonValue(Common::JsonValue::NIL));
return true;
2015-05-27 12:08:46 +00:00
}
template <typename T>
bool setParams(const T& v) {
2015-07-15 12:23:00 +00:00
psReq.set("params", storeToJsonValue(v));
return true;
2015-05-27 12:08:46 +00:00
}
const std::string& getMethod() const {
return method;
}
void setMethod(const std::string& m) {
method = m;
}
const OptionalId& getId() const {
return id;
}
std::string getBody() {
2015-07-15 12:23:00 +00:00
psReq.set("jsonrpc", std::string("2.0"));
psReq.set("method", method);
return psReq.toString();
2015-05-27 12:08:46 +00:00
}
private:
2015-07-15 12:23:00 +00:00
Common::JsonValue psReq;
2015-05-27 12:08:46 +00:00
OptionalId id;
std::string method;
};
class JsonRpcResponse {
public:
2015-07-15 12:23:00 +00:00
JsonRpcResponse() : psResp(Common::JsonValue::OBJECT) {}
void parse(const std::string& responseBody) {
try {
psResp = Common::JsonValue::fromString(responseBody);
} catch (std::exception&) {
2015-05-27 12:08:46 +00:00
throw JsonRpcError(errParseError);
}
}
void setId(const OptionalId& id) {
if (id.is_initialized()) {
2015-07-15 12:23:00 +00:00
psResp.insert("id", id.get());
2015-05-27 12:08:46 +00:00
}
}
void setError(const JsonRpcError& err) {
2015-07-15 12:23:00 +00:00
psResp.set("error", storeToJsonValue(err));
2015-05-27 12:08:46 +00:00
}
2015-07-15 12:23:00 +00:00
bool getError(JsonRpcError& err) const {
if (!psResp.contains("error")) {
2015-05-27 12:08:46 +00:00
return false;
}
2015-07-15 12:23:00 +00:00
loadFromJsonValue(err, psResp("error"));
2015-05-27 12:08:46 +00:00
return true;
}
std::string getBody() {
2015-07-15 12:23:00 +00:00
psResp.set("jsonrpc", std::string("2.0"));
return psResp.toString();
2015-05-27 12:08:46 +00:00
}
template <typename T>
bool setResult(const T& v) {
2015-07-15 12:23:00 +00:00
psResp.set("result", storeToJsonValue(v));
return true;
2015-05-27 12:08:46 +00:00
}
template <typename T>
bool getResult(T& v) const {
2015-07-15 12:23:00 +00:00
if (!psResp.contains("result")) {
return false;
}
loadFromJsonValue(v, psResp("result"));
return true;
2015-05-27 12:08:46 +00:00
}
private:
2015-07-15 12:23:00 +00:00
Common::JsonValue psResp;
2015-05-27 12:08:46 +00:00
};
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 (!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));
};
}
}
}