From 43286b46e585a575e5b25781f09d6ef8b7563e4b Mon Sep 17 00:00:00 2001 From: Oran Juice Date: Mon, 10 Nov 2014 02:14:09 +0530 Subject: [PATCH] More RPC handlers, more JSON RPC 2.0 compliant. --- src/rpc/json_rpc_handlers.h | 299 ++++++++++++++++++++++++------- src/rpc/json_rpc_http_server.cpp | 5 + src/rpc/json_rpc_http_server.h | 10 ++ 3 files changed, 254 insertions(+), 60 deletions(-) diff --git a/src/rpc/json_rpc_handlers.h b/src/rpc/json_rpc_handlers.h index fc03bb2ad..bbb812084 100644 --- a/src/rpc/json_rpc_handlers.h +++ b/src/rpc/json_rpc_handlers.h @@ -1,4 +1,8 @@ +#ifndef JSON_RPC_HANDLERS_H +#define JSON_RPC_HANDLERS_H + #include "net_skeleton/net_skeleton.h" +#include "json_rpc_http_server.h" #include "common/command_line.h" #include "net/http_server_impl_base.h" #include "cryptonote_core/cryptonote_core.h" @@ -74,9 +78,10 @@ namespace RPC return false; } - void construct_response_string(struct ns_rpc_request *req, rapidjson::Document &response_json, - std::string &response) + void construct_response_string(struct ns_rpc_request *req, rapidjson::Value &result_json, + rapidjson::Document &response_json, std::string &response) { + response_json.SetObject(); rapidjson::Value string_value(rapidjson::kStringType); if (req->id != NULL) { @@ -89,22 +94,45 @@ namespace RPC response_json.AddMember("id", string_value, response_json.GetAllocator()); string_value.SetString(req->method[0].ptr, req->method[0].len); response_json.AddMember("method", string_value, response_json.GetAllocator()); + response_json.AddMember("result", result_json, response_json.GetAllocator()); rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); response_json.Accept(writer); response = buffer.GetString(); } + //------------------------------------------------------------------------------------------------------------------------------ + // equivalent of strstr, but with arbitrary bytes (ie, NULs) + // This does not differentiate between "not found" and "found at offset 0" + uint64_t slow_memmem(const void *start_buff, size_t buflen, const void *pat, size_t patlen) + { + const void *buf = start_buff; + const void *end = (const char*)buf + buflen; + if (patlen > buflen || patlen == 0) + { + return 0; + } + while (buflen > 0 && (buf = memchr(buf,((const char*)pat)[0], buflen - patlen + 1))) + { + if (memcmp(buf,pat,patlen) == 0) + return (const char*)buf - (const char*)start_buff; + buf = (const char*)buf + 1; + buflen = (const char*)end - (const char*)buf; + } + return 0; + } + int getheight(char *buf, int len, struct ns_rpc_request *req) { CHECK_CORE_BUSY(); uint64_t height = core->get_current_blockchain_height(); rapidjson::Document response_json; - response_json.SetObject(); - response_json.AddMember("height", height, response_json.GetAllocator()); - response_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); + rapidjson::Value result_json; + result_json.SetObject(); + result_json.AddMember("height", height, response_json.GetAllocator()); + result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); std::string response; - construct_response_string(req, response_json, response); + construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); return response.length(); @@ -113,22 +141,30 @@ namespace RPC int getblocks(char *buf, int len, struct ns_rpc_request *req) { CHECK_CORE_BUSY(); + if (req->params == NULL) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Parameters missing.", "{}"); + } rapidjson::Document request_json; char request_buf[1000]; - strncpy(request_buf, req->message[0].ptr, req->message[0].len); - request_buf[req->message[0].len] = '\0'; + strncpy(request_buf, req->params[0].ptr, req->params[0].len); + request_buf[req->params[0].len] = '\0'; if (request_json.Parse(request_buf).HasParseError()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Invalid JSON passed"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, + "Invalid JSON passed", "{}"); } if (!request_json.HasMember("start_height") || !request_json["start_height"].IsUint64()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Incorrect start_height"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect start_height", "{}"); } if (!request_json.HasMember("block_ids") || !request_json["block_ids"].IsArray()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Incorrect block_ids"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect block_ids", "{}"); } uint64_t start_height = request_json["start_height"].GetUint(); @@ -140,11 +176,13 @@ namespace RPC crypto::hash hash; if (!it->IsString()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Wrong type in block_ids"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Wrong type in block_ids", "{}"); } if (strlen(it->GetString()) > crypto::HASH_SIZE) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Block ID exceeds length."); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Block ID exceeds length.", "{}"); } strcpy(hash.data, it->GetString()); block_ids.push_back(hash); @@ -156,11 +194,13 @@ namespace RPC if (!core->find_blockchain_supplement(start_height, block_ids, bs, result_current_height, result_start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, + "Failed", "{}"); } rapidjson::Document response_json; - response_json.SetObject(); + rapidjson::Value result_json; + result_json.SetObject(); rapidjson::Value block_json(rapidjson::kArrayType); rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator(); BOOST_FOREACH(auto &b, bs) @@ -181,13 +221,13 @@ namespace RPC block_json.PushBack(this_block, allocator); } - response_json.AddMember("start_height", result_start_height, allocator); - response_json.AddMember("current_height", result_current_height, allocator); - response_json.AddMember("status", CORE_RPC_STATUS_OK, allocator); - response_json.AddMember("blocks", block_json, allocator); + result_json.AddMember("start_height", result_start_height, allocator); + result_json.AddMember("current_height", result_current_height, allocator); + result_json.AddMember("status", CORE_RPC_STATUS_OK, allocator); + result_json.AddMember("blocks", block_json, allocator); std::string response; - construct_response_string(req, response_json, response); + construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); @@ -197,18 +237,25 @@ namespace RPC int gettransactions(char *buf, int len, struct ns_rpc_request *req) { CHECK_CORE_BUSY(); + if (req->params == NULL) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Parameters missing.", "{}"); + } rapidjson::Document request_json; char request_buf[1000]; - strncpy(request_buf, req->message[0].ptr, req->message[0].len); - request_buf[req->message[0].len] = '\0'; + strncpy(request_buf, req->params[0].ptr, req->params[0].len); + request_buf[req->params[0].len] = '\0'; if (request_json.Parse(request_buf).HasParseError()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Invalid JSON passed"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, + "Invalid JSON passed", "{}"); } if (!request_json.HasMember("txs_hashes") || !request_json["txs_hashes"].IsArray()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Incorrect txs_hashes"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect txs_hashes", "{}"); } std::list txs_hashes; @@ -217,7 +264,8 @@ namespace RPC { if (!it->IsString()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Wrong type in txs_hashes"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Wrong type in txs_hashes", "{}"); } txs_hashes.push_back(std::string(it->GetString())); } @@ -227,11 +275,13 @@ namespace RPC cryptonote::blobdata b; if (!string_tools::parse_hexstr_to_binbuff(tx_hex_str, b)) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed to parse hex representation of transaction hash"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Failed to parse hex representation of transaction hash", "{}"); } if (b.size() != sizeof(crypto::hash)) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed, size of data mismatch"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Failed, size of data mismatch", "{}"); } vh.push_back(*reinterpret_cast(b.data())); } @@ -240,11 +290,13 @@ namespace RPC bool r = core->get_transactions(vh, txs, missed_txs); if (!r) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, + "Failed", "{}"); } rapidjson::Document response_json; - response_json.SetObject(); + rapidjson::Value result_json; + result_json.SetObject(); rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator(); rapidjson::Value txs_as_hex(rapidjson::kArrayType); @@ -256,7 +308,7 @@ namespace RPC string_value.SetString(string_blob.c_str(), string_blob.length()); txs_as_hex.PushBack(string_value, allocator); } - response_json.AddMember("txs_as_hex", txs_as_hex, response_json.GetAllocator()); + result_json.AddMember("txs_as_hex", txs_as_hex, response_json.GetAllocator()); rapidjson::Value missed_tx(rapidjson::kArrayType); BOOST_FOREACH(const auto &miss_tx, missed_txs) @@ -266,10 +318,10 @@ namespace RPC string_value.SetString(string_blob.c_str(), string_blob.length()); missed_tx.PushBack(string_value, allocator); } - response_json.AddMember("missed_tx", missed_tx, response_json.GetAllocator()); + result_json.AddMember("missed_tx", missed_tx, response_json.GetAllocator()); std::string response; - construct_response_string(req, response_json, response); + construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); @@ -279,22 +331,30 @@ namespace RPC int startmining(char *buf, int len, struct ns_rpc_request *req) { CHECK_CORE_BUSY(); + if (req->params == NULL) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Parameters missing.", "{}"); + } rapidjson::Document request_json; char request_buf[1000]; - strncpy(request_buf, req->message[0].ptr, req->message[0].len); - request_buf[req->message[0].len] = '\0'; + strncpy(request_buf, req->params[0].ptr, req->params[0].len); + request_buf[req->params[0].len] = '\0'; if (request_json.Parse(request_buf).HasParseError()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Invalid JSON passed"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, + "Invalid JSON passed", "{}"); } if (!request_json.HasMember("miner_address") || !request_json["miner_address"].IsString()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Incorrect miner_address"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect miner_address", "{}"); } if (!request_json.HasMember("threads_count") || !request_json["threads_count"].IsUint64()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Incorrect threads_count"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect threads_count", "{}"); } std::string miner_address = request_json["miner_address"].GetString(); @@ -303,14 +363,16 @@ namespace RPC cryptonote::account_public_address adr; if (!cryptonote::get_account_address_from_str(adr, testnet, miner_address)) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed, wrong address"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Failed, wrong address", "{}"); } boost::thread::attributes attrs; attrs.set_stack_size(THREAD_STACK_SIZE); if (!core->get_miner().start(adr, static_cast(threads_count), attrs)) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed, mining not started"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, + "Failed, mining not started", "{}"); } return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", CORE_RPC_STATUS_OK); } @@ -320,7 +382,8 @@ namespace RPC CHECK_CORE_BUSY(); if (!core->get_miner().stop()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Failed, mining not stopped"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, + "Failed, mining not stopped", "{}"); } return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", CORE_RPC_STATUS_OK); } @@ -329,9 +392,10 @@ namespace RPC { CHECK_CORE_BUSY(); rapidjson::Document response_json; - response_json.SetObject(); + rapidjson::Value result_json; + result_json.SetObject(); bool active = core->get_miner().is_mining(); - response_json.AddMember("active", active, response_json.GetAllocator()); + result_json.AddMember("active", active, response_json.GetAllocator()); if (active) { @@ -339,16 +403,16 @@ namespace RPC uint64_t threads_count = core->get_miner().get_threads_count(); const cryptonote::account_public_address &mining_address = core->get_miner().get_mining_address(); std::string address = cryptonote::get_account_address_as_str(testnet, mining_address); - response_json.AddMember("speed", speed, response_json.GetAllocator()); - response_json.AddMember("threads_count", threads_count, response_json.GetAllocator()); + result_json.AddMember("speed", speed, response_json.GetAllocator()); + result_json.AddMember("threads_count", threads_count, response_json.GetAllocator()); rapidjson::Value string_address(rapidjson::kStringType); string_address.SetString(address.c_str(), address.length()); - response_json.AddMember("address", string_address, response_json.GetAllocator()); + result_json.AddMember("address", string_address, response_json.GetAllocator()); } - response_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); + result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); std::string response; - construct_response_string(req, response_json, response); + construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); @@ -359,12 +423,13 @@ namespace RPC { CHECK_CORE_BUSY(); rapidjson::Document response_json; - response_json.SetObject(); - response_json.AddMember("count", core->get_current_blockchain_height(), response_json.GetAllocator()); - response_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); + rapidjson::Value result_json; + result_json.SetObject(); + result_json.AddMember("count", core->get_current_blockchain_height(), response_json.GetAllocator()); + result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); std::string response; - construct_response_string(req, response_json, response); + construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); @@ -374,34 +439,144 @@ namespace RPC int getblockhash(char *buf, int len, struct ns_rpc_request *req) { CHECK_CORE_BUSY(); + if (req->params == NULL) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Parameters missing.", "{}"); + } rapidjson::Document request_json; char request_buf[1000]; - strncpy(request_buf, req->message[0].ptr, req->message[0].len); - request_buf[req->message[0].len] = '\0'; + strncpy(request_buf, req->params[0].ptr, req->params[0].len); + request_buf[req->params[0].len] = '\0'; if (request_json.Parse(request_buf).HasParseError()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Invalid JSON passed"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, + "Invalid JSON passed", "{}"); } if (!request_json.HasMember("height") || !request_json["height"].IsUint64()) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Incorrect height"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect height", "{}"); } uint64_t height = request_json["height"].GetUint(); if (core->get_current_blockchain_height() <= height) { - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", "Height specified is too big."); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Height specified is too big.", "{}"); } std::string hash = string_tools::pod_to_hex(core->get_block_id_by_height(height)); rapidjson::Document response_json; - response_json.SetObject(); + rapidjson::Value result_json; + result_json.SetObject(); rapidjson::Value string_value(rapidjson::kStringType); string_value.SetString(hash.c_str(), hash.length()); - response_json.AddMember("hash", string_value, response_json.GetAllocator()); - response_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); + result_json.AddMember("hash", string_value, response_json.GetAllocator()); + result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); std::string response; - construct_response_string(req, response_json, response); + construct_response_string(req, result_json, response_json, response); + size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; + strncpy(buf, response.c_str(), copy_length); + return response.length(); + } + + int getblocktemplate(char *buf, int len, struct ns_rpc_request *req) + { + CHECK_CORE_BUSY(); + if (req->params == NULL) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Parameters missing.", "{}"); + } + rapidjson::Document request_json; + char request_buf[1000]; + strncpy(request_buf, req->params[0].ptr, req->params[0].len); + request_buf[req->params[0].len] = '\0'; + + if (request_json.Parse(request_buf).HasParseError()) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, + "Invalid JSON passed", "{}"); + } + + if (!request_json.HasMember("reserve_size") || !request_json["reserve_size"].IsUint64()) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect reserve_size", "{}"); + } + if (!request_json.HasMember("wallet_address") || !request_json["wallet_address"].IsString()) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect wallet_address", "{}"); + } + + uint64_t reserve_size = request_json["reserve_size"].GetUint(); + std::string wallet_address = request_json["wallet_address"].GetString(); + + if (reserve_size > 255) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "To big reserved size, maximum 255", "{}"); + } + + cryptonote::account_public_address acc = AUTO_VAL_INIT(acc); + if (!wallet_address.size() || !cryptonote::get_account_address_from_str(acc, testnet, wallet_address)) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Failed to parse wallet address", "{}"); + } + + cryptonote::block b = AUTO_VAL_INIT(b); + cryptonote::blobdata blob_reserve; + blob_reserve.resize(reserve_size, 0); + + uint64_t difficulty, height, reserved_offset; + if (!core->get_block_template(b, acc, difficulty, height, blob_reserve)) + { + LOG_ERROR("Failed to create block template"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, + "Failed to create block template", "{}"); + } + + cryptonote::blobdata block_blob = t_serializable_object_to_blob(b); + crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(b.miner_tx); + if (tx_pub_key == cryptonote::null_pkey) + { + LOG_ERROR("Failed to tx pub key in coinbase extra"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, + "Failed to create block template", "{}"); + } + + reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); + if (!reserved_offset) + { + LOG_ERROR("Failed to find tx pub key in blockblob"); + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, + "Internal error: failed to create block template", "{}"); + } + + reserved_offset += sizeof(tx_pub_key) + 3; // 3 bytes: tag for TX_EXTRA_TAG_PUBKEY(1 byte), tag for TX_EXTRA_NONCE(1 byte), counter in TX_EXTRA_NONCE(1 byte) + if (reserved_offset + reserve_size > block_blob.size()) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, + "Internal error: failed to create block template", "{}"); + } + cryptonote::blobdata blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob); + + rapidjson::Document response_json; + rapidjson::Value result_json; + result_json.SetObject(); + result_json.AddMember("difficulty", difficulty, response_json.GetAllocator()); + result_json.AddMember("height", height, response_json.GetAllocator()); + result_json.AddMember("reserved_offset", reserved_offset, response_json.GetAllocator()); + rapidjson::Value string_value(rapidjson::kStringType); + string_value.SetString(blocktemplate_blob.c_str(), blocktemplate_blob.length()); + result_json.AddMember("blocktemplate_blob", string_value, response_json.GetAllocator()); + result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); + + std::string response; + construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); return response.length(); @@ -416,6 +591,7 @@ namespace RPC "miningstatus", "getblockcount", "getblockhash", + "getblocktemplate", NULL }; @@ -428,6 +604,7 @@ namespace RPC miningstatus, getblockcount, getblockhash, + getblocktemplate, NULL }; @@ -449,3 +626,5 @@ namespace RPC } } } + +#endif diff --git a/src/rpc/json_rpc_http_server.cpp b/src/rpc/json_rpc_http_server.cpp index 65eba883c..c34c11d3b 100644 --- a/src/rpc/json_rpc_http_server.cpp +++ b/src/rpc/json_rpc_http_server.cpp @@ -4,6 +4,11 @@ namespace RPC { + int Json_rpc_http_server::parse_error = -32700; + int Json_rpc_http_server::invalid_request = -32600; + int Json_rpc_http_server::invalid_params = -32602; + int Json_rpc_http_server::internal_error = -32603; + Json_rpc_http_server::Json_rpc_http_server(const std::string &ip, const std::string &port, void (*ev_handler)(struct ns_connection *nc, int ev, void *ev_data)) { diff --git a/src/rpc/json_rpc_http_server.h b/src/rpc/json_rpc_http_server.h index 4860fccd6..c3a9ffe59 100644 --- a/src/rpc/json_rpc_http_server.h +++ b/src/rpc/json_rpc_http_server.h @@ -1,3 +1,6 @@ +#ifndef JSON_RPC_HTTP_SERVER_H +#define JSON_RPC_HTTP_SERVER_H + #include "net_skeleton/net_skeleton.h" #include #include @@ -20,5 +23,12 @@ namespace RPC ~Json_rpc_http_server(); bool start(); void stop(); + + static int parse_error; + static int invalid_request; + static int invalid_params; + static int internal_error; }; } + +#endif