From 0f78b06e8c578819f831a513490278a5f70b01af Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Thu, 7 Nov 2019 05:45:06 +0000 Subject: Various improvements to the ZMQ JSON-RPC handling: - Finding handling function in ZMQ JSON-RPC now uses binary search - Temporary `std::vector`s in JSON output now use `epee::span` to prevent allocations. - Binary -> hex in JSON output no longer allocates temporary buffer - C++ structs -> JSON skips intermediate DOM creation, and instead write directly to an output stream. --- src/rpc/daemon_handler.cpp | 125 +++++---- src/rpc/daemon_handler.h | 2 +- src/rpc/daemon_messages.cpp | 618 ++++++++++++++------------------------------ src/rpc/daemon_messages.h | 17 +- src/rpc/message.cpp | 192 +++++--------- src/rpc/message.h | 49 +--- 6 files changed, 353 insertions(+), 650 deletions(-) (limited to 'src/rpc') diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 0b6cd6c7a..7c2bc4562 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -28,6 +28,10 @@ #include "daemon_handler.h" +#include +#include +#include + #include // likely included by daemon_handler.h's includes, // but including here for clarity @@ -42,6 +46,74 @@ namespace cryptonote namespace rpc { + namespace + { + using handler_function = std::string(DaemonHandler& handler, const rapidjson::Value& id, const rapidjson::Value& msg); + struct handler_map + { + const char* method_name; + handler_function* call; + }; + + bool operator<(const handler_map& lhs, const handler_map& rhs) noexcept + { + return std::strcmp(lhs.method_name, rhs.method_name) < 0; + } + + bool operator<(const handler_map& lhs, const std::string& rhs) noexcept + { + return std::strcmp(lhs.method_name, rhs.c_str()) < 0; + } + + template + std::string handle_message(DaemonHandler& handler, const rapidjson::Value& id, const rapidjson::Value& parameters) + { + typename Message::Request request{}; + request.fromJson(parameters); + + typename Message::Response response{}; + handler.handle(request, response); + return FullMessage::getResponse(response, id); + } + + constexpr const handler_map handlers[] = + { + {u8"get_block_hash", handle_message}, + {u8"get_block_header_by_hash", handle_message}, + {u8"get_block_header_by_height", handle_message}, + {u8"get_block_headers_by_height", handle_message}, + {u8"get_blocks_fast", handle_message}, + {u8"get_dynamic_fee_estimate", handle_message}, + {u8"get_hashes_fast", handle_message}, + {u8"get_height", handle_message}, + {u8"get_info", handle_message}, + {u8"get_last_block_header", handle_message}, + {u8"get_output_distribution", handle_message}, + {u8"get_output_histogram", handle_message}, + {u8"get_output_keys", handle_message}, + {u8"get_peer_list", handle_message}, + {u8"get_rpc_version", handle_message}, + {u8"get_transaction_pool", handle_message}, + {u8"get_transactions", handle_message}, + {u8"get_tx_global_output_indices", handle_message}, + {u8"hard_fork_info", handle_message}, + {u8"key_images_spent", handle_message}, + {u8"mining_status", handle_message}, + {u8"save_bc", handle_message}, + {u8"send_raw_tx", handle_message}, + {u8"set_log_level", handle_message}, + {u8"start_mining", handle_message}, + {u8"stop_mining", handle_message} + }; + } // anonymous + + DaemonHandler::DaemonHandler(cryptonote::core& c, t_p2p& p2p) + : m_core(c), m_p2p(p2p) + { + const auto last_sorted = std::is_sorted_until(std::begin(handlers), std::end(handlers)); + if (last_sorted != std::end(handlers)) + throw std::logic_error{std::string{"ZMQ JSON-RPC handlers map is not properly sorted, see "} + last_sorted->method_name}; + } void DaemonHandler::handle(const GetHeight::Request& req, GetHeight::Response& res) { @@ -840,68 +912,21 @@ namespace rpc { MDEBUG("Handling RPC request: " << request); - Message* resp_message = NULL; - try { FullMessage req_full(request, true); - rapidjson::Value& req_json = req_full.getMessage(); - const std::string request_type = req_full.getRequestType(); - - // create correct Message subclass and call handle() on it - REQ_RESP_TYPES_MACRO(request_type, GetHeight, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetBlocksFast, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetHashesFast, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetTransactions, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, KeyImagesSpent, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetTxGlobalOutputIndices, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, SendRawTx, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, SendRawTxHex, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetInfo, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, StartMining, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, StopMining, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, MiningStatus, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, SaveBC, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetBlockHash, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetLastBlockHeader, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetBlockHeaderByHash, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetBlockHeaderByHeight, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetBlockHeadersByHeight, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetPeerList, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, SetLogLevel, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetTransactionPool, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, HardForkInfo, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetOutputHistogram, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetOutputKeys, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetRPCVersion, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetFeeEstimate, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetOutputDistribution, req_json, resp_message, handle); - - // if none of the request types matches - if (resp_message == NULL) - { + const auto matched_handler = std::lower_bound(std::begin(handlers), std::end(handlers), request_type); + if (matched_handler == std::end(handlers) || matched_handler->method_name != request_type) return BAD_REQUEST(request_type, req_full.getID()); - } - - FullMessage resp_full = FullMessage::responseMessage(resp_message, req_full.getID()); - - const std::string response = resp_full.getJson(); - delete resp_message; - resp_message = NULL; + std::string response = matched_handler->call(*this, req_full.getID(), req_full.getMessage()); MDEBUG("Returning RPC response: " << response); - return response; } catch (const std::exception& e) { - if (resp_message) - { - delete resp_message; - } - return BAD_JSON(e.what()); } } diff --git a/src/rpc/daemon_handler.h b/src/rpc/daemon_handler.h index 34723f676..c33f608ab 100644 --- a/src/rpc/daemon_handler.h +++ b/src/rpc/daemon_handler.h @@ -50,7 +50,7 @@ class DaemonHandler : public RpcHandler { public: - DaemonHandler(cryptonote::core& c, t_p2p& p2p) : m_core(c), m_p2p(p2p) { } + DaemonHandler(cryptonote::core& c, t_p2p& p2p); ~DaemonHandler() { } diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp index cf0f5ece1..5c179408e 100644 --- a/src/rpc/daemon_messages.cpp +++ b/src/rpc/daemon_messages.cpp @@ -34,99 +34,47 @@ namespace cryptonote namespace rpc { +void GetHeight::Request::doToJson(rapidjson::Writer& dest) const +{} -const char* const GetHeight::name = "get_height"; -const char* const GetBlocksFast::name = "get_blocks_fast"; -const char* const GetHashesFast::name = "get_hashes_fast"; -const char* const GetTransactions::name = "get_transactions"; -const char* const KeyImagesSpent::name = "key_images_spent"; -const char* const GetTxGlobalOutputIndices::name = "get_tx_global_output_indices"; -const char* const SendRawTx::name = "send_raw_tx"; -const char* const SendRawTxHex::name = "send_raw_tx_hex"; -const char* const StartMining::name = "start_mining"; -const char* const StopMining::name = "stop_mining"; -const char* const MiningStatus::name = "mining_status"; -const char* const GetInfo::name = "get_info"; -const char* const SaveBC::name = "save_bc"; -const char* const GetBlockHash::name = "get_block_hash"; -const char* const GetLastBlockHeader::name = "get_last_block_header"; -const char* const GetBlockHeaderByHash::name = "get_block_header_by_hash"; -const char* const GetBlockHeaderByHeight::name = "get_block_header_by_height"; -const char* const GetBlockHeadersByHeight::name = "get_block_headers_by_height"; -const char* const GetPeerList::name = "get_peer_list"; -const char* const SetLogLevel::name = "set_log_level"; -const char* const GetTransactionPool::name = "get_transaction_pool"; -const char* const HardForkInfo::name = "hard_fork_info"; -const char* const GetOutputHistogram::name = "get_output_histogram"; -const char* const GetOutputKeys::name = "get_output_keys"; -const char* const GetRPCVersion::name = "get_rpc_version"; -const char* const GetFeeEstimate::name = "get_dynamic_fee_estimate"; -const char* const GetOutputDistribution::name = "get_output_distribution"; - - - - -rapidjson::Value GetHeight::Request::toJson(rapidjson::Document& doc) const +void GetHeight::Request::fromJson(const rapidjson::Value& val) { - return Message::toJson(doc); } -void GetHeight::Request::fromJson(rapidjson::Value& val) +void GetHeight::Response::doToJson(rapidjson::Writer& dest) const { + INSERT_INTO_JSON_OBJECT(dest, height, height); } -rapidjson::Value GetHeight::Response::toJson(rapidjson::Document& doc) const -{ - auto val = Message::toJson(doc); - - auto& al = doc.GetAllocator(); - - val.AddMember("height", height, al); - - return val; -} - -void GetHeight::Response::fromJson(rapidjson::Value& val) +void GetHeight::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, height, height); } -rapidjson::Value GetBlocksFast::Request::toJson(rapidjson::Document& doc) const +void GetBlocksFast::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - auto& al = doc.GetAllocator(); - - INSERT_INTO_JSON_OBJECT(val, doc, block_ids, block_ids); - val.AddMember("start_height", start_height, al); - val.AddMember("prune", prune, al); - - return val; + INSERT_INTO_JSON_OBJECT(dest, block_ids, block_ids); + INSERT_INTO_JSON_OBJECT(dest, start_height, start_height); + INSERT_INTO_JSON_OBJECT(dest, prune, prune); } -void GetBlocksFast::Request::fromJson(rapidjson::Value& val) +void GetBlocksFast::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, block_ids, block_ids); GET_FROM_JSON_OBJECT(val, start_height, start_height); GET_FROM_JSON_OBJECT(val, prune, prune); } -rapidjson::Value GetBlocksFast::Response::toJson(rapidjson::Document& doc) const +void GetBlocksFast::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - auto& al = doc.GetAllocator(); - - INSERT_INTO_JSON_OBJECT(val, doc, blocks, blocks); - val.AddMember("start_height", start_height, al); - val.AddMember("current_height", current_height, al); - INSERT_INTO_JSON_OBJECT(val, doc, output_indices, output_indices); - - return val; + INSERT_INTO_JSON_OBJECT(dest, blocks, blocks); + INSERT_INTO_JSON_OBJECT(dest, start_height, start_height); + INSERT_INTO_JSON_OBJECT(dest, current_height, current_height); + INSERT_INTO_JSON_OBJECT(dest, output_indices, output_indices); } -void GetBlocksFast::Response::fromJson(rapidjson::Value& val) +void GetBlocksFast::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, blocks, blocks); GET_FROM_JSON_OBJECT(val, start_height, start_height); @@ -135,38 +83,26 @@ void GetBlocksFast::Response::fromJson(rapidjson::Value& val) } -rapidjson::Value GetHashesFast::Request::toJson(rapidjson::Document& doc) const +void GetHashesFast::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - auto& al = doc.GetAllocator(); - - INSERT_INTO_JSON_OBJECT(val, doc, known_hashes, known_hashes); - val.AddMember("start_height", start_height, al); - - return val; + INSERT_INTO_JSON_OBJECT(dest, known_hashes, known_hashes); + INSERT_INTO_JSON_OBJECT(dest, start_height, start_height); } -void GetHashesFast::Request::fromJson(rapidjson::Value& val) +void GetHashesFast::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, known_hashes, known_hashes); GET_FROM_JSON_OBJECT(val, start_height, start_height); } -rapidjson::Value GetHashesFast::Response::toJson(rapidjson::Document& doc) const +void GetHashesFast::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - auto& al = doc.GetAllocator(); - - INSERT_INTO_JSON_OBJECT(val, doc, hashes, hashes); - val.AddMember("start_height", start_height, al); - val.AddMember("current_height", current_height, al); - - return val; + INSERT_INTO_JSON_OBJECT(dest, hashes, hashes); + INSERT_INTO_JSON_OBJECT(dest, start_height, start_height); + INSERT_INTO_JSON_OBJECT(dest, current_height, current_height); } -void GetHashesFast::Response::fromJson(rapidjson::Value& val) +void GetHashesFast::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, hashes, hashes); GET_FROM_JSON_OBJECT(val, start_height, start_height); @@ -174,154 +110,114 @@ void GetHashesFast::Response::fromJson(rapidjson::Value& val) } -rapidjson::Value GetTransactions::Request::toJson(rapidjson::Document& doc) const +void GetTransactions::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, tx_hashes, tx_hashes); - - return val; + INSERT_INTO_JSON_OBJECT(dest, tx_hashes, tx_hashes); } -void GetTransactions::Request::fromJson(rapidjson::Value& val) +void GetTransactions::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, tx_hashes, tx_hashes); } -rapidjson::Value GetTransactions::Response::toJson(rapidjson::Document& doc) const +void GetTransactions::Response::doToJson(rapidjson::Writer& dest) const { - rapidjson::Value val(rapidjson::kObjectType); - - INSERT_INTO_JSON_OBJECT(val, doc, txs, txs); - INSERT_INTO_JSON_OBJECT(val, doc, missed_hashes, missed_hashes); - - return val; + INSERT_INTO_JSON_OBJECT(dest, txs, txs); + INSERT_INTO_JSON_OBJECT(dest, missed_hashes, missed_hashes); } -void GetTransactions::Response::fromJson(rapidjson::Value& val) +void GetTransactions::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, txs, txs); GET_FROM_JSON_OBJECT(val, missed_hashes, missed_hashes); } -rapidjson::Value KeyImagesSpent::Request::toJson(rapidjson::Document& doc) const +void KeyImagesSpent::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, key_images, key_images); - - return val; + INSERT_INTO_JSON_OBJECT(dest, key_images, key_images); } -void KeyImagesSpent::Request::fromJson(rapidjson::Value& val) +void KeyImagesSpent::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, key_images, key_images); } -rapidjson::Value KeyImagesSpent::Response::toJson(rapidjson::Document& doc) const +void KeyImagesSpent::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, spent_status, spent_status); - - return val; + INSERT_INTO_JSON_OBJECT(dest, spent_status, spent_status); } -void KeyImagesSpent::Response::fromJson(rapidjson::Value& val) +void KeyImagesSpent::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, spent_status, spent_status); } -rapidjson::Value GetTxGlobalOutputIndices::Request::toJson(rapidjson::Document& doc) const +void GetTxGlobalOutputIndices::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, tx_hash, tx_hash); - - return val; + INSERT_INTO_JSON_OBJECT(dest, tx_hash, tx_hash); } -void GetTxGlobalOutputIndices::Request::fromJson(rapidjson::Value& val) +void GetTxGlobalOutputIndices::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, tx_hash, tx_hash); } -rapidjson::Value GetTxGlobalOutputIndices::Response::toJson(rapidjson::Document& doc) const +void GetTxGlobalOutputIndices::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, output_indices, output_indices); - - return val; + INSERT_INTO_JSON_OBJECT(dest, output_indices, output_indices); } -void GetTxGlobalOutputIndices::Response::fromJson(rapidjson::Value& val) +void GetTxGlobalOutputIndices::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, output_indices, output_indices); } -rapidjson::Value SendRawTx::Request::toJson(rapidjson::Document& doc) const +void SendRawTx::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, tx, tx); - INSERT_INTO_JSON_OBJECT(val, doc, relay, relay); - - return val; + INSERT_INTO_JSON_OBJECT(dest, tx, tx); + INSERT_INTO_JSON_OBJECT(dest, relay, relay); } -void SendRawTx::Request::fromJson(rapidjson::Value& val) +void SendRawTx::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, tx, tx); GET_FROM_JSON_OBJECT(val, relay, relay); } -rapidjson::Value SendRawTx::Response::toJson(rapidjson::Document& doc) const +void SendRawTx::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, relayed, relayed); - - return val; + INSERT_INTO_JSON_OBJECT(dest, relayed, relayed); } -void SendRawTx::Response::fromJson(rapidjson::Value& val) +void SendRawTx::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, relayed, relayed); } -rapidjson::Value SendRawTxHex::Request::toJson(rapidjson::Document& doc) const +void SendRawTxHex::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, tx_as_hex, tx_as_hex); - INSERT_INTO_JSON_OBJECT(val, doc, relay, relay); - - return val; + INSERT_INTO_JSON_OBJECT(dest, tx_as_hex, tx_as_hex); + INSERT_INTO_JSON_OBJECT(dest, relay, relay); } -void SendRawTxHex::Request::fromJson(rapidjson::Value& val) +void SendRawTxHex::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, tx_as_hex, tx_as_hex); GET_FROM_JSON_OBJECT(val, relay, relay); } -rapidjson::Value StartMining::Request::toJson(rapidjson::Document& doc) const +void StartMining::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, miner_address, miner_address); - INSERT_INTO_JSON_OBJECT(val, doc, threads_count, threads_count); - INSERT_INTO_JSON_OBJECT(val, doc, do_background_mining, do_background_mining); - INSERT_INTO_JSON_OBJECT(val, doc, ignore_battery, ignore_battery); - - return val; + INSERT_INTO_JSON_OBJECT(dest, miner_address, miner_address); + INSERT_INTO_JSON_OBJECT(dest, threads_count, threads_count); + INSERT_INTO_JSON_OBJECT(dest, do_background_mining, do_background_mining); + INSERT_INTO_JSON_OBJECT(dest, ignore_battery, ignore_battery); } -void StartMining::Request::fromJson(rapidjson::Value& val) +void StartMining::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, miner_address, miner_address); GET_FROM_JSON_OBJECT(val, threads_count, threads_count); @@ -329,58 +225,46 @@ void StartMining::Request::fromJson(rapidjson::Value& val) GET_FROM_JSON_OBJECT(val, ignore_battery, ignore_battery); } -rapidjson::Value StartMining::Response::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void StartMining::Response::doToJson(rapidjson::Writer& dest) const +{} -void StartMining::Response::fromJson(rapidjson::Value& val) +void StartMining::Response::fromJson(const rapidjson::Value& val) { } -rapidjson::Value StopMining::Request::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void StopMining::Request::doToJson(rapidjson::Writer& dest) const +{} -void StopMining::Request::fromJson(rapidjson::Value& val) +void StopMining::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value StopMining::Response::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void StopMining::Response::doToJson(rapidjson::Writer& dest) const +{} -void StopMining::Response::fromJson(rapidjson::Value& val) +void StopMining::Response::fromJson(const rapidjson::Value& val) { } -rapidjson::Value MiningStatus::Request::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void MiningStatus::Request::doToJson(rapidjson::Writer& dest) const +{} -void MiningStatus::Request::fromJson(rapidjson::Value& val) +void MiningStatus::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value MiningStatus::Response::toJson(rapidjson::Document& doc) const +void MiningStatus::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, active, active); - INSERT_INTO_JSON_OBJECT(val, doc, speed, speed); - INSERT_INTO_JSON_OBJECT(val, doc, threads_count, threads_count); - INSERT_INTO_JSON_OBJECT(val, doc, address, address); - INSERT_INTO_JSON_OBJECT(val, doc, is_background_mining_enabled, is_background_mining_enabled); - - return val; + INSERT_INTO_JSON_OBJECT(dest, active, active); + INSERT_INTO_JSON_OBJECT(dest, speed, speed); + INSERT_INTO_JSON_OBJECT(dest, threads_count, threads_count); + INSERT_INTO_JSON_OBJECT(dest, address, address); + INSERT_INTO_JSON_OBJECT(dest, is_background_mining_enabled, is_background_mining_enabled); } -void MiningStatus::Response::fromJson(rapidjson::Value& val) +void MiningStatus::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, active, active); GET_FROM_JSON_OBJECT(val, speed, speed); @@ -390,318 +274,230 @@ void MiningStatus::Response::fromJson(rapidjson::Value& val) } -rapidjson::Value GetInfo::Request::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void GetInfo::Request::doToJson(rapidjson::Writer& dest) const +{} -void GetInfo::Request::fromJson(rapidjson::Value& val) +void GetInfo::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetInfo::Response::toJson(rapidjson::Document& doc) const +void GetInfo::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, info, info); - - return val; + INSERT_INTO_JSON_OBJECT(dest, info, info); } -void GetInfo::Response::fromJson(rapidjson::Value& val) +void GetInfo::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, info, info); } -rapidjson::Value SaveBC::Request::toJson(rapidjson::Document& doc) const -{ - auto val = Message::toJson(doc); +void SaveBC::Request::doToJson(rapidjson::Writer& dest) const +{} - return val; -} - -void SaveBC::Request::fromJson(rapidjson::Value& val) +void SaveBC::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value SaveBC::Response::toJson(rapidjson::Document& doc) const -{ - auto val = Message::toJson(doc); +void SaveBC::Response::doToJson(rapidjson::Writer& dest) const +{} - return val; -} - -void SaveBC::Response::fromJson(rapidjson::Value& val) +void SaveBC::Response::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetBlockHash::Request::toJson(rapidjson::Document& doc) const +void GetBlockHash::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, height, height); - - return val; + INSERT_INTO_JSON_OBJECT(dest, height, height); } -void GetBlockHash::Request::fromJson(rapidjson::Value& val) +void GetBlockHash::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, height, height); } -rapidjson::Value GetBlockHash::Response::toJson(rapidjson::Document& doc) const +void GetBlockHash::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, hash, hash); - - return val; + INSERT_INTO_JSON_OBJECT(dest, hash, hash); } -void GetBlockHash::Response::fromJson(rapidjson::Value& val) +void GetBlockHash::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, hash, hash); } -rapidjson::Value GetLastBlockHeader::Request::toJson(rapidjson::Document& doc) const -{ - auto val = Message::toJson(doc); - - return val; -} +void GetLastBlockHeader::Request::doToJson(rapidjson::Writer& dest) const +{} -void GetLastBlockHeader::Request::fromJson(rapidjson::Value& val) +void GetLastBlockHeader::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetLastBlockHeader::Response::toJson(rapidjson::Document& doc) const +void GetLastBlockHeader::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, header, header); - - return val; + INSERT_INTO_JSON_OBJECT(dest, header, header); } -void GetLastBlockHeader::Response::fromJson(rapidjson::Value& val) +void GetLastBlockHeader::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, header, header); } -rapidjson::Value GetBlockHeaderByHash::Request::toJson(rapidjson::Document& doc) const +void GetBlockHeaderByHash::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, hash, hash); - - return val; + INSERT_INTO_JSON_OBJECT(dest, hash, hash); } -void GetBlockHeaderByHash::Request::fromJson(rapidjson::Value& val) +void GetBlockHeaderByHash::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, hash, hash); } -rapidjson::Value GetBlockHeaderByHash::Response::toJson(rapidjson::Document& doc) const +void GetBlockHeaderByHash::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, header, header); - - return val; + INSERT_INTO_JSON_OBJECT(dest, header, header); } -void GetBlockHeaderByHash::Response::fromJson(rapidjson::Value& val) +void GetBlockHeaderByHash::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, header, header); } -rapidjson::Value GetBlockHeaderByHeight::Request::toJson(rapidjson::Document& doc) const +void GetBlockHeaderByHeight::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, height, height); - - return val; + INSERT_INTO_JSON_OBJECT(dest, height, height); } -void GetBlockHeaderByHeight::Request::fromJson(rapidjson::Value& val) +void GetBlockHeaderByHeight::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, height, height); } -rapidjson::Value GetBlockHeaderByHeight::Response::toJson(rapidjson::Document& doc) const +void GetBlockHeaderByHeight::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, header, header); - - return val; + INSERT_INTO_JSON_OBJECT(dest, header, header); } -void GetBlockHeaderByHeight::Response::fromJson(rapidjson::Value& val) +void GetBlockHeaderByHeight::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, header, header); } -rapidjson::Value GetBlockHeadersByHeight::Request::toJson(rapidjson::Document& doc) const +void GetBlockHeadersByHeight::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, heights, heights); - - return val; + INSERT_INTO_JSON_OBJECT(dest, heights, heights); } -void GetBlockHeadersByHeight::Request::fromJson(rapidjson::Value& val) +void GetBlockHeadersByHeight::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, heights, heights); } -rapidjson::Value GetBlockHeadersByHeight::Response::toJson(rapidjson::Document& doc) const +void GetBlockHeadersByHeight::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, headers, headers); - - return val; + INSERT_INTO_JSON_OBJECT(dest, headers, headers); } -void GetBlockHeadersByHeight::Response::fromJson(rapidjson::Value& val) +void GetBlockHeadersByHeight::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, headers, headers); } -rapidjson::Value GetPeerList::Request::toJson(rapidjson::Document& doc) const -{ - auto val = Message::toJson(doc); +void GetPeerList::Request::doToJson(rapidjson::Writer& dest) const +{} - return val; -} - -void GetPeerList::Request::fromJson(rapidjson::Value& val) +void GetPeerList::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetPeerList::Response::toJson(rapidjson::Document& doc) const +void GetPeerList::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, white_list, white_list); - INSERT_INTO_JSON_OBJECT(val, doc, gray_list, gray_list); - - return val; + INSERT_INTO_JSON_OBJECT(dest, white_list, white_list); + INSERT_INTO_JSON_OBJECT(dest, gray_list, gray_list); } -void GetPeerList::Response::fromJson(rapidjson::Value& val) +void GetPeerList::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, white_list, white_list); GET_FROM_JSON_OBJECT(val, gray_list, gray_list); } -rapidjson::Value SetLogLevel::Request::toJson(rapidjson::Document& doc) const +void SetLogLevel::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - auto& al = doc.GetAllocator(); - - val.AddMember("level", level, al); - - return val; + INSERT_INTO_JSON_OBJECT(dest, level, level); } -void SetLogLevel::Request::fromJson(rapidjson::Value& val) +void SetLogLevel::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, level, level); } -rapidjson::Value SetLogLevel::Response::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void SetLogLevel::Response::doToJson(rapidjson::Writer& dest) const +{} -void SetLogLevel::Response::fromJson(rapidjson::Value& val) +void SetLogLevel::Response::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetTransactionPool::Request::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void GetTransactionPool::Request::doToJson(rapidjson::Writer& dest) const +{} -void GetTransactionPool::Request::fromJson(rapidjson::Value& val) +void GetTransactionPool::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetTransactionPool::Response::toJson(rapidjson::Document& doc) const +void GetTransactionPool::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, transactions, transactions); - INSERT_INTO_JSON_OBJECT(val, doc, key_images, key_images); - - return val; + INSERT_INTO_JSON_OBJECT(dest, transactions, transactions); + INSERT_INTO_JSON_OBJECT(dest, key_images, key_images); } -void GetTransactionPool::Response::fromJson(rapidjson::Value& val) +void GetTransactionPool::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, transactions, transactions); GET_FROM_JSON_OBJECT(val, key_images, key_images); } -rapidjson::Value HardForkInfo::Request::toJson(rapidjson::Document& doc) const +void HardForkInfo::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, version, version); - - return val; + INSERT_INTO_JSON_OBJECT(dest, version, version); } -void HardForkInfo::Request::fromJson(rapidjson::Value& val) +void HardForkInfo::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, version, version); } -rapidjson::Value HardForkInfo::Response::toJson(rapidjson::Document& doc) const +void HardForkInfo::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, info, info); - - return val; + INSERT_INTO_JSON_OBJECT(dest, info, info); } -void HardForkInfo::Response::fromJson(rapidjson::Value& val) +void HardForkInfo::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, info, info); } -rapidjson::Value GetOutputHistogram::Request::toJson(rapidjson::Document& doc) const +void GetOutputHistogram::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts); - INSERT_INTO_JSON_OBJECT(val, doc, min_count, min_count); - INSERT_INTO_JSON_OBJECT(val, doc, max_count, max_count); - INSERT_INTO_JSON_OBJECT(val, doc, unlocked, unlocked); - INSERT_INTO_JSON_OBJECT(val, doc, recent_cutoff, recent_cutoff); - - return val; + INSERT_INTO_JSON_OBJECT(dest, amounts, amounts); + INSERT_INTO_JSON_OBJECT(dest, min_count, min_count); + INSERT_INTO_JSON_OBJECT(dest, max_count, max_count); + INSERT_INTO_JSON_OBJECT(dest, unlocked, unlocked); + INSERT_INTO_JSON_OBJECT(dest, recent_cutoff, recent_cutoff); } -void GetOutputHistogram::Request::fromJson(rapidjson::Value& val) +void GetOutputHistogram::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, amounts, amounts); GET_FROM_JSON_OBJECT(val, min_count, min_count); @@ -710,100 +506,74 @@ void GetOutputHistogram::Request::fromJson(rapidjson::Value& val) GET_FROM_JSON_OBJECT(val, recent_cutoff, recent_cutoff); } -rapidjson::Value GetOutputHistogram::Response::toJson(rapidjson::Document& doc) const +void GetOutputHistogram::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, histogram, histogram); - - return val; + INSERT_INTO_JSON_OBJECT(dest, histogram, histogram); } -void GetOutputHistogram::Response::fromJson(rapidjson::Value& val) +void GetOutputHistogram::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, histogram, histogram); } -rapidjson::Value GetOutputKeys::Request::toJson(rapidjson::Document& doc) const +void GetOutputKeys::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, outputs, outputs); - - return val; + INSERT_INTO_JSON_OBJECT(dest, outputs, outputs); } -void GetOutputKeys::Request::fromJson(rapidjson::Value& val) +void GetOutputKeys::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, outputs, outputs); } -rapidjson::Value GetOutputKeys::Response::toJson(rapidjson::Document& doc) const +void GetOutputKeys::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, keys, keys); - - return val; + INSERT_INTO_JSON_OBJECT(dest, keys, keys); } -void GetOutputKeys::Response::fromJson(rapidjson::Value& val) +void GetOutputKeys::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, keys, keys); } -rapidjson::Value GetRPCVersion::Request::toJson(rapidjson::Document& doc) const -{ - return Message::toJson(doc); -} +void GetRPCVersion::Request::doToJson(rapidjson::Writer& dest) const +{} -void GetRPCVersion::Request::fromJson(rapidjson::Value& val) +void GetRPCVersion::Request::fromJson(const rapidjson::Value& val) { } -rapidjson::Value GetRPCVersion::Response::toJson(rapidjson::Document& doc) const +void GetRPCVersion::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, version, version); - - return val; + INSERT_INTO_JSON_OBJECT(dest, version, version); } -void GetRPCVersion::Response::fromJson(rapidjson::Value& val) +void GetRPCVersion::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, version, version); } -rapidjson::Value GetFeeEstimate::Request::toJson(rapidjson::Document& doc) const +void GetFeeEstimate::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, num_grace_blocks, num_grace_blocks); - - return val; + INSERT_INTO_JSON_OBJECT(dest, num_grace_blocks, num_grace_blocks); } -void GetFeeEstimate::Request::fromJson(rapidjson::Value& val) +void GetFeeEstimate::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, num_grace_blocks, num_grace_blocks); } -rapidjson::Value GetFeeEstimate::Response::toJson(rapidjson::Document& doc) const +void GetFeeEstimate::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, estimated_base_fee, estimated_base_fee); - INSERT_INTO_JSON_OBJECT(val, doc, fee_mask, fee_mask); - INSERT_INTO_JSON_OBJECT(val, doc, size_scale, size_scale); - INSERT_INTO_JSON_OBJECT(val, doc, hard_fork_version, hard_fork_version); - - return val; + INSERT_INTO_JSON_OBJECT(dest, estimated_base_fee, estimated_base_fee); + INSERT_INTO_JSON_OBJECT(dest, fee_mask, fee_mask); + INSERT_INTO_JSON_OBJECT(dest, size_scale, size_scale); + INSERT_INTO_JSON_OBJECT(dest, hard_fork_version, hard_fork_version); } -void GetFeeEstimate::Response::fromJson(rapidjson::Value& val) +void GetFeeEstimate::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, estimated_base_fee, estimated_base_fee); GET_FROM_JSON_OBJECT(val, fee_mask, fee_mask); @@ -811,19 +581,15 @@ void GetFeeEstimate::Response::fromJson(rapidjson::Value& val) GET_FROM_JSON_OBJECT(val, hard_fork_version, hard_fork_version); } -rapidjson::Value GetOutputDistribution::Request::toJson(rapidjson::Document& doc) const +void GetOutputDistribution::Request::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts); - INSERT_INTO_JSON_OBJECT(val, doc, from_height, from_height); - INSERT_INTO_JSON_OBJECT(val, doc, to_height, to_height); - INSERT_INTO_JSON_OBJECT(val, doc, cumulative, cumulative); - - return val; + INSERT_INTO_JSON_OBJECT(dest, amounts, amounts); + INSERT_INTO_JSON_OBJECT(dest, from_height, from_height); + INSERT_INTO_JSON_OBJECT(dest, to_height, to_height); + INSERT_INTO_JSON_OBJECT(dest, cumulative, cumulative); } -void GetOutputDistribution::Request::fromJson(rapidjson::Value& val) +void GetOutputDistribution::Request::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, amounts, amounts); GET_FROM_JSON_OBJECT(val, from_height, from_height); @@ -831,17 +597,13 @@ void GetOutputDistribution::Request::fromJson(rapidjson::Value& val) GET_FROM_JSON_OBJECT(val, cumulative, cumulative); } -rapidjson::Value GetOutputDistribution::Response::toJson(rapidjson::Document& doc) const +void GetOutputDistribution::Response::doToJson(rapidjson::Writer& dest) const { - auto val = Message::toJson(doc); - - INSERT_INTO_JSON_OBJECT(val, doc, status, status); - INSERT_INTO_JSON_OBJECT(val, doc, distributions, distributions); - - return val; + INSERT_INTO_JSON_OBJECT(dest, status, status); + INSERT_INTO_JSON_OBJECT(dest, distributions, distributions); } -void GetOutputDistribution::Response::fromJson(rapidjson::Value& val) +void GetOutputDistribution::Response::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, status, status); GET_FROM_JSON_OBJECT(val, distributions, distributions); diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index c0d9aed0a..bb5059cdc 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -28,6 +28,8 @@ #pragma once +#include +#include #include #include @@ -40,26 +42,25 @@ #define BEGIN_RPC_MESSAGE_CLASS(classname) \ class classname \ { \ - public: \ - static const char* const name; + public: #define BEGIN_RPC_MESSAGE_REQUEST \ - class Request : public Message \ + class Request final : public Message \ { \ public: \ Request() { } \ ~Request() { } \ - rapidjson::Value toJson(rapidjson::Document& doc) const; \ - void fromJson(rapidjson::Value& val); + void doToJson(rapidjson::Writer& dest) const override final; \ + void fromJson(const rapidjson::Value& val) override final; #define BEGIN_RPC_MESSAGE_RESPONSE \ - class Response : public Message \ + class Response final : public Message \ { \ public: \ Response() { } \ ~Response() { } \ - rapidjson::Value toJson(rapidjson::Document& doc) const; \ - void fromJson(rapidjson::Value& val); + void doToJson(rapidjson::Writer& dest) const override final; \ + void fromJson(const rapidjson::Value& val) override final; #define END_RPC_MESSAGE_REQUEST }; #define END_RPC_MESSAGE_RESPONSE }; diff --git a/src/rpc/message.cpp b/src/rpc/message.cpp index 158b58005..a3df7fb56 100644 --- a/src/rpc/message.cpp +++ b/src/rpc/message.cpp @@ -27,12 +27,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "message.h" + #include "daemon_rpc_version.h" #include "serialization/json_object.h" -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" - namespace cryptonote { @@ -54,60 +52,23 @@ constexpr const char params_field[] = "params"; constexpr const char result_field[] = "result"; } -rapidjson::Value Message::toJson(rapidjson::Document& doc) const +void Message::toJson(rapidjson::Writer& dest) const { - rapidjson::Value val(rapidjson::kObjectType); - - auto& al = doc.GetAllocator(); - - val.AddMember("status", rapidjson::StringRef(status.c_str()), al); - val.AddMember("error_details", rapidjson::StringRef(error_details.c_str()), al); - INSERT_INTO_JSON_OBJECT(val, doc, rpc_version, DAEMON_RPC_VERSION_ZMQ); - - return val; + dest.StartObject(); + INSERT_INTO_JSON_OBJECT(dest, status, status); + INSERT_INTO_JSON_OBJECT(dest, error_details, error_details); + INSERT_INTO_JSON_OBJECT(dest, rpc_version, DAEMON_RPC_VERSION_ZMQ); + doToJson(dest); + dest.EndObject(); } -void Message::fromJson(rapidjson::Value& val) +void Message::fromJson(const rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, status, status); GET_FROM_JSON_OBJECT(val, error_details, error_details); GET_FROM_JSON_OBJECT(val, rpc_version, rpc_version); } - -FullMessage::FullMessage(const std::string& request, Message* message) -{ - doc.SetObject(); - - doc.AddMember(method_field, rapidjson::StringRef(request.c_str()), doc.GetAllocator()); - doc.AddMember(params_field, message->toJson(doc), doc.GetAllocator()); - - // required by JSON-RPC 2.0 spec - doc.AddMember("jsonrpc", rapidjson::Value("2.0"), doc.GetAllocator()); -} - -FullMessage::FullMessage(Message* message) -{ - doc.SetObject(); - - // required by JSON-RPC 2.0 spec - doc.AddMember("jsonrpc", "2.0", doc.GetAllocator()); - - if (message->status == Message::STATUS_OK) - { - doc.AddMember(result_field, message->toJson(doc), doc.GetAllocator()); - } - else - { - cryptonote::rpc::error err; - - err.error_str = message->status; - err.message = message->error_details; - - INSERT_INTO_JSON_OBJECT(doc, doc, error, err); - } -} - FullMessage::FullMessage(const std::string& json_string, bool request) { doc.Parse(json_string.c_str()); @@ -132,30 +93,13 @@ FullMessage::FullMessage(const std::string& json_string, bool request) } } -std::string FullMessage::getJson() -{ - - if (!doc.HasMember(id_field)) - { - doc.AddMember(id_field, rapidjson::Value("unused"), doc.GetAllocator()); - } - - rapidjson::StringBuffer buf; - - rapidjson::Writer writer(buf); - - doc.Accept(writer); - - return std::string(buf.GetString(), buf.GetSize()); -} - std::string FullMessage::getRequestType() const { OBJECT_HAS_MEMBER_OR_THROW(doc, method_field) return doc[method_field].GetString(); } -rapidjson::Value& FullMessage::getMessage() +const rapidjson::Value& FullMessage::getMessage() const { if (doc.HasMember(params_field)) { @@ -174,30 +118,15 @@ rapidjson::Value& FullMessage::getMessage() rapidjson::Value FullMessage::getMessageCopy() { - rapidjson::Value& val = getMessage(); - - return rapidjson::Value(val, doc.GetAllocator()); + return rapidjson::Value(getMessage(), doc.GetAllocator()); } -rapidjson::Value& FullMessage::getID() +const rapidjson::Value& FullMessage::getID() const { OBJECT_HAS_MEMBER_OR_THROW(doc, id_field) return doc[id_field]; } -void FullMessage::setID(rapidjson::Value& id) -{ - auto itr = doc.FindMember(id_field); - if (itr != doc.MemberEnd()) - { - itr->value = id; - } - else - { - doc.AddMember(id_field, id, doc.GetAllocator()); - } -} - cryptonote::rpc::error FullMessage::getError() { cryptonote::rpc::error err; @@ -211,82 +140,89 @@ cryptonote::rpc::error FullMessage::getError() return err; } -FullMessage FullMessage::requestMessage(const std::string& request, Message* message) +std::string FullMessage::getRequest(const std::string& request, const Message& message, const unsigned id) { - return FullMessage(request, message); -} + rapidjson::StringBuffer buffer; + { + rapidjson::Writer dest{buffer}; -FullMessage FullMessage::requestMessage(const std::string& request, Message* message, rapidjson::Value& id) -{ - auto mes = requestMessage(request, message); - mes.setID(id); - return mes; -} + dest.StartObject(); + INSERT_INTO_JSON_OBJECT(dest, jsonrpc, (boost::string_ref{"2.0", 3})); -FullMessage FullMessage::responseMessage(Message* message) -{ - return FullMessage(message); -} + dest.Key(id_field); + json::toJsonValue(dest, id); -FullMessage FullMessage::responseMessage(Message* message, rapidjson::Value& id) -{ - auto mes = responseMessage(message); - mes.setID(id); - return mes; + dest.Key(method_field); + json::toJsonValue(dest, request); + + dest.Key(params_field); + message.toJson(dest); + + dest.EndObject(); + + if (!dest.IsComplete()) + throw std::logic_error{"Invalid JSON tree generated"}; + } + return std::string{buffer.GetString(), buffer.GetSize()}; } -FullMessage* FullMessage::timeoutMessage() + +std::string FullMessage::getResponse(const Message& message, const rapidjson::Value& id) { - auto *full_message = new FullMessage(); + rapidjson::StringBuffer buffer; + { + rapidjson::Writer dest{buffer}; - auto& doc = full_message->doc; - auto& al = full_message->doc.GetAllocator(); + dest.StartObject(); + INSERT_INTO_JSON_OBJECT(dest, jsonrpc, (boost::string_ref{"2.0", 3})); - doc.SetObject(); + dest.Key(id_field); + json::toJsonValue(dest, id); - // required by JSON-RPC 2.0 spec - doc.AddMember("jsonrpc", "2.0", al); + if (message.status == Message::STATUS_OK) + { + dest.Key(result_field); + message.toJson(dest); + } + else + { + cryptonote::rpc::error err; - cryptonote::rpc::error err; + err.error_str = message.status; + err.message = message.error_details; - err.error_str = "RPC request timed out."; - INSERT_INTO_JSON_OBJECT(doc, doc, err, err); + INSERT_INTO_JSON_OBJECT(dest, error, err); + } + dest.EndObject(); - return full_message; + if (!dest.IsComplete()) + throw std::logic_error{"Invalid JSON tree generated"}; + } + return std::string{buffer.GetString(), buffer.GetSize()}; } // convenience functions for bad input std::string BAD_REQUEST(const std::string& request) { - Message fail; - fail.status = Message::STATUS_BAD_REQUEST; - fail.error_details = std::string("\"") + request + "\" is not a valid request."; - - FullMessage fail_response = FullMessage::responseMessage(&fail); - - return fail_response.getJson(); + rapidjson::Value invalid; + return BAD_REQUEST(request, invalid); } -std::string BAD_REQUEST(const std::string& request, rapidjson::Value& id) +std::string BAD_REQUEST(const std::string& request, const rapidjson::Value& id) { Message fail; fail.status = Message::STATUS_BAD_REQUEST; fail.error_details = std::string("\"") + request + "\" is not a valid request."; - - FullMessage fail_response = FullMessage::responseMessage(&fail, id); - - return fail_response.getJson(); + return FullMessage::getResponse(fail, id); } std::string BAD_JSON(const std::string& error_details) { + rapidjson::Value invalid; Message fail; fail.status = Message::STATUS_BAD_JSON; fail.error_details = error_details; - - FullMessage fail_response = FullMessage::responseMessage(&fail); - - return fail_response.getJson(); + return FullMessage::getResponse(fail, invalid); } diff --git a/src/rpc/message.h b/src/rpc/message.h index 2b7b61ab3..4cbc84fe4 100644 --- a/src/rpc/message.h +++ b/src/rpc/message.h @@ -28,27 +28,12 @@ #pragma once -#include "rapidjson/document.h" -#include "rpc/message_data_structs.h" +#include +#include +#include #include -/* I normally hate using macros, but in this case it would be untenably - * verbose to not use a macro. This macro saves the trouble of explicitly - * writing the below if block for every single RPC call. - */ -#define REQ_RESP_TYPES_MACRO( runtime_str, type, reqjson, resp_message_ptr, handler) \ - \ - if (runtime_str == type::name) \ - { \ - type::Request reqvar; \ - type::Response *respvar = new type::Response(); \ - \ - reqvar.fromJson(reqjson); \ - \ - handler(reqvar, *respvar); \ - \ - resp_message_ptr = respvar; \ - } +#include "rpc/message_data_structs.h" namespace cryptonote { @@ -58,6 +43,9 @@ namespace rpc class Message { + virtual void doToJson(rapidjson::Writer& dest) const + {} + public: static const char* STATUS_OK; static const char* STATUS_RETRY; @@ -69,9 +57,9 @@ namespace rpc virtual ~Message() { } - virtual rapidjson::Value toJson(rapidjson::Document& doc) const; + void toJson(rapidjson::Writer& dest) const; - virtual void fromJson(rapidjson::Value& val); + virtual void fromJson(const rapidjson::Value& val); std::string status; std::string error_details; @@ -87,27 +75,18 @@ namespace rpc FullMessage(const std::string& json_string, bool request=false); - std::string getJson(); - std::string getRequestType() const; - rapidjson::Value& getMessage(); + const rapidjson::Value& getMessage() const; rapidjson::Value getMessageCopy(); - rapidjson::Value& getID(); - - void setID(rapidjson::Value& id); + const rapidjson::Value& getID() const; cryptonote::rpc::error getError(); - static FullMessage requestMessage(const std::string& request, Message* message); - static FullMessage requestMessage(const std::string& request, Message* message, rapidjson::Value& id); - - static FullMessage responseMessage(Message* message); - static FullMessage responseMessage(Message* message, rapidjson::Value& id); - - static FullMessage* timeoutMessage(); + static std::string getRequest(const std::string& request, const Message& message, unsigned id); + static std::string getResponse(const Message& message, const rapidjson::Value& id); private: FullMessage() = default; @@ -121,7 +100,7 @@ namespace rpc // convenience functions for bad input std::string BAD_REQUEST(const std::string& request); - std::string BAD_REQUEST(const std::string& request, rapidjson::Value& id); + std::string BAD_REQUEST(const std::string& request, const rapidjson::Value& id); std::string BAD_JSON(const std::string& error_details); -- cgit v1.2.3