diff options
author | Riccardo Spagni <ric@spagni.net> | 2017-02-02 19:32:01 +0200 |
---|---|---|
committer | Riccardo Spagni <ric@spagni.net> | 2017-02-02 19:32:01 +0200 |
commit | 5fb3f97a55a9b8f31a69119c41557a9774deffb5 (patch) | |
tree | abf27b7fd1bf7fc164ce91f5179dbddf899112db /contrib/epee | |
parent | Merge pull request #1628 (diff) | |
parent | Updates to epee HTTP client code (diff) | |
download | monero-5fb3f97a55a9b8f31a69119c41557a9774deffb5.tar.xz |
Merge pull request #1629
c02e1cb9 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 (Lee Clagett)
Diffstat (limited to 'contrib/epee')
-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 |
4 files changed, 80 insertions, 200 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); } } |