diff options
author | Lee Clagett <code@leeclagett.com> | 2017-01-25 00:16:05 -0500 |
---|---|---|
committer | Lee Clagett <code@leeclagett.com> | 2017-01-25 15:39:32 -0500 |
commit | c02e1cb943903d34becfaf1c6d9cd71e4424d748 (patch) | |
tree | a363ce155ba8f6b14a924c84380ec2886894f22d | |
parent | Merge pull request #1622 (diff) | |
download | monero-c02e1cb943903d34becfaf1c6d9cd71e4424d748.tar.xz |
Updates to epee HTTP client code
- http_simple_client now uses std::chrono for timeouts
- http_simple_client accepts timeouts per connect / invoke call
- shortened names of epee http invoke functions
- invoke command functions only take relative path, connection
is not automatically performed
-rw-r--r-- | contrib/epee/include/net/http_client.h | 94 | ||||
-rw-r--r-- | contrib/epee/include/net/http_client_abstract_invoke.h | 101 | ||||
-rw-r--r-- | contrib/epee/include/net/net_helper.h | 51 | ||||
-rw-r--r-- | contrib/epee/include/storages/http_abstract_invoke.h | 34 | ||||
-rw-r--r-- | src/common/http_connection.h | 17 | ||||
-rw-r--r-- | src/common/rpc_client.h | 35 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 13 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 12 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 2 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.cpp | 41 | ||||
-rw-r--r-- | src/wallet/node_rpc_proxy.cpp | 28 | ||||
-rw-r--r-- | src/wallet/node_rpc_proxy.h | 6 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 47 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 10 | ||||
-rw-r--r-- | tests/functional_tests/transactions_flow_test.cpp | 4 |
15 files changed, 172 insertions, 323 deletions
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index a54318ebb..c5aeb9251 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -263,7 +263,6 @@ using namespace std; blocked_mode_client m_net_client; std::string m_host_buff; std::string m_port; - unsigned int m_timeout; std::string m_header_cache; http_response_info m_response_info; size_t m_len_in_summary; @@ -276,23 +275,43 @@ using namespace std; critical_section m_lock; public: - void set_host_name(const std::string& name) + explicit http_simple_client() + : i_target_handler() + , m_net_client() + , m_host_buff() + , m_port() + , m_header_cache() + , m_response_info() + , m_len_in_summary(0) + , m_len_in_remain(0) + , m_pcontent_encoding_handler(nullptr) + , m_state() + , m_chunked_state() + , m_chunked_cache() + , m_lock() + {} + + bool set_server(const std::string& address) + { + http::url_content parsed{}; + const bool r = parse_url(address, parsed); + CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address); + set_server(std::move(parsed.host), std::to_string(parsed.port)); + return true; + } + + void set_server(std::string host, std::string port) { CRITICAL_REGION_LOCAL(m_lock); - m_host_buff = name; + disconnect(); + m_host_buff = std::move(host); + m_port = std::move(port); } - bool connect(const std::string& host, int port, unsigned int timeout) - { - return connect(host, std::to_string(port), timeout); - } - bool connect(const std::string& host, const std::string& port, unsigned int timeout) + + bool connect(std::chrono::milliseconds timeout) { CRITICAL_REGION_LOCAL(m_lock); - m_host_buff = host; - m_port = port; - m_timeout = timeout; - - return m_net_client.connect(host, port, timeout, timeout); + return m_net_client.connect(m_host_buff, m_port, timeout); } //--------------------------------------------------------------------------- bool disconnect() @@ -316,20 +335,20 @@ using namespace std; } //--------------------------------------------------------------------------- inline - bool invoke_get(const std::string& uri, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) + bool invoke_get(const std::string& 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()) { CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "GET", body, ppresponse_info, additional_params); + return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params); } //--------------------------------------------------------------------------- - inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) + inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) { CRITICAL_REGION_LOCAL(m_lock); if(!is_connected()) { MDEBUG("Reconnecting..."); - if(!connect(m_host_buff, m_port, m_timeout)) + if(!connect(timeout)) { MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port); return false; @@ -347,27 +366,27 @@ using namespace std; req_buff += "\r\n"; //-- - bool res = m_net_client.send(req_buff); + bool res = m_net_client.send(req_buff, timeout); CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); if(body.size()) - res = m_net_client.send(body); + res = m_net_client.send(body, timeout); CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); if(ppresponse_info) *ppresponse_info = &m_response_info; m_state = reciev_machine_state_header; - return handle_reciev(); + return handle_reciev(timeout); } //--------------------------------------------------------------------------- - inline bool invoke_post(const std::string& uri, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) + inline bool invoke_post(const std::string& uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) { CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "POST", body, ppresponse_info, additional_params); + return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params); } private: //--------------------------------------------------------------------------- - inline bool handle_reciev() + inline bool handle_reciev(std::chrono::milliseconds timeout) { CRITICAL_REGION_LOCAL(m_lock); bool keep_handling = true; @@ -377,7 +396,7 @@ using namespace std; { if(need_more_data) { - if(!m_net_client.recv(recv_buffer)) + if(!m_net_client.recv(recv_buffer, timeout)) { MERROR("Unexpected recv fail"); m_state = reciev_machine_state_error; @@ -878,33 +897,6 @@ using namespace std; return true; } }; - - - - /************************************************************************/ - /* */ - /************************************************************************/ - //inline - template<class t_transport> - bool invoke_request(const std::string& url, t_transport& tr, unsigned int timeout, const http_response_info** ppresponse_info, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list()) - { - http::url_content u_c; - bool res = parse_url(url, u_c); - - if(!tr.is_connected() && !u_c.host.empty()) - { - CHECK_AND_ASSERT_MES(res, false, "failed to parse url: " << url); - - if(!u_c.port) - u_c.port = 80;//default for http - - res = tr.connect(u_c.host, static_cast<int>(u_c.port), timeout); - CHECK_AND_ASSERT_MES(res, false, "failed to connect " << u_c.host << ":" << u_c.port); - } - - return tr.invoke(u_c.uri, method, body, ppresponse_info, additional_params); - } - } } } diff --git a/contrib/epee/include/net/http_client_abstract_invoke.h b/contrib/epee/include/net/http_client_abstract_invoke.h deleted file mode 100644 index 9b6ab4db8..000000000 --- a/contrib/epee/include/net/http_client_abstract_invoke.h +++ /dev/null @@ -1,101 +0,0 @@ - -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 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. -// - -#pragma once -#include "storages/serializeble_struct_helper.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ - namespace net_utils - { - namespace http - { - template<class TArg, class TResult, class TTransport> - bool invoke_http_json_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - StorageNamed::InMemStorageSpace::json::store_t_to_json(out_struct, req_param); - - const http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return StorageNamed::InMemStorageSpace::json::load_t_from_json(result_struct, pri->m_body); - } - - - - template<class TArg, class TResult, class TTransport> - bool invoke_http_bin_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - epee::StorageNamed::save_struct_as_storage_to_buff(out_struct, req_param); - - const http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return epee::StorageNamed::load_struct_from_storage_buff(result_struct, pri->m_body); - } - - - } - } -} diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 22cea122f..432169990 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -37,6 +37,7 @@ #include <ostream> #include <string> #include <boost/asio.hpp> +#include <boost/asio/steady_timer.hpp> #include <boost/preprocessor/selection/min.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/lambda.hpp> @@ -98,7 +99,7 @@ namespace net_utils // No deadline is required until the first socket operation is started. We // set the deadline to positive infinity so that the actor takes no action // until a specific deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); // Start the persistent actor that checks for deadline expiry. check_deadline(); @@ -111,26 +112,16 @@ namespace net_utils shutdown(); } - inline void set_recv_timeout(int reciev_timeout) - { - m_reciev_timeout = reciev_timeout; - } - inline - bool connect(const std::string& addr, int port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") + bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0") { - return connect(addr, std::to_string(port), connect_timeout, reciev_timeout, bind_ip); + return connect(addr, std::to_string(port), timeout, bind_ip); } inline - bool connect(const std::string& addr, const std::string& port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") + bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0") { - m_connect_timeout = connect_timeout; - m_reciev_timeout = reciev_timeout; m_connected = false; - if(!m_reciev_timeout) - m_reciev_timeout = m_connect_timeout; - try { m_socket.close(); @@ -164,7 +155,7 @@ namespace net_utils } - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_connect_timeout)); + m_deadline.expires_from_now(timeout); boost::system::error_code ec = boost::asio::error::would_block; @@ -179,7 +170,7 @@ namespace net_utils if (!ec && m_socket.is_open()) { m_connected = true; - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); return true; }else { @@ -231,12 +222,12 @@ namespace net_utils inline - bool send(const std::string& buff) + bool send(const std::string& buff, std::chrono::milliseconds timeout) { try { - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + m_deadline.expires_from_now(timeout); // Set up the variable that receives the result of the asynchronous // operation. The error code is set to would_block to signal that the @@ -264,7 +255,7 @@ namespace net_utils return false; }else { - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } } @@ -322,7 +313,7 @@ namespace net_utils return false; }else { - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } } @@ -350,7 +341,7 @@ namespace net_utils } inline - bool recv(std::string& buff) + bool recv(std::string& buff, std::chrono::milliseconds timeout) { try @@ -358,7 +349,7 @@ namespace net_utils // Set a deadline for the asynchronous operation. Since this function uses // a composed operation (async_read_until), the deadline applies to the // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + m_deadline.expires_from_now(timeout); // Set up the variable that receives the result of the asynchronous // operation. The error code is set to would_block to signal that the @@ -404,7 +395,7 @@ namespace net_utils }else { MTRACE("READ ENDS: Success. bytes_tr: " << bytes_transfered); - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } /*if(!bytes_transfered) @@ -432,7 +423,7 @@ namespace net_utils } - inline bool recv_n(std::string& buff, int64_t sz) + inline bool recv_n(std::string& buff, int64_t sz, std::chrono::milliseconds timeout) { try @@ -440,7 +431,7 @@ namespace net_utils // Set a deadline for the asynchronous operation. Since this function uses // a composed operation (async_read_until), the deadline applies to the // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + m_deadline.expires_from_now(timeout); // Set up the variable that receives the result of the asynchronous // operation. The error code is set to would_block to signal that the @@ -477,7 +468,7 @@ namespace net_utils return false; }else { - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } if(bytes_transfered != buff.size()) @@ -539,7 +530,7 @@ namespace net_utils // Check whether the deadline has passed. We compare the deadline against // the current time since a new asynchronous operation may have moved the // deadline before this actor had a chance to run. - if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) + if (m_deadline.expires_at() <= std::chrono::steady_clock::now()) { // The deadline has passed. The socket is closed so that any outstanding // asynchronous operations are cancelled. This allows the blocked @@ -550,7 +541,7 @@ namespace net_utils // There is no longer an active deadline. The expiry is set to positive // infinity so that the actor takes no action until a new deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); + m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } // Put the actor back to sleep. @@ -562,11 +553,9 @@ namespace net_utils protected: boost::asio::io_service m_io_service; boost::asio::ip::tcp::socket m_socket; - int m_connect_timeout; - int m_reciev_timeout; bool m_initialized; bool m_connected; - boost::asio::deadline_timer m_deadline; + boost::asio::steady_timer m_deadline; volatile uint32_t m_shutdowned; }; diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h index 00ee8a4ad..36177c7e0 100644 --- a/contrib/epee/include/storages/http_abstract_invoke.h +++ b/contrib/epee/include/storages/http_abstract_invoke.h @@ -35,28 +35,28 @@ namespace epee namespace net_utils { template<class t_request, class t_response, class t_transport> - bool invoke_http_json_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") + bool invoke_http_json(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET") { std::string req_param; if(!serialization::store_t_to_json(out_struct, req_param)) return false; const http::http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) + if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri))) { - LOG_PRINT_L1("Failed to invoke http request to " << url); + LOG_PRINT_L1("Failed to invoke http request to " << uri); return false; } - if(!pri->m_response_code) + if(!pri) { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); + LOG_PRINT_L1("Failed to invoke http request to " << uri << ", internal error (null response ptr)"); return false; } if(pri->m_response_code != 200) { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); + LOG_PRINT_L1("Failed to invoke http request to " << uri << ", wrong response code: " << pri->m_response_code); return false; } @@ -66,28 +66,28 @@ namespace epee template<class t_request, class t_response, class t_transport> - bool invoke_http_bin_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") + bool invoke_http_bin(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET") { std::string req_param; if(!serialization::store_t_to_binary(out_struct, req_param)) return false; const http::http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) + if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri))) { - LOG_PRINT_L1("Failed to invoke http request to " << url); + LOG_PRINT_L1("Failed to invoke http request to " << uri); return false; } - if(!pri->m_response_code) + if(!pri) { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); + LOG_PRINT_L1("Failed to invoke http request to " << uri << ", internal error (null response ptr)"); return false; } if(pri->m_response_code != 200) { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); + LOG_PRINT_L1("Failed to invoke http request to " << uri << ", wrong response code: " << pri->m_response_code); return false; } @@ -95,15 +95,15 @@ namespace epee } template<class t_request, class t_response, class t_transport> - bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") + bool invoke_http_json_rpc(const std::string& uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0") { epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t); req_t.jsonrpc = "2.0"; req_t.id = req_id; - req_t.method = method_name; + req_t.method = std::move(method_name); req_t.params = out_struct; epee::json_rpc::response<t_response, epee::json_rpc::error> resp_t = AUTO_VAL_INIT(resp_t); - if(!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method)) + if(!epee::net_utils::invoke_http_json(uri, req_t, resp_t, transport, timeout, http_method)) { return false; } @@ -117,9 +117,9 @@ namespace epee } template<class t_command, class t_transport> - bool invoke_http_json_rpc(const std::string& url, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") + bool invoke_http_json_rpc(const std::string& uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0") { - return invoke_http_json_rpc(url, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id); + return invoke_http_json_rpc(uri, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id); } } diff --git a/src/common/http_connection.h b/src/common/http_connection.h index 156474cdd..8a786361a 100644 --- a/src/common/http_connection.h +++ b/src/common/http_connection.h @@ -28,6 +28,7 @@ #pragma once +#include <chrono> #include "string_tools.h" #include "net/http_client.h" @@ -38,20 +39,16 @@ private: epee::net_utils::http::http_simple_client * mp_http_client; bool m_ok; public: - static unsigned int const TIMEOUT = 200000; + static constexpr std::chrono::seconds TIMEOUT() + { + return std::chrono::minutes(3) + std::chrono::seconds(30); + } - t_http_connection( - epee::net_utils::http::http_simple_client * p_http_client - , uint32_t ip - , uint16_t port - ) + t_http_connection(epee::net_utils::http::http_simple_client* p_http_client) : mp_http_client(p_http_client) , m_ok(false) { - // TODO fix http client so that it accepts properly typed arguments - std::string ip_str = epee::string_tools::get_ip_string_from_int32(ip); - std::string port_str = boost::lexical_cast<std::string>(port); - m_ok = mp_http_client->connect(ip_str, port_str, TIMEOUT); + m_ok = mp_http_client->connect(TIMEOUT()); } ~t_http_connection() diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h index 9c0036198..f5ecc8b50 100644 --- a/src/common/rpc_client.h +++ b/src/common/rpc_client.h @@ -34,7 +34,6 @@ #include "storages/http_abstract_invoke.h" #include "net/http_client.h" #include "string_tools.h" -#include <boost/lexical_cast.hpp> namespace tools { @@ -42,27 +41,16 @@ namespace tools { private: epee::net_utils::http::http_simple_client m_http_client; - uint32_t m_ip; - uint16_t m_port; public: t_rpc_client( uint32_t ip , uint16_t port ) : m_http_client{} - , m_ip{ip} - , m_port{port} - {} - - std::string build_url(std::string const & relative_url) const { - std::string result = - "http://" - + epee::string_tools::get_ip_string_from_int32(m_ip) - + ":" - + boost::lexical_cast<std::string>(m_port) - + relative_url; - return result; + m_http_client.set_server( + epee::string_tools::get_ip_string_from_int32(ip), std::to_string(port) + ); } template <typename T_req, typename T_res> @@ -72,8 +60,7 @@ namespace tools , std::string const & method_name ) { - std::string rpc_url = build_url("/json_rpc"); - t_http_connection connection(&m_http_client, m_ip, m_port); + t_http_connection connection(&m_http_client); bool ok = connection.is_open(); if (!ok) @@ -81,7 +68,7 @@ namespace tools fail_msg_writer() << "Couldn't connect to daemon"; return false; } - ok = ok && epee::net_utils::invoke_http_json_rpc(rpc_url, method_name, req, res, m_http_client); + ok = ok && epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client, t_http_connection::TIMEOUT()); if (!ok) { fail_msg_writer() << "Daemon request failed"; @@ -101,11 +88,10 @@ namespace tools , std::string const & fail_msg ) { - std::string rpc_url = build_url("/json_rpc"); - t_http_connection connection(&m_http_client, m_ip, m_port); + t_http_connection connection(&m_http_client); bool ok = connection.is_open(); - ok = ok && epee::net_utils::invoke_http_json_rpc(rpc_url, method_name, req, res, m_http_client); + ok = ok && epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client, t_http_connection::TIMEOUT()); if (!ok) { fail_msg_writer() << "Couldn't connect to daemon"; @@ -130,11 +116,10 @@ namespace tools , std::string const & fail_msg ) { - std::string rpc_url = build_url(relative_url); - t_http_connection connection(&m_http_client, m_ip, m_port); + t_http_connection connection(&m_http_client); bool ok = connection.is_open(); - ok = ok && epee::net_utils::invoke_http_json_remote_command2(rpc_url, req, res, m_http_client); + ok = ok && epee::net_utils::invoke_http_json(relative_url, req, res, m_http_client, t_http_connection::TIMEOUT()); if (!ok) { fail_msg_writer() << "Couldn't connect to daemon"; @@ -153,7 +138,7 @@ namespace tools bool check_connection() { - t_http_connection connection(&m_http_client, m_ip, m_port); + t_http_connection connection(&m_http_client); return connection.is_open(); } }; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 50509040c..49d80ec9b 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1163,6 +1163,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) } catch (const std::exception &e) { } + m_http_client.set_server(m_wallet->get_daemon_address()); m_wallet->callback(this); return true; } @@ -1560,7 +1561,7 @@ bool simple_wallet::start_mining(const std::vector<std::string>& args) } COMMAND_RPC_START_MINING::response res; - bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/start_mining", req, res, m_http_client); + bool r = net_utils::invoke_http_json("/start_mining", req, res, m_http_client); std::string err = interpret_rpc_response(r, res.status); if (err.empty()) success_msg_writer() << tr("Mining started in daemon"); @@ -1577,7 +1578,7 @@ bool simple_wallet::stop_mining(const std::vector<std::string>& args) assert(m_wallet); COMMAND_RPC_STOP_MINING::request req; COMMAND_RPC_STOP_MINING::response res; - bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/stop_mining", req, res, m_http_client); + bool r = net_utils::invoke_http_json("/stop_mining", req, res, m_http_client); std::string err = interpret_rpc_response(r, res.status); if (err.empty()) success_msg_writer() << tr("Mining stopped in daemon"); @@ -1594,7 +1595,7 @@ bool simple_wallet::save_bc(const std::vector<std::string>& args) assert(m_wallet); COMMAND_RPC_SAVE_BC::request req; COMMAND_RPC_SAVE_BC::response res; - bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/save_bc", req, res, m_http_client); + bool r = net_utils::invoke_http_json("/save_bc", req, res, m_http_client); std::string err = interpret_rpc_response(r, res.status); if (err.empty()) success_msg_writer() << tr("Blockchain saved"); @@ -1883,7 +1884,7 @@ uint64_t simple_wallet::get_daemon_blockchain_height(std::string& err) COMMAND_RPC_GET_HEIGHT::request req; COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>(); - bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/getheight", req, res, m_http_client); + bool r = net_utils::invoke_http_json("/getheight", req, res, m_http_client); err = interpret_rpc_response(r, res.status); return res.height; } @@ -1994,7 +1995,7 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending req.outputs[j].index = absolute_offsets[j]; } COMMAND_RPC_GET_OUTPUTS_BIN::response res = AUTO_VAL_INIT(res); - bool r = net_utils::invoke_http_bin_remote_command2(m_wallet->get_daemon_address() + "/get_outs.bin", req, res, m_http_client); + bool r = net_utils::invoke_http_bin("/get_outs.bin", req, res, m_http_client); err = interpret_rpc_response(r, res.status); if (!err.empty()) { @@ -3196,7 +3197,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_) COMMAND_RPC_GET_TRANSACTIONS::request req; COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); - if (!net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/gettransactions", req, res, m_http_client) || + if (!net_utils::invoke_http_json("/gettransactions", req, res, m_http_client) || (res.txs.size() != 1 && res.txs_as_hex.size() != 1)) { fail_msg_writer() << tr("failed to get transaction from daemon"); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 52ecc2e6a..cd4b523c9 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -516,12 +516,12 @@ string WalletImpl::keysFilename() const bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) { clearStatus(); - doInit(daemon_address, upper_transaction_size_limit); + if (!doInit(daemon_address, upper_transaction_size_limit)) + return false; bool result = this->refresh(); // enabling background refresh thread startRefresh(); return result; - } void WalletImpl::initAsync(const string &daemon_address, uint64_t upper_transaction_size_limit) @@ -1232,9 +1232,10 @@ bool WalletImpl::isNewWallet() const return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_rebuildWalletCache) && !watchOnly(); } -void WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit) +bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit) { - m_wallet->init(daemon_address, upper_transaction_size_limit); + if (!m_wallet->init(daemon_address, upper_transaction_size_limit)) + return false; // in case new wallet, this will force fast-refresh (pulling hashes instead of blocks) // If daemon isn't synced a calculated block height will be used instead @@ -1253,8 +1254,7 @@ void WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction this->setTrustedDaemon(false); m_refreshIntervalMillis = DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS; } - - + return true; } bool WalletImpl::parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index e3df7fd01..844d552c4 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -127,7 +127,7 @@ private: bool daemonSynced() const; void stopRefresh(); bool isNewWallet() const; - void doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit); + bool doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit); private: diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 904338a72..0601c104e 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -43,6 +43,15 @@ namespace epee { unsigned int g_test_dbg_lock_sleep = 0; } +namespace { + template<typename Request, typename Response> + bool connect_and_invoke(const std::string& address, const std::string& path, const Request& request, Response& response) + { + epee::net_utils::http::http_simple_client client{}; + return client.set_server(address) && epee::net_utils::invoke_http_json(path, request, response, client); + } +} + namespace Monero { Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password, @@ -145,9 +154,7 @@ bool WalletManagerImpl::connected(uint32_t *version) const req_t.jsonrpc = "2.0"; req_t.id = epee::serialization::storage_entry(0); req_t.method = "get_version"; - epee::net_utils::http::http_simple_client http_client; - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client); - if (!r) + if (!connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t)) return false; if (version) @@ -193,8 +200,7 @@ bool WalletManagerImpl::checkPayment(const std::string &address_text, const std: cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req; cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(daemon_address + "/gettransactions", req, res, http_client) || + if (!connect_and_invoke(m_daemonAddress, "/gettransactions", req, res) || (res.txs.size() != 1 && res.txs_as_hex.size() != 1)) { error = tr("failed to get transaction from daemon"); @@ -312,8 +318,7 @@ uint64_t WalletManagerImpl::blockchainHeight() const cryptonote::COMMAND_RPC_GET_INFO::request ireq; cryptonote::COMMAND_RPC_GET_INFO::response ires; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires)) return 0; return ires.height; } @@ -323,8 +328,7 @@ uint64_t WalletManagerImpl::blockchainTargetHeight() const cryptonote::COMMAND_RPC_GET_INFO::request ireq; cryptonote::COMMAND_RPC_GET_INFO::response ires; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires)) return 0; return ires.target_height >= ires.height ? ires.target_height : ires.height; } @@ -334,8 +338,7 @@ uint64_t WalletManagerImpl::networkDifficulty() const cryptonote::COMMAND_RPC_GET_INFO::request ireq; cryptonote::COMMAND_RPC_GET_INFO::response ires; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires)) return 0; return ires.difficulty; } @@ -346,7 +349,7 @@ double WalletManagerImpl::miningHashRate() const cryptonote::COMMAND_RPC_MINING_STATUS::response mres; epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres)) return 0.0; if (!mres.active) return 0.0; @@ -366,7 +369,7 @@ void WalletManagerImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height req_t.id = epee::serialization::storage_entry(0); req_t.method = "hard_fork_info"; req_t.params.version = 0; - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client); + bool r = connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t); if (!r || resp_t.result.status != CORE_RPC_STATUS_OK) return; version = resp_t.result.version; @@ -378,8 +381,7 @@ uint64_t WalletManagerImpl::blockTarget() const cryptonote::COMMAND_RPC_GET_INFO::request ireq; cryptonote::COMMAND_RPC_GET_INFO::response ires; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires)) return 0; return ires.target; } @@ -389,8 +391,7 @@ bool WalletManagerImpl::isMining() const cryptonote::COMMAND_RPC_MINING_STATUS::request mreq; cryptonote::COMMAND_RPC_MINING_STATUS::response mres; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres)) return false; return mres.active; } @@ -403,8 +404,7 @@ bool WalletManagerImpl::startMining(const std::string &address, uint32_t threads mreq.miner_address = address; mreq.threads_count = threads; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/start_mining", mreq, mres, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/start_mining", mreq, mres)) return false; return mres.status == CORE_RPC_STATUS_OK; } @@ -414,8 +414,7 @@ bool WalletManagerImpl::stopMining() cryptonote::COMMAND_RPC_STOP_MINING::request mreq; cryptonote::COMMAND_RPC_STOP_MINING::response mres; - epee::net_utils::http::http_simple_client http_client; - if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/stop_mining", mreq, mres, http_client)) + if (!connect_and_invoke(m_daemonAddress, "/stop_mining", mreq, mres)) return false; return mres.status == CORE_RPC_STATUS_OK; } diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index d7f755e36..cc249b5cc 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -36,18 +36,16 @@ using namespace epee; namespace tools { -void NodeRPCProxy::init(const std::string &daemon_address) -{ - m_daemon_address = daemon_address; - - m_height = 0; - m_height_time = 0; - for (auto &slot: m_earliest_height) - slot = 0; - m_dynamic_per_kb_fee_estimate = 0; - m_dynamic_per_kb_fee_estimate_cached_height = 0; - m_dynamic_per_kb_fee_estimate_grace_blocks = 0; -} +NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex) + : m_http_client(http_client) + , m_daemon_rpc_mutex(mutex) + , m_height(0) + , m_height_time(0) + , m_earliest_height() + , m_dynamic_per_kb_fee_estimate(0) + , m_dynamic_per_kb_fee_estimate_cached_height(0) + , m_dynamic_per_kb_fee_estimate_grace_blocks(0) +{} boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height) { @@ -58,7 +56,7 @@ boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height) cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res); m_daemon_rpc_mutex.lock(); - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client); + bool r = net_utils::invoke_http_json("/getheight", req, res, m_http_client); m_daemon_rpc_mutex.unlock(); CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, res.status, "Failed to connect to daemon"); @@ -87,7 +85,7 @@ boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version, req_t.id = epee::serialization::storage_entry(0); req_t.method = "hard_fork_info"; req_t.params.version = version; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); m_daemon_rpc_mutex.unlock(); CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon"); @@ -117,7 +115,7 @@ boost::optional<std::string> NodeRPCProxy::get_dynamic_per_kb_fee_estimate(uint6 req_t.id = epee::serialization::storage_entry(0); req_t.method = "get_fee_estimate"; req_t.params.grace_blocks = grace_blocks; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); m_daemon_rpc_mutex.unlock(); CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon"); diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h index 1ae716dab..e2f42d541 100644 --- a/src/wallet/node_rpc_proxy.h +++ b/src/wallet/node_rpc_proxy.h @@ -39,10 +39,7 @@ namespace tools class NodeRPCProxy { public: - NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex): - m_http_client(http_client), m_daemon_rpc_mutex(mutex) { init(""); } - - void init(const std::string &daemon_address); + NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex); boost::optional<std::string> get_height(uint64_t &height); void set_height(uint64_t h); @@ -50,7 +47,6 @@ public: boost::optional<std::string> get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks, uint64_t &fee); private: - std::string m_daemon_address; epee::net_utils::http::http_simple_client &m_http_client; boost::mutex &m_daemon_rpc_mutex; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 4348b8a62..676f35e26 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -164,7 +164,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port); std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted)); - wallet->init(daemon_address); + wallet->init(std::move(daemon_address)); return wallet; } @@ -418,6 +418,7 @@ namespace tools // for now, limit to 30 attempts. TODO: discuss a good number to limit to. const size_t MAX_SPLIT_ATTEMPTS = 30; +constexpr const std::chrono::seconds wallet2::rpc_timeout; const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); } bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm) @@ -484,11 +485,11 @@ std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_new(const } //---------------------------------------------------------------------------------------------------- -void wallet2::init(const std::string& daemon_address, uint64_t upper_transaction_size_limit) +bool wallet2::init(std::string daemon_address, uint64_t upper_transaction_size_limit) { m_upper_transaction_size_limit = upper_transaction_size_limit; - m_daemon_address = daemon_address; - m_node_rpc_proxy.init(m_daemon_address); + m_daemon_address = std::move(daemon_address); + return m_http_client.set_server(get_daemon_address()); } //---------------------------------------------------------------------------------------------------- bool wallet2::is_deterministic() const @@ -1169,7 +1170,7 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, req.start_height = start_height; m_daemon_rpc_mutex.lock(); - bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getblocks.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT); + bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getblocks.bin"); THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getblocks.bin"); @@ -1191,7 +1192,7 @@ void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height, req.start_height = start_height; m_daemon_rpc_mutex.lock(); - bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/gethashes.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT); + bool r = net_utils::invoke_http_bin("/gethashes.bin", req, res, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gethashes.bin"); THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gethashes.bin"); @@ -1353,7 +1354,7 @@ void wallet2::update_pool_state() cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req; cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res; m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/get_transaction_pool", req, res, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_json("/get_transaction_pool", req, res, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool"); THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool"); @@ -1461,7 +1462,7 @@ void wallet2::update_pool_state() req.txs_hashes.push_back(it.id_hash); req.decode_as_json = false; m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/gettransactions", req, res, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); if (r && res.status == CORE_RPC_STATUS_OK) { @@ -2262,15 +2263,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout) if(!m_http_client.is_connected()) { - net_utils::http::url_content u; - net_utils::parse_url(m_daemon_address, u); - - if(!u.port) - { - u.port = m_testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT; - } - - if (!m_http_client.connect(u.host, std::to_string(u.port), timeout)) + if (!m_http_client.connect(std::chrono::milliseconds(timeout))) return false; } @@ -2281,7 +2274,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout) req_t.jsonrpc = "2.0"; req_t.id = epee::serialization::storage_entry(0); req_t.method = "get_version"; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); if (!r || resp_t.result.status != CORE_RPC_STATUS_OK) *version = 0; else @@ -2602,7 +2595,7 @@ void wallet2::rescan_spent() COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp); req.key_images = key_images; m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/is_key_image_spent", req, daemon_resp, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent"); @@ -2976,7 +2969,7 @@ void wallet2::commit_tx(pending_tx& ptx) req.do_not_relay = false; COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp; m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_json("/sendrawtransaction", req, daemon_send_resp, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction"); THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction"); @@ -3437,7 +3430,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> req_t.params.amounts.resize(std::distance(req_t.params.amounts.begin(), end)); req_t.params.unlocked = true; req_t.params.recent_cutoff = time(NULL) - RECENT_OUTPUT_ZONE; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "transfer_selected"); THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram"); @@ -3564,7 +3557,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> // get the keys for those m_daemon_rpc_mutex.lock(); - r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/get_outs.bin", req, daemon_resp, m_http_client, 200000); + r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, daemon_resp, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_outs.bin"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_outs.bin"); @@ -4636,7 +4629,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co req_t.params.min_count = count; req_t.params.max_count = 0; req_t.params.unlocked = unlocked; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs"); THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram"); @@ -4675,7 +4668,7 @@ uint64_t wallet2::get_num_rct_outputs() req_t.params.amounts.push_back(0); req_t.params.min_count = 0; req_t.params.max_count = 0; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_num_rct_outputs"); THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram"); @@ -4784,7 +4777,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) req_t.jsonrpc = "2.0"; req_t.id = epee::serialization::storage_entry(0); req_t.method = "get_info"; - bool ok = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + bool ok = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client); m_daemon_rpc_mutex.unlock(); if (ok) { @@ -5097,7 +5090,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag } m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/is_key_image_spent", req, daemon_resp, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent"); @@ -5407,7 +5400,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui height_mid, height_max }; - bool r = net_utils::invoke_http_bin_remote_command2(get_daemon_address() + "/getblocks_by_height.bin", req, res, m_http_client); + bool r = net_utils::invoke_http_bin("/getblocks_by_height.bin", req, res, m_http_client); if (!r || res.status != CORE_RPC_STATUS_OK) { std::ostringstream oss; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 629011800..437729075 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -61,8 +61,6 @@ #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2" -#define WALLET_RCP_CONNECTION_TIMEOUT 200000 - class Serialization_portability_wallet_Test; namespace tools @@ -96,6 +94,8 @@ namespace tools { friend class ::Serialization_portability_wallet_Test; public: + static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30); + enum RefreshType { RefreshFull, RefreshOptimizeCoinbase, @@ -107,7 +107,7 @@ namespace tools wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {} public: - static const char* tr(const char* str);// { return i18n_translate(str, "cryptonote::simple_wallet"); } + static const char* tr(const char* str); static bool has_testnet_option(const boost::program_options::variables_map& vm); static void init_options(boost::program_options::options_description& desc_params); @@ -342,8 +342,8 @@ namespace tools // free block size. TODO: fix this so that it actually takes // into account the current median block size rather than // the minimum block size. - void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0); bool deinit(); + bool init(std::string daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0); void stop() { m_run.store(false, std::memory_order_relaxed); } @@ -1018,7 +1018,7 @@ namespace tools } m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_bin("/getrandom_outs.bin", req, daemon_resp, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin"); diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 73c79c237..5666f49bf 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -159,14 +159,14 @@ bool transactions_flow_test(std::string& working_folder, epee::net_utils::http::http_simple_client http_client; COMMAND_RPC_STOP_MINING::request daemon1_req = AUTO_VAL_INIT(daemon1_req); COMMAND_RPC_STOP_MINING::response daemon1_rsp = AUTO_VAL_INIT(daemon1_rsp); - bool r = net_utils::invoke_http_json_remote_command2(daemon_addr_a + "/stop_mine", daemon1_req, daemon1_rsp, http_client, 10000); + bool r = http_client.set_server(daemon_addr_a) && net_utils::invoke_http_json("/stop_mine", daemon1_req, daemon1_rsp, http_client, std::chrono::seconds(10)); CHECK_AND_ASSERT_MES(r, false, "failed to stop mining"); COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req); COMMAND_RPC_START_MINING::response daemon_rsp = AUTO_VAL_INIT(daemon_rsp); daemon_req.miner_address = w1.get_account().get_public_address_str(false); daemon_req.threads_count = 9; - r = net_utils::invoke_http_json_remote_command2(daemon_addr_a + "/start_mining", daemon_req, daemon_rsp, http_client, 10000); + r = net_utils::invoke_http_json("/start_mining", daemon_req, daemon_rsp, http_client, std::chrono::seconds(10)); CHECK_AND_ASSERT_MES(r, false, "failed to get getrandom_outs"); CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to getrandom_outs.bin"); |