diff --git a/src/rpc/json_rpc_handlers.h b/src/rpc/json_rpc_handlers.h index bbb812084..5975a335e 100644 --- a/src/rpc/json_rpc_handlers.h +++ b/src/rpc/json_rpc_handlers.h @@ -582,6 +582,60 @@ namespace RPC return response.length(); } + int submitblock(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("block") || !request_json["block"].IsString()) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, + "Incorrect block", "{}"); + } + + std::string string_blockblob = request_json["block"].GetString(); + cryptonote::blobdata blockblob; + if (!string_tools::parse_hexstr_to_binbuff(string_blockblob, blockblob)) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, + "Incorrect block", "{}"); + } + // Fixing of high orphan issue for most pools + cryptonote::block b = AUTO_VAL_INIT(b); + if (!parse_and_validate_block_from_blob(blockblob, b)) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, + "Wrong block blob", "{}"); + } + // Fix from Boolberry neglects to check block + // size, do that with the function below + if (!core->check_incoming_block_size(blockblob)) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, + "Block blob size is too big, rejecting block", "{}"); + } + if (!core->handle_block_found(b)) + { + return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, + "Block not accepted.", "{}"); + } + + return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", CORE_RPC_STATUS_OK); + } + const char *method_names[] = { "getheight", "getblocks", @@ -592,6 +646,7 @@ namespace RPC "getblockcount", "getblockhash", "getblocktemplate", + "submitblock", NULL }; @@ -605,6 +660,7 @@ namespace RPC getblockcount, getblockhash, getblocktemplate, + submitblock, NULL }; diff --git a/src/rpc/json_rpc_http_server.cpp b/src/rpc/json_rpc_http_server.cpp index c34c11d3b..a27dd49d4 100644 --- a/src/rpc/json_rpc_http_server.cpp +++ b/src/rpc/json_rpc_http_server.cpp @@ -1,7 +1,16 @@ +/*! + * \file json_rpc_http_server.h + * \brief Header for Json_rpc_http_server class + */ + #include "json_rpc_http_server.h" #include +/*! + * \namespace RPC + * \brief RPC related utilities + */ namespace RPC { int Json_rpc_http_server::parse_error = -32700; @@ -9,6 +18,12 @@ namespace RPC int Json_rpc_http_server::invalid_params = -32602; int Json_rpc_http_server::internal_error = -32603; + /** + * \brief Constructor + * \param ip IP address to bind + * \param port Port number to bind + * \param ev_handler Event handler function pointer + */ 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)) { @@ -18,11 +33,18 @@ namespace RPC m_ev_handler = ev_handler; } + /** + * \brief Destructor + */ Json_rpc_http_server::~Json_rpc_http_server() { stop(); } + /*! + * \brief Starts the server + * \return True if start was successful + */ bool Json_rpc_http_server::start() { m_is_running = true; @@ -33,17 +55,25 @@ namespace RPC return false; } ns_set_protocol_http_websocket(nc); + // Start a new thread so it doesn't block. server_thread = new boost::thread(&Json_rpc_http_server::poll, this); return true; } + /*! + * \brief Repeated loops processing requests if any. + */ void Json_rpc_http_server::poll() { + // Loop until the server is running and poll. while (m_is_running) { ns_mgr_poll(&mgr, 1000); } } + /*! + * \brief Stops the server + */ void Json_rpc_http_server::stop() { m_is_running = false; diff --git a/src/rpc/json_rpc_http_server.h b/src/rpc/json_rpc_http_server.h index c3a9ffe59..b69a2f574 100644 --- a/src/rpc/json_rpc_http_server.h +++ b/src/rpc/json_rpc_http_server.h @@ -1,3 +1,8 @@ +/*! + * \file json_rpc_http_server.h + * \brief Header for Json_rpc_http_server class + */ + #ifndef JSON_RPC_HTTP_SERVER_H #define JSON_RPC_HTTP_SERVER_H @@ -5,29 +10,62 @@ #include #include +/*! + * \namespace RPC + * \brief RPC related utilities + */ namespace RPC { + /*! + * \class Json_rpc_http_server + * \brief JSON HTTP RPC Server implemented with net_skeleton (aka fossa). + * + * Provides a higher level interface to C-like net_skeleton. + */ class Json_rpc_http_server { - struct ns_mgr mgr; - struct ns_connection *nc; - boost::thread *server_thread; + struct ns_mgr mgr; /*!< Connection manager */ + struct ns_connection *nc; /*!< Connection pointer */ + boost::thread *server_thread; /*!< Server runs on this thread */ + /*! + * \brief Repeated loops processing requests if any. + */ void poll(); - std::string m_ip; - std::string m_port; - bool m_is_running; - void (*m_ev_handler)(struct ns_connection *nc, int ev, void *ev_data); + std::string m_ip; /*!< IP address where its listening */ + std::string m_port; /*!< Port where its listening */ + bool m_is_running; /*!< Whether the server is currently running */ + void (*m_ev_handler)(struct ns_connection *nc, int ev, void *ev_data); /*!< Server event handler function pointer */ public: + + /** + * \brief Constructor + * \param ip IP address to bind + * \param port Port number to bind + * \param ev_handler Event handler function pointer + */ Json_rpc_http_server(const std::string &ip, const std::string &port, void (*ev_handler)(struct ns_connection *nc, int ev, void *ev_data)); + + /** + * \brief Destructor + */ ~Json_rpc_http_server(); + + /*! + * \brief Starts the server + * \return True if start was successful + */ bool start(); + + /*! + * \brief Stops the server + */ void stop(); - static int parse_error; - static int invalid_request; - static int invalid_params; - static int internal_error; + static int parse_error; /*!< JSON request passed couldn't be parsed */ + static int invalid_request; /*!< JSON request invalid */ + static int invalid_params; /*!< JSON request had faulty/missing params */ + static int internal_error; /*!< JSON request resulted in an internal error */ }; }