diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index cf7d5f8ab..f8acf1357 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -60,7 +60,7 @@ private: public: t_core core; t_p2p p2p; - t_rpc rpc; + std::vector> rpcs; t_internals( boost::program_options::variables_map const & vm @@ -68,11 +68,22 @@ public: : core{vm} , protocol{vm, core} , p2p{vm, protocol} - , rpc{vm, core, p2p} { // Handle circular dependencies protocol.set_p2p_endpoint(p2p.get()); core.set_protocol(protocol.get()); + + const auto testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + const auto restricted = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_restricted_rpc); + const auto main_rpc_port = command_line::get_arg(vm, testnet ? cryptonote::core_rpc_server::arg_testnet_rpc_bind_port : cryptonote::core_rpc_server::arg_rpc_bind_port); + rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet, main_rpc_port, "core"}); + + auto restricted_rpc_port_arg = testnet ? cryptonote::core_rpc_server::arg_testnet_rpc_restricted_bind_port : cryptonote::core_rpc_server::arg_rpc_restricted_bind_port; + if(!command_line::is_arg_defaulted(vm, restricted_rpc_port_arg)) + { + auto restricted_rpc_port = command_line::get_arg(vm, restricted_rpc_port_arg); + rpcs.emplace_back(new t_rpc{vm, core, p2p, true, testnet, restricted_rpc_port, "restricted"}); + } } }; @@ -135,14 +146,15 @@ bool t_daemon::run(bool interactive) { if (!mp_internals->core.run()) return false; - mp_internals->rpc.run(); - std::unique_ptr rpc_commands; + for(auto& rpc: mp_internals->rpcs) + rpc->run(); - if (interactive) + std::unique_ptr rpc_commands; + if (interactive && mp_internals->rpcs.size()) { // The first three variables are not used when the fourth is false - rpc_commands.reset(new daemonize::t_command_server(0, 0, boost::none, false, mp_internals->rpc.get_server())); + rpc_commands.reset(new daemonize::t_command_server(0, 0, boost::none, false, mp_internals->rpcs.front()->get_server())); rpc_commands->start_handling(std::bind(&daemonize::t_daemon::stop_p2p, this)); } @@ -154,12 +166,11 @@ bool t_daemon::run(bool interactive) LOG_ERROR(std::string("Failed to add TCP Socket (") + zmq_rpc_bind_address + ":" + zmq_rpc_bind_port + ") to ZMQ RPC Server"); - if (interactive) - { + if (rpc_commands) rpc_commands->stop_handling(); - } - mp_internals->rpc.stop(); + for(auto& rpc : mp_internals->rpcs) + rpc->stop(); return false; } @@ -173,13 +184,12 @@ bool t_daemon::run(bool interactive) mp_internals->p2p.run(); // blocks until p2p goes down if (rpc_commands) - { rpc_commands->stop_handling(); - } zmq_server.stop(); - mp_internals->rpc.stop(); + for(auto& rpc : mp_internals->rpcs) + rpc->stop(); mp_internals->core.get().get_miner().stop(); MGINFO("Node stopped."); return true; @@ -204,7 +214,9 @@ void t_daemon::stop() } mp_internals->core.get().get_miner().stop(); mp_internals->p2p.stop(); - mp_internals->rpc.stop(); + for(auto& rpc : mp_internals->rpcs) + rpc->stop(); + mp_internals.reset(nullptr); // Ensure resources are cleaned up before we return } diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h index 0ecfdd120..9b7438053 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -47,35 +47,41 @@ public: } private: cryptonote::core_rpc_server m_server; + const std::string m_description; public: t_rpc( boost::program_options::variables_map const & vm , t_core & core , t_p2p & p2p + , const bool restricted + , const bool testnet + , const std::string & port + , const std::string & description ) - : m_server{core.get(), p2p.get()} + : m_server{core.get(), p2p.get()}, m_description{description} { - MGINFO("Initializing core rpc server..."); - if (!m_server.init(vm)) + MGINFO("Initializing " << m_description << " rpc server..."); + + if (!m_server.init(vm, restricted, testnet, port)) { - throw std::runtime_error("Failed to initialize core rpc server."); + throw std::runtime_error("Failed to initialize " + m_description + " rpc server."); } - MGINFO("Core rpc server initialized OK on port: " << m_server.get_binded_port()); + MGINFO(m_description << " rpc server initialized OK on port: " << m_server.get_binded_port()); } void run() { - MGINFO("Starting core rpc server..."); + MGINFO("Starting " << m_description << " rpc server..."); if (!m_server.run(2, false)) { - throw std::runtime_error("Failed to start core rpc server."); + throw std::runtime_error("Failed to start " + m_description + " rpc server."); } - MGINFO("Core rpc server started ok"); + MGINFO(m_description << " rpc server started ok"); } void stop() { - MGINFO("Stopping core rpc server..."); + MGINFO("Stopping " << m_description << " rpc server..."); m_server.send_stop_signal(); m_server.timed_wait_server_stop(5000); } @@ -87,11 +93,11 @@ public: ~t_rpc() { - MGINFO("Deinitializing rpc server..."); + MGINFO("Deinitializing " << m_description << " rpc server..."); try { m_server.deinit(); } catch (...) { - MERROR("Failed to deinitialize rpc server..."); + MERROR("Failed to deinitialize " << m_description << " rpc server..."); } } }; diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 6e7fb7e8e..1a5e928a8 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -68,7 +68,9 @@ namespace cryptonote void core_rpc_server::init_options(boost::program_options::options_description& desc) { command_line::add_arg(desc, arg_rpc_bind_port); + command_line::add_arg(desc, arg_rpc_restricted_bind_port); command_line::add_arg(desc, arg_testnet_rpc_bind_port); + command_line::add_arg(desc, arg_testnet_rpc_restricted_bind_port); command_line::add_arg(desc, arg_restricted_rpc); cryptonote::rpc_args::init_options(desc); } @@ -83,21 +85,21 @@ namespace cryptonote //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::init( const boost::program_options::variables_map& vm + , const bool restricted + , const bool testnet + , const std::string& port ) { - m_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + m_restricted = restricted; + m_testnet = testnet; m_net_server.set_threads_prefix("RPC"); - auto p2p_bind_arg = m_testnet ? arg_testnet_rpc_bind_port : arg_rpc_bind_port; - auto rpc_config = cryptonote::rpc_args::process(vm); if (!rpc_config) return false; - m_restricted = command_line::get_arg(vm, arg_restricted_rpc); - boost::optional http_login{}; - std::string port = command_line::get_arg(vm, p2p_bind_arg); + if (rpc_config->login) http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password()); @@ -1780,12 +1782,24 @@ namespace cryptonote , std::to_string(config::RPC_DEFAULT_PORT) }; + const command_line::arg_descriptor core_rpc_server::arg_rpc_restricted_bind_port = { + "rpc-restricted-bind-port" + , "Port for restricted RPC server" + , "" + }; + const command_line::arg_descriptor core_rpc_server::arg_testnet_rpc_bind_port = { "testnet-rpc-bind-port" , "Port for testnet RPC server" , std::to_string(config::testnet::RPC_DEFAULT_PORT) }; + const command_line::arg_descriptor core_rpc_server::arg_testnet_rpc_restricted_bind_port = { + "testnet-rpc-restricted-bind-port" + , "Port for testnet restricted RPC server" + , "" + }; + const command_line::arg_descriptor core_rpc_server::arg_restricted_rpc = { "restricted-rpc" , "Restrict RPC to view only commands and do not return privacy sensitive data in RPC calls" diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 7f252258c..bf4371a4e 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -53,7 +53,9 @@ namespace cryptonote public: static const command_line::arg_descriptor arg_rpc_bind_port; + static const command_line::arg_descriptor arg_rpc_restricted_bind_port; static const command_line::arg_descriptor arg_testnet_rpc_bind_port; + static const command_line::arg_descriptor arg_testnet_rpc_restricted_bind_port; static const command_line::arg_descriptor arg_restricted_rpc; typedef epee::net_utils::connection_context_base connection_context; @@ -65,7 +67,10 @@ namespace cryptonote static void init_options(boost::program_options::options_description& desc); bool init( - const boost::program_options::variables_map& vm + const boost::program_options::variables_map& vm, + const bool restricted, + const bool testnet, + const std::string& port ); bool is_testnet() const { return m_testnet; }