Provide last error from http client to UI

This commit is contained in:
Lee Clagett 2020-12-02 19:07:02 -05:00 committed by Lee *!* Clagett
parent 059028a30a
commit 5736862baf
13 changed files with 109 additions and 93 deletions

View file

@ -25,6 +25,7 @@
#pragma once #pragma once
#include <boost/system/error_code.hpp>
#include <string> #include <string>
#include <boost/optional/optional.hpp> #include <boost/optional/optional.hpp>
#include "http_auth.h" #include "http_auth.h"
@ -69,6 +70,7 @@ namespace http
virtual bool connect(std::chrono::milliseconds timeout) = 0; virtual bool connect(std::chrono::milliseconds timeout) = 0;
virtual bool disconnect() = 0; virtual bool disconnect() = 0;
virtual bool is_connected(bool *ssl = NULL) = 0; virtual bool is_connected(bool *ssl = NULL) = 0;
virtual boost::system::error_code last_error();
virtual bool invoke(const boost::string_ref uri, const boost::string_ref method, const boost::string_ref body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0; virtual bool invoke(const boost::string_ref uri, const boost::string_ref method, const boost::string_ref body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
virtual bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0; virtual bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
virtual uint64_t get_bytes_sent() const = 0; virtual uint64_t get_bytes_sent() const = 0;

View file

@ -135,7 +135,7 @@ class connection_basic { // not-templated base class for rapid developmet of som
bool handshake(boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer = {}) bool handshake(boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer = {})
{ {
//m_state != nullptr verified in constructor //m_state != nullptr verified in constructor
return m_state->ssl_options().handshake(socket_, type, buffer); return !bool(m_state->ssl_options().handshake(socket_, type, buffer));
} }
template<typename MutableBufferSequence, typename ReadHandler> template<typename MutableBufferSequence, typename ReadHandler>

View file

@ -161,6 +161,12 @@ namespace net_utils
return m_net_client.is_connected(ssl); return m_net_client.is_connected(ssl);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
boost::system::error_code last_error() override final
{
CRITICAL_REGION_LOCAL(m_lock);
return m_net_client.last_error();
}
//---------------------------------------------------------------------------
virtual bool handle_target_data(std::string& piece_of_transfer) override virtual bool handle_target_data(std::string& piece_of_transfer) override
{ {
CRITICAL_REGION_LOCAL(m_lock); CRITICAL_REGION_LOCAL(m_lock);

View file

@ -63,15 +63,6 @@ namespace net_utils
class blocked_mode_client class blocked_mode_client
{ {
enum try_connect_result_t
{
CONNECT_SUCCESS,
CONNECT_FAILURE,
CONNECT_NO_SSL,
};
struct handler_obj struct handler_obj
{ {
handler_obj(boost::system::error_code& error, size_t& bytes_transferred):ref_error(error), ref_bytes_transferred(bytes_transferred) handler_obj(boost::system::error_code& error, size_t& bytes_transferred):ref_error(error), ref_bytes_transferred(bytes_transferred)
@ -91,6 +82,13 @@ namespace net_utils
} }
}; };
static boost::system::error_code guarantee_error(const boost::system::error_code error)
{
if (error)
return error;
return make_error_code(boost::system::errc::not_connected);
}
public: public:
inline inline
blocked_mode_client() : blocked_mode_client() :
@ -99,7 +97,7 @@ namespace net_utils
m_ssl_socket(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service, m_ctx)), m_ssl_socket(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service, m_ctx)),
m_connector(direct_connect{}), m_connector(direct_connect{}),
m_ssl_options(epee::net_utils::ssl_support_t::e_ssl_support_autodetect), m_ssl_options(epee::net_utils::ssl_support_t::e_ssl_support_autodetect),
m_connected(false), m_stream_error(make_error_code(boost::system::errc::not_connected)),
m_deadline(m_io_service, std::chrono::steady_clock::time_point::max()), m_deadline(m_io_service, std::chrono::steady_clock::time_point::max()),
m_shutdowned(false), m_shutdowned(false),
m_bytes_sent(0), m_bytes_sent(0),
@ -142,7 +140,7 @@ namespace net_utils
} }
inline inline
try_connect_result_t try_connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout) boost::system::error_code try_connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout)
{ {
m_deadline.expires_from_now(timeout); m_deadline.expires_from_now(timeout);
boost::unique_future<boost::asio::ip::tcp::socket> connection = m_connector(addr, port, m_deadline); boost::unique_future<boost::asio::ip::tcp::socket> connection = m_connector(addr, port, m_deadline);
@ -159,79 +157,65 @@ namespace net_utils
m_deadline.cancel(); m_deadline.cancel();
if (m_ssl_socket->next_layer().is_open()) if (m_ssl_socket->next_layer().is_open())
{ {
m_connected = true; boost::system::error_code error{};
m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
// SSL Options // SSL Options
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
{ {
if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout)) if ((error = m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout)))
{ {
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) MWARNING("Failed to establish SSL connection");
{ boost::system::error_code ignored_ec;
boost::system::error_code ignored_ec; m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); m_ssl_socket->next_layer().close();
m_ssl_socket->next_layer().close();
m_connected = false;
return CONNECT_NO_SSL;
}
else
{
MWARNING("Failed to establish SSL connection");
m_connected = false;
return CONNECT_FAILURE;
}
} }
} }
return CONNECT_SUCCESS; return error;
}else
{
MWARNING("Some problems at connect, expected open socket");
return CONNECT_FAILURE;
} }
MWARNING("Some problems at connect, expected open socket");
return boost::asio::error::not_connected;
} }
inline inline
bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout) bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout)
{ {
m_connected = false;
try try
{ {
m_ssl_socket->next_layer().close(); disconnect();
// Set SSL options // Set SSL options
// disable sslv2 // disable sslv2
m_ssl_socket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service, m_ctx)); m_ssl_socket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service, m_ctx));
// Get a list of endpoints corresponding to the server name. boost::system::error_code error = try_connect(addr, port, timeout);
if (error && error != boost::asio::error::not_connected && m_ssl_options.support == ssl_support_t::e_ssl_support_autodetect)
try_connect_result_t try_connect_result = try_connect(addr, port, timeout);
if (try_connect_result == CONNECT_FAILURE)
return false;
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
{ {
if (try_connect_result == CONNECT_NO_SSL) MERROR("SSL handshake failed on an autodetect connection, reconnecting without SSL");
{ m_ssl_options.support = ssl_support_t::e_ssl_support_disabled;
MERROR("SSL handshake failed on an autodetect connection, reconnecting without SSL"); error = try_connect(addr, port, timeout);
m_ssl_options.support = epee::net_utils::ssl_support_t::e_ssl_support_disabled;
if (try_connect(addr, port, timeout) != CONNECT_SUCCESS)
return false;
}
} }
m_stream_error = error;
} }
catch(const boost::system::system_error& er) catch (const boost::system::system_error& er)
{ {
m_stream_error = guarantee_error(er.code());
MDEBUG("Some problems at connect, message: " << er.what());
}
catch(const std::exception& er)
{
m_stream_error = make_error_code(boost::system::errc::not_connected);
MDEBUG("Some problems at connect, message: " << er.what()); MDEBUG("Some problems at connect, message: " << er.what());
return false;
} }
catch(...) catch(...)
{ {
m_stream_error = make_error_code(boost::system::errc::not_connected);
MDEBUG("Some fatal problems."); MDEBUG("Some fatal problems.");
return false;
} }
return !m_stream_error;
return true;
} }
//! Change the connection routine (proxy, etc.) //! Change the connection routine (proxy, etc.)
void set_connector(std::function<connect_func> connector) void set_connector(std::function<connect_func> connector)
{ {
@ -243,9 +227,9 @@ namespace net_utils
{ {
try try
{ {
if(m_connected) if(!last_error())
{ {
m_connected = false; m_stream_error = make_error_code(boost::system::errc::not_connected);
if(m_ssl_options) if(m_ssl_options)
shutdown_ssl(); shutdown_ssl();
m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both); m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both);
@ -295,8 +279,8 @@ namespace net_utils
if (ec) if (ec)
{ {
m_stream_error = ec;
LOG_PRINT_L3("Problems at write: " << ec.message()); LOG_PRINT_L3("Problems at write: " << ec.message());
m_connected = false;
return false; return false;
}else }else
{ {
@ -307,11 +291,13 @@ namespace net_utils
catch(const boost::system::system_error& er) catch(const boost::system::system_error& er)
{ {
m_stream_error = guarantee_error(er.code());
LOG_ERROR("Some problems at connect, message: " << er.what()); LOG_ERROR("Some problems at connect, message: " << er.what());
return false; return false;
} }
catch(...) catch(...)
{ {
m_stream_error = make_error_code(boost::system::errc::not_connected);
LOG_ERROR("Some fatal problems."); LOG_ERROR("Some fatal problems.");
return false; return false;
} }
@ -319,9 +305,11 @@ namespace net_utils
return true; return true;
} }
const boost::system::error_code& last_error() const noexcept { return m_stream_error; }
bool is_connected(bool *ssl = NULL) bool is_connected(bool *ssl = NULL)
{ {
if (!m_connected || !m_ssl_socket->next_layer().is_open()) if (last_error() || !m_ssl_socket->next_layer().is_open())
return false; return false;
if (ssl) if (ssl)
*ssl = m_ssl_options.support != ssl_support_t::e_ssl_support_disabled; *ssl = m_ssl_options.support != ssl_support_t::e_ssl_support_disabled;
@ -371,6 +359,7 @@ namespace net_utils
if (ec) if (ec)
{ {
m_stream_error = ec;
MTRACE("READ ENDS: Connection err_code " << ec.value()); MTRACE("READ ENDS: Connection err_code " << ec.value());
if(ec == boost::asio::error::eof) if(ec == boost::asio::error::eof)
{ {
@ -381,7 +370,6 @@ namespace net_utils
} }
MDEBUG("Problems at read: " << ec.message()); MDEBUG("Problems at read: " << ec.message());
m_connected = false;
return false; return false;
}else }else
{ {
@ -399,24 +387,22 @@ namespace net_utils
catch(const boost::system::system_error& er) catch(const boost::system::system_error& er)
{ {
m_stream_error = guarantee_error(er.code());
LOG_ERROR("Some problems at read, message: " << er.what()); LOG_ERROR("Some problems at read, message: " << er.what());
m_connected = false;
return false;
} }
catch(...) catch(...)
{ {
m_stream_error = make_error_code(boost::system::errc::not_connected);
LOG_ERROR("Some fatal problems at read."); LOG_ERROR("Some fatal problems at read.");
return false;
} }
return false; return false;
} }
bool shutdown() bool shutdown()
{ {
m_stream_error = make_error_code(boost::system::errc::not_connected);
m_deadline.cancel(); m_deadline.cancel();
boost::system::error_code ec; boost::system::error_code ec;
if(m_ssl_options) if(m_ssl_options)
@ -431,7 +417,6 @@ namespace net_utils
if(ec) if(ec)
MDEBUG("Problems at close: " << ec.message()); MDEBUG("Problems at close: " << ec.message());
m_shutdowned = true; m_shutdowned = true;
m_connected = false;
return true; return true;
} }
@ -457,8 +442,8 @@ namespace net_utils
// The deadline has passed. The socket is closed so that any outstanding // The deadline has passed. The socket is closed so that any outstanding
// asynchronous operations are cancelled. This allows the blocked // asynchronous operations are cancelled. This allows the blocked
// connect(), read_line() or write_line() functions to return. // connect(), read_line() or write_line() functions to return.
m_stream_error = make_error_code(boost::system::errc::timed_out);
LOG_PRINT_L3("Timed out socket"); LOG_PRINT_L3("Timed out socket");
m_connected = false;
m_ssl_socket->next_layer().close(); m_ssl_socket->next_layer().close();
// There is no longer an active deadline. The expiry is set to positive // There is no longer an active deadline. The expiry is set to positive
@ -516,7 +501,7 @@ namespace net_utils
std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_ssl_socket; std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_ssl_socket;
std::function<connect_func> m_connector; std::function<connect_func> m_connector;
ssl_options_t m_ssl_options; ssl_options_t m_ssl_options;
bool m_connected; boost::system::error_code m_stream_error;
boost::asio::steady_timer m_deadline; boost::asio::steady_timer m_deadline;
std::atomic<bool> m_shutdowned; std::atomic<bool> m_shutdowned;
std::atomic<uint64_t> m_bytes_sent; std::atomic<uint64_t> m_bytes_sent;

View file

@ -133,9 +133,8 @@ namespace net_utils
`verification == system_ca` the client also does a rfc2818 check to `verification == system_ca` the client also does a rfc2818 check to
ensure that the server certificate is to the provided hostname. ensure that the server certificate is to the provided hostname.
\return True if the SSL handshake completes with peer verification \return Non-empty error_code on failure. */
settings. */ boost::system::error_code handshake(
bool handshake(
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
boost::asio::ssl::stream_base::handshake_type type, boost::asio::ssl::stream_base::handshake_type type,
boost::asio::const_buffer buffer = {}, boost::asio::const_buffer buffer = {},

View file

@ -133,6 +133,13 @@ namespace http
{ {
return false; return false;
} }
boost::system::error_code epee::net_utils::http::abstract_http_client::last_error()
{
if (is_connected())
return boost::system::error_code{};
return make_error_code(boost::system::errc::not_connected);
}
} }
} }
} }

View file

@ -544,7 +544,7 @@ void ssl_options_t::configure(
} }
} }
bool ssl_options_t::handshake( boost::system::error_code ssl_options_t::handshake(
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
boost::asio::ssl::stream_base::handshake_type type, boost::asio::ssl::stream_base::handshake_type type,
boost::asio::const_buffer buffer, boost::asio::const_buffer buffer,
@ -636,12 +636,10 @@ bool ssl_options_t::handshake(
const auto ec = start_handshake(); const auto ec = start_handshake();
if (ec) if (ec)
{
MERROR("SSL handshake failed, connection dropped: " << ec.message()); MERROR("SSL handshake failed, connection dropped: " << ec.message());
return false; else
} MDEBUG("SSL handshake success");
MDEBUG("SSL handshake success"); return ec;
return true;
} }
std::string get_hr_ssl_fingerprint(const X509 *cert, const EVP_MD *fdig) std::string get_hr_ssl_fingerprint(const X509 *cert, const EVP_MD *fdig)

View file

@ -4554,7 +4554,8 @@ bool simple_wallet::try_connect_to_daemon(bool silent, uint32_t* version)
if (!version) if (!version)
version = &version_; version = &version_;
bool wallet_is_outdated = false, daemon_is_outdated = false; bool wallet_is_outdated = false, daemon_is_outdated = false;
if (!m_wallet->check_connection(version, NULL, 200000, &wallet_is_outdated, &daemon_is_outdated)) boost::system::error_code err{};
if (!m_wallet->check_connection(version, NULL, 200000, &wallet_is_outdated, &daemon_is_outdated, std::addressof(err)))
{ {
if (!silent) if (!silent)
{ {
@ -4568,7 +4569,7 @@ bool simple_wallet::try_connect_to_daemon(bool silent, uint32_t* version)
tr("Daemon is not up to date. " tr("Daemon is not up to date. "
"Please make sure the daemon is running the latest version or change the daemon address using the 'set_daemon' command."); "Please make sure the daemon is running the latest version or change the daemon address using the 'set_daemon' command.");
else else
fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_wallet->get_daemon_address() << ". " << fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_wallet->get_daemon_address() << " : " << err.message() << ". " <<
tr("Daemon either is not started or wrong port was passed. " tr("Daemon either is not started or wrong port was passed. "
"Please make sure daemon is running or change the daemon address using the 'set_daemon' command."); "Please make sure daemon is running or change the daemon address using the 'set_daemon' command.");
} }
@ -9652,9 +9653,10 @@ bool simple_wallet::status(const std::vector<std::string> &args)
uint64_t local_height = m_wallet->get_blockchain_current_height(); uint64_t local_height = m_wallet->get_blockchain_current_height();
uint32_t version = 0; uint32_t version = 0;
bool ssl = false; bool ssl = false;
if (!m_wallet->check_connection(&version, &ssl)) boost::system::error_code error{};
if (!m_wallet->check_connection(&version, &ssl, 200000, nullptr, nullptr, std::addressof(error)))
{ {
success_msg_writer() << "Refreshed " << local_height << "/?, no daemon connected"; success_msg_writer() << "Refreshed " << local_height << "/?, no daemon connected: " << error.message();
return true; return true;
} }

View file

@ -2095,14 +2095,15 @@ bool WalletImpl::verifyMessageWithPublicKey(const std::string &message, const st
bool WalletImpl::connectToDaemon() bool WalletImpl::connectToDaemon()
{ {
bool result = m_wallet->check_connection(NULL, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS); boost::system::error_code err{};
bool result = m_wallet->check_connection(NULL, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS, NULL, NULL, std::addressof(err));
if (!result) { if (!result) {
setStatusError("Error connecting to daemon at " + m_wallet->get_daemon_address()); setStatusError("Error connecting to daemon at " + m_wallet->get_daemon_address() + " : " + err.message());
} else { } else {
clearStatus(); clearStatus();
// start refreshing here // start refreshing here
} }
return result; return !err;
} }
Wallet::ConnectionStatus WalletImpl::connected() const Wallet::ConnectionStatus WalletImpl::connected() const

View file

@ -5863,7 +5863,7 @@ bool wallet2::prepare_file_names(const std::string& file_path)
return true; return true;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout, bool *wallet_is_outdated, bool *daemon_is_outdated) bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout, bool *wallet_is_outdated, bool *daemon_is_outdated, boost::system::error_code* error)
{ {
THROW_WALLET_EXCEPTION_IF(!m_is_initialized, error::wallet_not_initialized); THROW_WALLET_EXCEPTION_IF(!m_is_initialized, error::wallet_not_initialized);
@ -5874,6 +5874,8 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout, b
*version = 0; *version = 0;
if (ssl) if (ssl)
*ssl = false; *ssl = false;
if (error)
*error = make_error_code(boost::system::errc::not_connected);
return false; return false;
} }
@ -5883,18 +5885,26 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout, b
{ {
m_rpc_version = 0; m_rpc_version = 0;
m_node_rpc_proxy.invalidate(); m_node_rpc_proxy.invalidate();
if (!m_http_client->connect(std::chrono::milliseconds(timeout))) if (!m_http_client->connect(std::chrono::milliseconds(timeout)) || !m_http_client->is_connected(ssl))
return false; {
if(!m_http_client->is_connected(ssl)) if (error)
*error = m_http_client->last_error();
return false; return false;
}
} }
} }
if (!m_rpc_version && !check_version(version, wallet_is_outdated, daemon_is_outdated)) if (!m_rpc_version && !check_version(version, wallet_is_outdated, daemon_is_outdated))
{
if (error)
*error = make_error_code(boost::system::errc::protocol_error);
return false; return false;
}
if (version) if (version)
*version = m_rpc_version; *version = m_rpc_version;
if (error)
*error = boost::system::error_code{};
return true; return true;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
@ -11534,7 +11544,8 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
{ {
uint32_t rpc_version; uint32_t rpc_version;
THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address()); boost::system::error_code error{};
THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version, nullptr, 200000, nullptr, nullptr, std::addressof(error)), error::wallet_internal_error, "Failed to connect to daemon (" + get_daemon_address() + "): " + error.message());
COMMAND_RPC_GET_TRANSACTIONS::request req; COMMAND_RPC_GET_TRANSACTIONS::request req;
COMMAND_RPC_GET_TRANSACTIONS::response res; COMMAND_RPC_GET_TRANSACTIONS::response res;
@ -12059,7 +12070,8 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
bool wallet2::check_reserve_proof(const cryptonote::account_public_address &address, const std::string &message, const std::string &sig_str, uint64_t &total, uint64_t &spent) bool wallet2::check_reserve_proof(const cryptonote::account_public_address &address, const std::string &message, const std::string &sig_str, uint64_t &total, uint64_t &spent)
{ {
uint32_t rpc_version; uint32_t rpc_version;
THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address()); boost::system::error_code error{};
THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version, nullptr, 200000, nullptr, nullptr, std::addressof(error)), error::wallet_internal_error, "Failed to connect to daemon (" + get_daemon_address() + "): " + error.message());
THROW_WALLET_EXCEPTION_IF(rpc_version < MAKE_CORE_RPC_VERSION(1, 0), error::wallet_internal_error, "Daemon RPC version is too old"); THROW_WALLET_EXCEPTION_IF(rpc_version < MAKE_CORE_RPC_VERSION(1, 0), error::wallet_internal_error, "Daemon RPC version is too old");
static constexpr char header_v1[] = "ReserveProofV1"; static constexpr char header_v1[] = "ReserveProofV1";
@ -13987,9 +13999,10 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day) uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day)
{ {
uint32_t version; uint32_t version;
if (!check_connection(&version)) boost::system::error_code error{};
if (!check_connection(&version, nullptr, 200000, nullptr, nullptr, std::addressof(error)))
{ {
throw std::runtime_error("failed to connect to daemon: " + get_daemon_address()); throw std::runtime_error("failed to connect to daemon (" + get_daemon_address() + "): " + error.message());
} }
if (version < MAKE_CORE_RPC_VERSION(1, 6)) if (version < MAKE_CORE_RPC_VERSION(1, 6))
{ {

View file

@ -40,6 +40,7 @@
#include <boost/serialization/list.hpp> #include <boost/serialization/list.hpp>
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>
#include <boost/serialization/deque.hpp> #include <boost/serialization/deque.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/lock_guard.hpp> #include <boost/thread/lock_guard.hpp>
#include <atomic> #include <atomic>
#include <random> #include <random>
@ -1113,7 +1114,7 @@ private:
bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector<crypto::hash> &txids); bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector<crypto::hash> &txids);
std::vector<pending_tx> create_unmixable_sweep_transactions(); std::vector<pending_tx> create_unmixable_sweep_transactions();
void discard_unmixable_outputs(); void discard_unmixable_outputs();
bool check_connection(uint32_t *version = NULL, bool *ssl = NULL, uint32_t timeout = 200000, bool *wallet_is_outdated = NULL, bool *daemon_is_outdated = NULL); bool check_connection(uint32_t *version = NULL, bool *ssl = NULL, uint32_t timeout = 200000, bool *wallet_is_outdated = NULL, bool *daemon_is_outdated = NULL, boost::system::error_code* error = nullptr);
bool check_version(uint32_t *version, bool *wallet_is_outdated, bool *daemon_is_outdated); bool check_version(uint32_t *version, bool *wallet_is_outdated, bool *daemon_is_outdated);
bool check_hard_fork_version(cryptonote::network_type nettype, const std::vector<std::pair<uint8_t, uint64_t>> &daemon_hard_forks, const uint64_t height, const uint64_t target_height, bool *wallet_is_outdated, bool *daemon_is_outdated); bool check_hard_fork_version(cryptonote::network_type nettype, const std::vector<std::pair<uint8_t, uint64_t>> &daemon_hard_forks, const uint64_t height, const uint64_t target_height, bool *wallet_is_outdated, bool *daemon_is_outdated);
void get_transfers(wallet2::transfer_container& incoming_transfers) const; void get_transfers(wallet2::transfer_container& incoming_transfers) const;

View file

@ -26,6 +26,7 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/system/error_code.hpp>
#include <boost/utility/string_ref.hpp> #include <boost/utility/string_ref.hpp>
#include "include_base_utils.h" #include "include_base_utils.h"
#include "file_io_utils.h" #include "file_io_utils.h"
@ -42,6 +43,7 @@ public:
bool send(const boost::string_ref buff, std::chrono::milliseconds timeout) { return true; } bool send(const boost::string_ref buff, std::chrono::milliseconds timeout) { return true; }
bool send(const void* data, size_t sz) { return true; } bool send(const void* data, size_t sz) { return true; }
bool is_connected() { return true; } bool is_connected() { return true; }
static boost::system::error_code last_error() noexcept { return {}; }
bool recv(std::string& buff, std::chrono::milliseconds timeout) bool recv(std::string& buff, std::chrono::milliseconds timeout)
{ {
buff = data; buff = data;

View file

@ -567,7 +567,7 @@ TEST(test_epee_connection, ssl_handshake)
std::this_thread::sleep_for(std::chrono::milliseconds(50)); std::this_thread::sleep_for(std::chrono::milliseconds(50));
}); });
} }
EXPECT_EQ( EXPECT_NE(
ssl_options.handshake( ssl_options.handshake(
*ssl_socket, *ssl_socket,
ssl_socket_t::server, ssl_socket_t::server,
@ -575,7 +575,7 @@ TEST(test_epee_connection, ssl_handshake)
{}, {},
std::chrono::milliseconds(0) std::chrono::milliseconds(0)
), ),
false boost::system::error_code{}
); );
ssl_socket->next_layer().close(); ssl_socket->next_layer().close();
ssl_socket.reset(); ssl_socket.reset();