2019-08-27 12:01:49 +00:00
|
|
|
#include "bootstrap_daemon.h"
|
|
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
2020-02-26 12:37:28 +00:00
|
|
|
#include <boost/thread/locks.hpp>
|
|
|
|
|
2019-08-27 12:01:49 +00:00
|
|
|
#include "crypto/crypto.h"
|
|
|
|
#include "cryptonote_core/cryptonote_core.h"
|
|
|
|
#include "misc_log_ex.h"
|
2021-01-19 08:50:12 +00:00
|
|
|
#include "net/parse.h"
|
2019-08-27 12:01:49 +00:00
|
|
|
|
|
|
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
|
|
|
#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc.bootstrap_daemon"
|
|
|
|
|
|
|
|
namespace cryptonote
|
|
|
|
{
|
|
|
|
|
2020-02-26 12:37:28 +00:00
|
|
|
bootstrap_daemon::bootstrap_daemon(
|
|
|
|
std::function<std::map<std::string, bool>()> get_public_nodes,
|
2021-01-19 08:50:12 +00:00
|
|
|
bool rpc_payment_enabled,
|
|
|
|
const std::string &proxy)
|
2020-02-26 12:37:28 +00:00
|
|
|
: m_selector(new bootstrap_node::selector_auto(std::move(get_public_nodes)))
|
|
|
|
, m_rpc_payment_enabled(rpc_payment_enabled)
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
2021-01-19 08:50:12 +00:00
|
|
|
set_proxy(proxy);
|
2019-08-27 12:01:49 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 12:37:28 +00:00
|
|
|
bootstrap_daemon::bootstrap_daemon(
|
|
|
|
const std::string &address,
|
|
|
|
boost::optional<epee::net_utils::http::login> credentials,
|
2021-01-19 08:50:12 +00:00
|
|
|
bool rpc_payment_enabled,
|
|
|
|
const std::string &proxy)
|
2020-02-26 12:37:28 +00:00
|
|
|
: m_selector(nullptr)
|
|
|
|
, m_rpc_payment_enabled(rpc_payment_enabled)
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
2021-01-19 08:50:12 +00:00
|
|
|
set_proxy(proxy);
|
2020-02-26 12:37:28 +00:00
|
|
|
if (!set_server(address, std::move(credentials)))
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
|
|
|
throw std::runtime_error("invalid bootstrap daemon address or credentials");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string bootstrap_daemon::address() const noexcept
|
|
|
|
{
|
|
|
|
const auto& host = m_http_client.get_host();
|
|
|
|
if (host.empty())
|
|
|
|
{
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
return host + ":" + m_http_client.get_port();
|
|
|
|
}
|
|
|
|
|
2020-11-17 23:15:36 +00:00
|
|
|
boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon::get_height()
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
2020-11-17 23:15:36 +00:00
|
|
|
cryptonote::COMMAND_RPC_GET_INFO::request req;
|
|
|
|
cryptonote::COMMAND_RPC_GET_INFO::response res;
|
2019-08-27 12:01:49 +00:00
|
|
|
|
2020-11-17 23:15:36 +00:00
|
|
|
if (!invoke_http_json("/getinfo", req, res))
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
|
|
|
return boost::none;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res.status != CORE_RPC_STATUS_OK)
|
|
|
|
{
|
|
|
|
return boost::none;
|
|
|
|
}
|
|
|
|
|
2020-11-17 23:15:36 +00:00
|
|
|
return {{res.height, res.target_height}};
|
2019-08-27 12:01:49 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 12:37:28 +00:00
|
|
|
bool bootstrap_daemon::handle_result(bool success, const std::string &status)
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
2020-02-26 12:37:28 +00:00
|
|
|
const bool failed = !success || (!m_rpc_payment_enabled && status == CORE_RPC_STATUS_PAYMENT_REQUIRED);
|
|
|
|
if (failed && m_selector)
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
2020-02-26 12:37:28 +00:00
|
|
|
const std::string current_address = address();
|
2019-08-27 12:01:49 +00:00
|
|
|
m_http_client.disconnect();
|
2020-02-26 12:37:28 +00:00
|
|
|
|
|
|
|
const boost::unique_lock<boost::mutex> lock(m_selector_mutex);
|
|
|
|
m_selector->handle_result(current_address, !failed);
|
2019-08-27 12:01:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2021-01-19 08:50:12 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 12:01:49 +00:00
|
|
|
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))
|
|
|
|
{
|
|
|
|
MERROR("Failed to set bootstrap daemon address " << address);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
MINFO("Changed bootstrap daemon address to " << address);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool bootstrap_daemon::switch_server_if_needed()
|
|
|
|
{
|
2020-02-26 12:37:28 +00:00
|
|
|
if (m_http_client.is_connected() || !m_selector)
|
2019-08-27 12:01:49 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-02-26 12:37:28 +00:00
|
|
|
boost::optional<bootstrap_node::node_info> node;
|
|
|
|
{
|
|
|
|
const boost::unique_lock<boost::mutex> lock(m_selector_mutex);
|
|
|
|
node = m_selector->next_node();
|
|
|
|
}
|
|
|
|
if (node) {
|
|
|
|
return set_server(node->address, node->credentials);
|
2019-08-27 12:01:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|