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
This commit is contained in:
Lee Clagett 2017-01-25 00:16:05 -05:00
parent ad91ffe7e5
commit c02e1cb943
15 changed files with 172 additions and 323 deletions

View file

@ -263,7 +263,6 @@ using namespace std;
blocked_mode_client m_net_client; blocked_mode_client m_net_client;
std::string m_host_buff; std::string m_host_buff;
std::string m_port; std::string m_port;
unsigned int m_timeout;
std::string m_header_cache; std::string m_header_cache;
http_response_info m_response_info; http_response_info m_response_info;
size_t m_len_in_summary; size_t m_len_in_summary;
@ -276,23 +275,43 @@ using namespace std;
critical_section m_lock; critical_section m_lock;
public: public:
void set_host_name(const std::string& name) explicit http_simple_client()
{ : i_target_handler()
CRITICAL_REGION_LOCAL(m_lock); , m_net_client()
m_host_buff = name; , m_host_buff()
} , m_port()
bool connect(const std::string& host, int port, unsigned int timeout) , m_header_cache()
{ , m_response_info()
return connect(host, std::to_string(port), timeout); , m_len_in_summary(0)
} , m_len_in_remain(0)
bool connect(const std::string& host, const std::string& port, unsigned int timeout) , m_pcontent_encoding_handler(nullptr)
{ , m_state()
CRITICAL_REGION_LOCAL(m_lock); , m_chunked_state()
m_host_buff = host; , m_chunked_cache()
m_port = port; , m_lock()
m_timeout = timeout; {}
return m_net_client.connect(host, port, timeout, timeout); 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);
disconnect();
m_host_buff = std::move(host);
m_port = std::move(port);
}
bool connect(std::chrono::milliseconds timeout)
{
CRITICAL_REGION_LOCAL(m_lock);
return m_net_client.connect(m_host_buff, m_port, timeout);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool disconnect() bool disconnect()
@ -316,20 +335,20 @@ using namespace std;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
inline 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); 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); CRITICAL_REGION_LOCAL(m_lock);
if(!is_connected()) if(!is_connected())
{ {
MDEBUG("Reconnecting..."); MDEBUG("Reconnecting...");
if(!connect(m_host_buff, m_port, m_timeout)) if(!connect(timeout))
{ {
MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port); MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port);
return false; return false;
@ -347,27 +366,27 @@ using namespace std;
req_buff += "\r\n"; 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"); CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
if(body.size()) 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"); CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
if(ppresponse_info) if(ppresponse_info)
*ppresponse_info = &m_response_info; *ppresponse_info = &m_response_info;
m_state = reciev_machine_state_header; 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); 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: private:
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
inline bool handle_reciev() inline bool handle_reciev(std::chrono::milliseconds timeout)
{ {
CRITICAL_REGION_LOCAL(m_lock); CRITICAL_REGION_LOCAL(m_lock);
bool keep_handling = true; bool keep_handling = true;
@ -377,7 +396,7 @@ using namespace std;
{ {
if(need_more_data) if(need_more_data)
{ {
if(!m_net_client.recv(recv_buffer)) if(!m_net_client.recv(recv_buffer, timeout))
{ {
MERROR("Unexpected recv fail"); MERROR("Unexpected recv fail");
m_state = reciev_machine_state_error; m_state = reciev_machine_state_error;
@ -878,33 +897,6 @@ using namespace std;
return true; 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);
}
} }
} }
} }

View file

@ -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);
}
}
}
}

View file

@ -37,6 +37,7 @@
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/preprocessor/selection/min.hpp> #include <boost/preprocessor/selection/min.hpp>
#include <boost/lambda/bind.hpp> #include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.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 // 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 // set the deadline to positive infinity so that the actor takes no action
// until a specific deadline is set. // 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. // Start the persistent actor that checks for deadline expiry.
check_deadline(); check_deadline();
@ -111,26 +112,16 @@ namespace net_utils
shutdown(); shutdown();
} }
inline void set_recv_timeout(int reciev_timeout) inline
bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0")
{ {
m_reciev_timeout = reciev_timeout; return connect(addr, std::to_string(port), timeout, bind_ip);
} }
inline 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, const std::string& 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);
}
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")
{
m_connect_timeout = connect_timeout;
m_reciev_timeout = reciev_timeout;
m_connected = false; m_connected = false;
if(!m_reciev_timeout)
m_reciev_timeout = m_connect_timeout;
try try
{ {
m_socket.close(); 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; boost::system::error_code ec = boost::asio::error::would_block;
@ -179,7 +170,7 @@ namespace net_utils
if (!ec && m_socket.is_open()) if (!ec && m_socket.is_open())
{ {
m_connected = true; 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; return true;
}else }else
{ {
@ -231,12 +222,12 @@ namespace net_utils
inline inline
bool send(const std::string& buff) bool send(const std::string& buff, std::chrono::milliseconds timeout)
{ {
try 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 // Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the // operation. The error code is set to would_block to signal that the
@ -264,7 +255,7 @@ namespace net_utils
return false; return false;
}else }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; return false;
}else }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 inline
bool recv(std::string& buff) bool recv(std::string& buff, std::chrono::milliseconds timeout)
{ {
try try
@ -358,7 +349,7 @@ namespace net_utils
// Set a deadline for the asynchronous operation. Since this function uses // Set a deadline for the asynchronous operation. Since this function uses
// a composed operation (async_read_until), the deadline applies to the // a composed operation (async_read_until), the deadline applies to the
// entire operation, rather than individual reads from the socket. // 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 // Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the // operation. The error code is set to would_block to signal that the
@ -404,7 +395,7 @@ namespace net_utils
}else }else
{ {
MTRACE("READ ENDS: Success. bytes_tr: " << bytes_transfered); 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) /*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 try
@ -440,7 +431,7 @@ namespace net_utils
// Set a deadline for the asynchronous operation. Since this function uses // Set a deadline for the asynchronous operation. Since this function uses
// a composed operation (async_read_until), the deadline applies to the // a composed operation (async_read_until), the deadline applies to the
// entire operation, rather than individual reads from the socket. // 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 // Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the // operation. The error code is set to would_block to signal that the
@ -477,7 +468,7 @@ namespace net_utils
return false; return false;
}else }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()) if(bytes_transfered != buff.size())
@ -539,7 +530,7 @@ namespace net_utils
// Check whether the deadline has passed. We compare the deadline against // Check whether the deadline has passed. We compare the deadline against
// the current time since a new asynchronous operation may have moved the // the current time since a new asynchronous operation may have moved the
// deadline before this actor had a chance to run. // 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 // 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
@ -550,7 +541,7 @@ namespace net_utils
// 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
// infinity so that the actor takes no action until a new deadline is set. // 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. // Put the actor back to sleep.
@ -562,11 +553,9 @@ namespace net_utils
protected: protected:
boost::asio::io_service m_io_service; boost::asio::io_service m_io_service;
boost::asio::ip::tcp::socket m_socket; boost::asio::ip::tcp::socket m_socket;
int m_connect_timeout;
int m_reciev_timeout;
bool m_initialized; bool m_initialized;
bool m_connected; bool m_connected;
boost::asio::deadline_timer m_deadline; boost::asio::steady_timer m_deadline;
volatile uint32_t m_shutdowned; volatile uint32_t m_shutdowned;
}; };

View file

@ -35,28 +35,28 @@ namespace epee
namespace net_utils namespace net_utils
{ {
template<class t_request, class t_response, class t_transport> 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; std::string req_param;
if(!serialization::store_t_to_json(out_struct, req_param)) if(!serialization::store_t_to_json(out_struct, req_param))
return false; return false;
const http::http_response_info* pri = NULL; 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; 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; return false;
} }
if(pri->m_response_code != 200) 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; return false;
} }
@ -66,28 +66,28 @@ namespace epee
template<class t_request, class t_response, class t_transport> 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; std::string req_param;
if(!serialization::store_t_to_binary(out_struct, req_param)) if(!serialization::store_t_to_binary(out_struct, req_param))
return false; return false;
const http::http_response_info* pri = NULL; 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; 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; return false;
} }
if(pri->m_response_code != 200) 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; return false;
} }
@ -95,15 +95,15 @@ namespace epee
} }
template<class t_request, class t_response, class t_transport> 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); epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t);
req_t.jsonrpc = "2.0"; req_t.jsonrpc = "2.0";
req_t.id = req_id; req_t.id = req_id;
req_t.method = method_name; req_t.method = std::move(method_name);
req_t.params = out_struct; req_t.params = out_struct;
epee::json_rpc::response<t_response, epee::json_rpc::error> resp_t = AUTO_VAL_INIT(resp_t); 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; return false;
} }
@ -117,9 +117,9 @@ namespace epee
} }
template<class t_command, class t_transport> 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);
} }
} }

View file

@ -28,6 +28,7 @@
#pragma once #pragma once
#include <chrono>
#include "string_tools.h" #include "string_tools.h"
#include "net/http_client.h" #include "net/http_client.h"
@ -38,20 +39,16 @@ private:
epee::net_utils::http::http_simple_client * mp_http_client; epee::net_utils::http::http_simple_client * mp_http_client;
bool m_ok; bool m_ok;
public: 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( t_http_connection(epee::net_utils::http::http_simple_client* p_http_client)
epee::net_utils::http::http_simple_client * p_http_client
, uint32_t ip
, uint16_t port
)
: mp_http_client(p_http_client) : mp_http_client(p_http_client)
, m_ok(false) , m_ok(false)
{ {
// TODO fix http client so that it accepts properly typed arguments m_ok = mp_http_client->connect(TIMEOUT());
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);
} }
~t_http_connection() ~t_http_connection()

View file

@ -34,7 +34,6 @@
#include "storages/http_abstract_invoke.h" #include "storages/http_abstract_invoke.h"
#include "net/http_client.h" #include "net/http_client.h"
#include "string_tools.h" #include "string_tools.h"
#include <boost/lexical_cast.hpp>
namespace tools namespace tools
{ {
@ -42,27 +41,16 @@ namespace tools
{ {
private: private:
epee::net_utils::http::http_simple_client m_http_client; epee::net_utils::http::http_simple_client m_http_client;
uint32_t m_ip;
uint16_t m_port;
public: public:
t_rpc_client( t_rpc_client(
uint32_t ip uint32_t ip
, uint16_t port , uint16_t port
) )
: m_http_client{} : m_http_client{}
, m_ip{ip}
, m_port{port}
{}
std::string build_url(std::string const & relative_url) const
{ {
std::string result = m_http_client.set_server(
"http://" epee::string_tools::get_ip_string_from_int32(ip), std::to_string(port)
+ epee::string_tools::get_ip_string_from_int32(m_ip) );
+ ":"
+ boost::lexical_cast<std::string>(m_port)
+ relative_url;
return result;
} }
template <typename T_req, typename T_res> template <typename T_req, typename T_res>
@ -72,8 +60,7 @@ namespace tools
, std::string const & method_name , std::string const & method_name
) )
{ {
std::string rpc_url = build_url("/json_rpc"); t_http_connection connection(&m_http_client);
t_http_connection connection(&m_http_client, m_ip, m_port);
bool ok = connection.is_open(); bool ok = connection.is_open();
if (!ok) if (!ok)
@ -81,7 +68,7 @@ namespace tools
fail_msg_writer() << "Couldn't connect to daemon"; fail_msg_writer() << "Couldn't connect to daemon";
return false; 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) if (!ok)
{ {
fail_msg_writer() << "Daemon request failed"; fail_msg_writer() << "Daemon request failed";
@ -101,11 +88,10 @@ namespace tools
, std::string const & fail_msg , std::string const & fail_msg
) )
{ {
std::string rpc_url = build_url("/json_rpc"); t_http_connection connection(&m_http_client);
t_http_connection connection(&m_http_client, m_ip, m_port);
bool ok = connection.is_open(); 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) if (!ok)
{ {
fail_msg_writer() << "Couldn't connect to daemon"; fail_msg_writer() << "Couldn't connect to daemon";
@ -130,11 +116,10 @@ namespace tools
, std::string const & fail_msg , std::string const & fail_msg
) )
{ {
std::string rpc_url = build_url(relative_url); t_http_connection connection(&m_http_client);
t_http_connection connection(&m_http_client, m_ip, m_port);
bool ok = connection.is_open(); 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) if (!ok)
{ {
fail_msg_writer() << "Couldn't connect to daemon"; fail_msg_writer() << "Couldn't connect to daemon";
@ -153,7 +138,7 @@ namespace tools
bool check_connection() 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(); return connection.is_open();
} }
}; };

View file

@ -1163,6 +1163,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
} }
catch (const std::exception &e) { } catch (const std::exception &e) { }
m_http_client.set_server(m_wallet->get_daemon_address());
m_wallet->callback(this); m_wallet->callback(this);
return true; return true;
} }
@ -1560,7 +1561,7 @@ bool simple_wallet::start_mining(const std::vector<std::string>& args)
} }
COMMAND_RPC_START_MINING::response res; 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); std::string err = interpret_rpc_response(r, res.status);
if (err.empty()) if (err.empty())
success_msg_writer() << tr("Mining started in daemon"); 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); assert(m_wallet);
COMMAND_RPC_STOP_MINING::request req; COMMAND_RPC_STOP_MINING::request req;
COMMAND_RPC_STOP_MINING::response res; 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); std::string err = interpret_rpc_response(r, res.status);
if (err.empty()) if (err.empty())
success_msg_writer() << tr("Mining stopped in daemon"); 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); assert(m_wallet);
COMMAND_RPC_SAVE_BC::request req; COMMAND_RPC_SAVE_BC::request req;
COMMAND_RPC_SAVE_BC::response res; 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); std::string err = interpret_rpc_response(r, res.status);
if (err.empty()) if (err.empty())
success_msg_writer() << tr("Blockchain saved"); 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::request req;
COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>(); 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); err = interpret_rpc_response(r, res.status);
return res.height; 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]; req.outputs[j].index = absolute_offsets[j];
} }
COMMAND_RPC_GET_OUTPUTS_BIN::response res = AUTO_VAL_INIT(res); 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); err = interpret_rpc_response(r, res.status);
if (!err.empty()) 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::request req;
COMMAND_RPC_GET_TRANSACTIONS::response res; COMMAND_RPC_GET_TRANSACTIONS::response res;
req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); 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)) (res.txs.size() != 1 && res.txs_as_hex.size() != 1))
{ {
fail_msg_writer() << tr("failed to get transaction from daemon"); fail_msg_writer() << tr("failed to get transaction from daemon");

View file

@ -516,12 +516,12 @@ string WalletImpl::keysFilename() const
bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit)
{ {
clearStatus(); clearStatus();
doInit(daemon_address, upper_transaction_size_limit); if (!doInit(daemon_address, upper_transaction_size_limit))
return false;
bool result = this->refresh(); bool result = this->refresh();
// enabling background refresh thread // enabling background refresh thread
startRefresh(); startRefresh();
return result; return result;
} }
void WalletImpl::initAsync(const string &daemon_address, uint64_t upper_transaction_size_limit) 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(); 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) // 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 // 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); this->setTrustedDaemon(false);
m_refreshIntervalMillis = DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS; 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) 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)

View file

@ -127,7 +127,7 @@ private:
bool daemonSynced() const; bool daemonSynced() const;
void stopRefresh(); void stopRefresh();
bool isNewWallet() const; 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: private:

View file

@ -43,6 +43,15 @@ namespace epee {
unsigned int g_test_dbg_lock_sleep = 0; 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 { namespace Monero {
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password, 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.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0); req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_version"; req_t.method = "get_version";
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t))
bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client);
if (!r)
return false; return false;
if (version) 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::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res; cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/gettransactions", req, res) ||
if (!epee::net_utils::invoke_http_json_remote_command2(daemon_address + "/gettransactions", req, res, http_client) ||
(res.txs.size() != 1 && res.txs_as_hex.size() != 1)) (res.txs.size() != 1 && res.txs_as_hex.size() != 1))
{ {
error = tr("failed to get transaction from daemon"); 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::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires; cryptonote::COMMAND_RPC_GET_INFO::response ires;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
return 0; return 0;
return ires.height; return ires.height;
} }
@ -323,8 +328,7 @@ uint64_t WalletManagerImpl::blockchainTargetHeight() const
cryptonote::COMMAND_RPC_GET_INFO::request ireq; cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires; cryptonote::COMMAND_RPC_GET_INFO::response ires;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
return 0; return 0;
return ires.target_height >= ires.height ? ires.target_height : ires.height; 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::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires; cryptonote::COMMAND_RPC_GET_INFO::response ires;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
return 0; return 0;
return ires.difficulty; return ires.difficulty;
} }
@ -346,7 +349,7 @@ double WalletManagerImpl::miningHashRate() const
cryptonote::COMMAND_RPC_MINING_STATUS::response mres; cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
epee::net_utils::http::http_simple_client http_client; 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; return 0.0;
if (!mres.active) if (!mres.active)
return 0.0; 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.id = epee::serialization::storage_entry(0);
req_t.method = "hard_fork_info"; req_t.method = "hard_fork_info";
req_t.params.version = 0; 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) if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
return; return;
version = resp_t.result.version; 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::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires; cryptonote::COMMAND_RPC_GET_INFO::response ires;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
return 0; return 0;
return ires.target; return ires.target;
} }
@ -389,8 +391,7 @@ bool WalletManagerImpl::isMining() const
cryptonote::COMMAND_RPC_MINING_STATUS::request mreq; cryptonote::COMMAND_RPC_MINING_STATUS::request mreq;
cryptonote::COMMAND_RPC_MINING_STATUS::response mres; cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client))
return false; return false;
return mres.active; return mres.active;
} }
@ -403,8 +404,7 @@ bool WalletManagerImpl::startMining(const std::string &address, uint32_t threads
mreq.miner_address = address; mreq.miner_address = address;
mreq.threads_count = threads; mreq.threads_count = threads;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/start_mining", mreq, mres))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/start_mining", mreq, mres, http_client))
return false; return false;
return mres.status == CORE_RPC_STATUS_OK; 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::request mreq;
cryptonote::COMMAND_RPC_STOP_MINING::response mres; cryptonote::COMMAND_RPC_STOP_MINING::response mres;
epee::net_utils::http::http_simple_client http_client; if (!connect_and_invoke(m_daemonAddress, "/stop_mining", mreq, mres))
if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/stop_mining", mreq, mres, http_client))
return false; return false;
return mres.status == CORE_RPC_STATUS_OK; return mres.status == CORE_RPC_STATUS_OK;
} }

View file

@ -36,18 +36,16 @@ using namespace epee;
namespace tools namespace tools
{ {
void NodeRPCProxy::init(const std::string &daemon_address) NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex)
{ : m_http_client(http_client)
m_daemon_address = daemon_address; , m_daemon_rpc_mutex(mutex)
, m_height(0)
m_height = 0; , m_height_time(0)
m_height_time = 0; , m_earliest_height()
for (auto &slot: m_earliest_height) , m_dynamic_per_kb_fee_estimate(0)
slot = 0; , m_dynamic_per_kb_fee_estimate_cached_height(0)
m_dynamic_per_kb_fee_estimate = 0; , m_dynamic_per_kb_fee_estimate_grace_blocks(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) 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); cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res);
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); 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"); 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.id = epee::serialization::storage_entry(0);
req_t.method = "hard_fork_info"; req_t.method = "hard_fork_info";
req_t.params.version = version; 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(); m_daemon_rpc_mutex.unlock();
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); 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"); 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.id = epee::serialization::storage_entry(0);
req_t.method = "get_fee_estimate"; req_t.method = "get_fee_estimate";
req_t.params.grace_blocks = grace_blocks; 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(); m_daemon_rpc_mutex.unlock();
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); 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"); CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon");

View file

@ -39,10 +39,7 @@ namespace tools
class NodeRPCProxy class NodeRPCProxy
{ {
public: public:
NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex): 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);
boost::optional<std::string> get_height(uint64_t &height); boost::optional<std::string> get_height(uint64_t &height);
void set_height(uint64_t h); 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); boost::optional<std::string> get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks, uint64_t &fee);
private: private:
std::string m_daemon_address;
epee::net_utils::http::http_simple_client &m_http_client; epee::net_utils::http::http_simple_client &m_http_client;
boost::mutex &m_daemon_rpc_mutex; boost::mutex &m_daemon_rpc_mutex;

View file

@ -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); daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted)); std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted));
wallet->init(daemon_address); wallet->init(std::move(daemon_address));
return wallet; return wallet;
} }
@ -418,6 +418,7 @@ namespace tools
// for now, limit to 30 attempts. TODO: discuss a good number to limit to. // for now, limit to 30 attempts. TODO: discuss a good number to limit to.
const size_t MAX_SPLIT_ATTEMPTS = 30; 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"); } 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) 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_upper_transaction_size_limit = upper_transaction_size_limit;
m_daemon_address = daemon_address; m_daemon_address = std::move(daemon_address);
m_node_rpc_proxy.init(m_daemon_address); return m_http_client.set_server(get_daemon_address());
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
bool wallet2::is_deterministic() const 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; req.start_height = start_height;
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getblocks.bin"); 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"); 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; req.start_height = start_height;
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gethashes.bin"); 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"); 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::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res; cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool"); 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"); 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.txs_hashes.push_back(it.id_hash);
req.decode_as_json = false; req.decode_as_json = false;
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
if (r && res.status == CORE_RPC_STATUS_OK) 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()) if(!m_http_client.is_connected())
{ {
net_utils::http::url_content u; if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
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))
return false; return false;
} }
@ -2281,7 +2274,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
req_t.jsonrpc = "2.0"; req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0); req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_version"; 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) if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
*version = 0; *version = 0;
else else
@ -2602,7 +2595,7 @@ void wallet2::rescan_spent()
COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp); COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
req.key_images = key_images; req.key_images = key_images;
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent"); 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"); 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; req.do_not_relay = false;
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp; COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction"); 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"); 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.amounts.resize(std::distance(req_t.params.amounts.begin(), end));
req_t.params.unlocked = true; req_t.params.unlocked = true;
req_t.params.recent_cutoff = time(NULL) - RECENT_OUTPUT_ZONE; 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "transfer_selected"); 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"); 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 // get the keys for those
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_outs.bin"); 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"); 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.min_count = count;
req_t.params.max_count = 0; req_t.params.max_count = 0;
req_t.params.unlocked = unlocked; 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs"); 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"); 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.amounts.push_back(0);
req_t.params.min_count = 0; req_t.params.min_count = 0;
req_t.params.max_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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_num_rct_outputs"); 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"); 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.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0); req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_info"; 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(); m_daemon_rpc_mutex.unlock();
if (ok) 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(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent"); 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"); 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_mid,
height_max 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) if (!r || res.status != CORE_RPC_STATUS_OK)
{ {
std::ostringstream oss; std::ostringstream oss;

View file

@ -61,8 +61,6 @@
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2" #define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
#define WALLET_RCP_CONNECTION_TIMEOUT 200000
class Serialization_portability_wallet_Test; class Serialization_portability_wallet_Test;
namespace tools namespace tools
@ -96,6 +94,8 @@ namespace tools
{ {
friend class ::Serialization_portability_wallet_Test; friend class ::Serialization_portability_wallet_Test;
public: public:
static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30);
enum RefreshType { enum RefreshType {
RefreshFull, RefreshFull,
RefreshOptimizeCoinbase, 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) {} 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: 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 bool has_testnet_option(const boost::program_options::variables_map& vm);
static void init_options(boost::program_options::options_description& desc_params); 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 // free block size. TODO: fix this so that it actually takes
// into account the current median block size rather than // into account the current median block size rather than
// the minimum block size. // the minimum block size.
void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
bool deinit(); 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); } void stop() { m_run.store(false, std::memory_order_relaxed); }
@ -1018,7 +1018,7 @@ namespace tools
} }
m_daemon_rpc_mutex.lock(); 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(); m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin"); 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"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin");

View file

@ -159,14 +159,14 @@ bool transactions_flow_test(std::string& working_folder,
epee::net_utils::http::http_simple_client http_client; 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::request daemon1_req = AUTO_VAL_INIT(daemon1_req);
COMMAND_RPC_STOP_MINING::response daemon1_rsp = AUTO_VAL_INIT(daemon1_rsp); 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"); 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::request daemon_req = AUTO_VAL_INIT(daemon_req);
COMMAND_RPC_START_MINING::response daemon_rsp = AUTO_VAL_INIT(daemon_rsp); 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.miner_address = w1.get_account().get_public_address_str(false);
daemon_req.threads_count = 9; 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(r, false, "failed to get getrandom_outs");
CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to getrandom_outs.bin"); CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to getrandom_outs.bin");