bootstrap_daemon: proxy configuration support

This commit is contained in:
xiphon 2021-01-19 08:50:12 +00:00 committed by selsta
parent a6df656b4e
commit 52dcc03068
No known key found for this signature in database
GPG Key ID: 2EA0A99A8B07AE5E
9 changed files with 125 additions and 27 deletions

View File

@ -887,16 +887,66 @@ bool t_command_parser_executor::check_blockchain_pruning(const std::vector<std::
bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::string>& args)
{
const size_t args_count = args.size();
if (args_count < 1 || args_count > 3)
struct parsed_t
{
std::string address;
std::string user;
std::string password;
std::string proxy;
};
boost::optional<parsed_t> parsed = [&args]() -> boost::optional<parsed_t> {
const size_t args_count = args.size();
if (args_count == 0)
{
return {};
}
if (args[0] == "auto")
{
if (args_count == 1)
{
return {{args[0], "", "", ""}};
}
if (args_count == 2)
{
return {{args[0], "", "", args[1]}};
}
}
else if (args[0] == "none")
{
if (args_count == 1)
{
return {{"", "", "", ""}};
}
}
else
{
if (args_count == 1)
{
return {{args[0], "", "", ""}};
}
if (args_count == 2)
{
return {{args[0], "", "", args[1]}};
}
if (args_count == 3)
{
return {{args[0], args[1], args[2], ""}};
}
if (args_count == 4)
{
return {{args[0], args[1], args[2], args[3]}};
}
}
return {};
}();
if (!parsed)
{
return false;
}
return m_executor.set_bootstrap_daemon(
args[0] != "none" ? args[0] : std::string(),
args_count > 1 ? args[1] : std::string(),
args_count > 2 ? args[2] : std::string());
return m_executor.set_bootstrap_daemon(parsed->address, parsed->user, parsed->password, parsed->proxy);
}
bool t_command_parser_executor::flush_cache(const std::vector<std::string>& args)

View File

@ -324,7 +324,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"set_bootstrap_daemon"
, std::bind(&t_command_parser_executor::set_bootstrap_daemon, &m_parser, p::_1)
, "set_bootstrap_daemon (auto | none | host[:port] [username] [password])"
, "set_bootstrap_daemon (auto | none | host[:port] [username] [password]) [proxy_ip:proxy_port]"
, "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced.\n"
"Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
);

View File

@ -2405,7 +2405,8 @@ bool t_rpc_command_executor::check_blockchain_pruning()
bool t_rpc_command_executor::set_bootstrap_daemon(
const std::string &address,
const std::string &username,
const std::string &password)
const std::string &password,
const std::string &proxy)
{
cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req;
cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res;
@ -2414,6 +2415,7 @@ bool t_rpc_command_executor::set_bootstrap_daemon(
req.address = address;
req.username = username;
req.password = password;
req.proxy = proxy;
if (m_is_rpc)
{

View File

@ -168,7 +168,8 @@ public:
bool set_bootstrap_daemon(
const std::string &address,
const std::string &username,
const std::string &password);
const std::string &password,
const std::string &proxy);
bool rpc_payments();

View File

@ -7,6 +7,7 @@
#include "crypto/crypto.h"
#include "cryptonote_core/cryptonote_core.h"
#include "misc_log_ex.h"
#include "net/parse.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc.bootstrap_daemon"
@ -16,19 +17,23 @@ namespace cryptonote
bootstrap_daemon::bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes,
bool rpc_payment_enabled)
bool rpc_payment_enabled,
const std::string &proxy)
: m_selector(new bootstrap_node::selector_auto(std::move(get_public_nodes)))
, m_rpc_payment_enabled(rpc_payment_enabled)
{
set_proxy(proxy);
}
bootstrap_daemon::bootstrap_daemon(
const std::string &address,
boost::optional<epee::net_utils::http::login> credentials,
bool rpc_payment_enabled)
bool rpc_payment_enabled,
const std::string &proxy)
: m_selector(nullptr)
, m_rpc_payment_enabled(rpc_payment_enabled)
{
set_proxy(proxy);
if (!set_server(address, std::move(credentials)))
{
throw std::runtime_error("invalid bootstrap daemon address or credentials");
@ -78,6 +83,18 @@ namespace cryptonote
return success;
}
void bootstrap_daemon::set_proxy(const std::string &address)
{
if (!address.empty() && !net::get_tcp_endpoint(address))
{
throw std::runtime_error("invalid proxy address format");
}
if (!m_http_client.set_proxy(address))
{
throw std::runtime_error("failed to set proxy address");
}
}
bool bootstrap_daemon::set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials /* = boost::none */)
{
if (!m_http_client.set_server(address, credentials))

View File

@ -8,7 +8,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/utility/string_ref.hpp>
#include "net/http_client.h"
#include "net/http.h"
#include "storages/http_abstract_invoke.h"
#include "bootstrap_node_selector.h"
@ -21,11 +21,13 @@ namespace cryptonote
public:
bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes,
bool rpc_payment_enabled);
bool rpc_payment_enabled,
const std::string &proxy);
bootstrap_daemon(
const std::string &address,
boost::optional<epee::net_utils::http::login> credentials,
bool rpc_payment_enabled);
bool rpc_payment_enabled,
const std::string &proxy);
std::string address() const noexcept;
boost::optional<std::pair<uint64_t, uint64_t>> get_height();
@ -72,12 +74,14 @@ namespace cryptonote
return handle_result(result, result_struct.status);
}
void set_proxy(const std::string &address);
private:
bool set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials = boost::none);
bool switch_server_if_needed();
private:
epee::net_utils::http::http_simple_client m_http_client;
net::http::client m_http_client;
const bool m_rpc_payment_enabled;
const std::unique_ptr<bootstrap_node::selector> m_selector;
boost::mutex m_selector_mutex;

View File

@ -154,6 +154,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_restricted_rpc);
command_line::add_arg(desc, arg_bootstrap_daemon_address);
command_line::add_arg(desc, arg_bootstrap_daemon_login);
command_line::add_arg(desc, arg_bootstrap_daemon_proxy);
cryptonote::rpc_args::init_options(desc, true);
command_line::add_arg(desc, arg_rpc_payment_address);
command_line::add_arg(desc, arg_rpc_payment_difficulty);
@ -172,7 +173,10 @@ namespace cryptonote
, m_rpc_payment_allow_free_loopback(false)
{}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const std::string &username_password)
bool core_rpc_server::set_bootstrap_daemon(
const std::string &address,
const std::string &username_password,
const std::string &proxy)
{
boost::optional<epee::net_utils::http::login> credentials;
const auto loc = username_password.find(':');
@ -180,7 +184,7 @@ namespace cryptonote
{
credentials = epee::net_utils::http::login(username_password.substr(0, loc), username_password.substr(loc + 1));
}
return set_bootstrap_daemon(address, credentials);
return set_bootstrap_daemon(address, credentials, proxy);
}
//------------------------------------------------------------------------------------------------------------------------------
std::map<std::string, bool> core_rpc_server::get_public_nodes(uint32_t credits_per_hash_threshold/* = 0*/)
@ -217,7 +221,10 @@ namespace cryptonote
return result;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials)
bool core_rpc_server::set_bootstrap_daemon(
const std::string &address,
const boost::optional<epee::net_utils::http::login> &credentials,
const std::string &proxy)
{
boost::unique_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
@ -233,11 +240,11 @@ namespace cryptonote
auto get_nodes = [this]() {
return get_public_nodes(credits_per_hash_threshold);
};
m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled));
m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled, proxy));
}
else
{
m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled));
m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled, proxy));
}
m_should_use_bootstrap_daemon = m_bootstrap_daemon.get() != nullptr;
@ -318,8 +325,10 @@ namespace cryptonote
MWARNING("The RPC server is accessible from the outside, but no RPC payment was setup. RPC access will be free for all.");
}
if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
command_line::get_arg(vm, arg_bootstrap_daemon_login)))
if (!set_bootstrap_daemon(
command_line::get_arg(vm, arg_bootstrap_daemon_address),
command_line::get_arg(vm, arg_bootstrap_daemon_login),
command_line::get_arg(vm, arg_bootstrap_daemon_proxy)))
{
MFATAL("Failed to parse bootstrap daemon address");
return false;
@ -1596,15 +1605,15 @@ namespace cryptonote
{
credentials = epee::net_utils::http::login(req.username, req.password);
}
if (set_bootstrap_daemon(req.address, credentials))
if (set_bootstrap_daemon(req.address, credentials, req.proxy))
{
res.status = CORE_RPC_STATUS_OK;
}
else
{
res.status = "Failed to set bootstrap daemon";
}
}
return true;
}
@ -3386,6 +3395,12 @@ namespace cryptonote
, ""
};
const command_line::arg_descriptor<std::string> core_rpc_server::arg_bootstrap_daemon_proxy = {
"bootstrap-daemon-proxy"
, "<ip>:<port> socks proxy to use for bootstrap daemon connections"
, ""
};
const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_payment_address = {
"rpc-payment-address"
, "Restrict RPC to clients sending micropayment to this address"

View File

@ -72,6 +72,7 @@ namespace cryptonote
static const command_line::arg_descriptor<bool> arg_rpc_ssl_allow_any_cert;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_login;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_proxy;
static const command_line::arg_descriptor<std::string> arg_rpc_payment_address;
static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_difficulty;
static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_credits;
@ -270,8 +271,14 @@ private:
uint64_t get_block_reward(const block& blk);
bool fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash);
std::map<std::string, bool> get_public_nodes(uint32_t credits_per_hash_threshold = 0);
bool set_bootstrap_daemon(const std::string &address, const std::string &username_password);
bool set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials);
bool set_bootstrap_daemon(
const std::string &address,
const std::string &username_password,
const std::string &proxy);
bool set_bootstrap_daemon(
const std::string &address,
const boost::optional<epee::net_utils::http::login> &credentials,
const std::string &proxy);
enum invoke_http_mode { JON, BIN, JON_RPC };
template <typename COMMAND_TYPE>
bool use_bootstrap_daemon_if_necessary(const invoke_http_mode &mode, const std::string &command_name, const typename COMMAND_TYPE::request& req, typename COMMAND_TYPE::response& res, bool &r);

View File

@ -1663,11 +1663,13 @@ namespace cryptonote
std::string address;
std::string username;
std::string password;
std::string proxy;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
KV_SERIALIZE(username)
KV_SERIALIZE(password)
KV_SERIALIZE(proxy)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;