diff options
Diffstat (limited to 'contrib/epee')
-rw-r--r-- | contrib/epee/include/console_handler.h | 1 | ||||
-rw-r--r-- | contrib/epee/include/net/abstract_tcp_server2.inl | 22 | ||||
-rw-r--r-- | contrib/epee/include/net/http_client.h | 9 | ||||
-rw-r--r-- | contrib/epee/include/net/net_helper.h | 134 | ||||
-rw-r--r-- | contrib/epee/include/net/net_utils_base.h | 6 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_base.h | 1 | ||||
-rw-r--r-- | contrib/epee/src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | contrib/epee/src/connection_basic.cpp | 11 | ||||
-rw-r--r-- | contrib/epee/src/net_helper.cpp | 54 |
9 files changed, 157 insertions, 84 deletions
diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 6e7efd1d7..e07e16d91 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -357,6 +357,7 @@ eof: if (m_stdin_reader.eos()) { MGINFO("EOF on stdin, exiting"); + std::cout << std::endl; break; } if (!get_line_ret) diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index f5548c585..67c63cca5 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -58,6 +58,7 @@ #define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes #define TIMEOUT_EXTRA_MS_PER_BYTE 0.2 + PRAGMA_WARNING_PUSH namespace epee { @@ -99,7 +100,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_connection_type( connection_type ), m_throttle_speed_in("speed_in", "throttle_speed_in"), m_throttle_speed_out("speed_out", "throttle_speed_out"), - m_timer(socket_.get_io_service()), + m_timer(GET_IO_SERVICE(socket_)), m_local(false), m_ready_to_close(false) { @@ -243,7 +244,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) template<class t_protocol_handler> boost::asio::io_service& connection<t_protocol_handler>::get_io_service() { - return socket().get_io_service(); + return GET_IO_SERVICE(socket()); } //--------------------------------------------------------------------------------- template<class t_protocol_handler> @@ -487,7 +488,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) if(!m_is_multithreaded) { //single thread model, we can wait in blocked call - size_t cnt = socket().get_io_service().run_one(); + size_t cnt = GET_IO_SERVICE(socket()).run_one(); if(!cnt)//service is going to quit return false; }else @@ -497,7 +498,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) //if no handlers were called //TODO: Maybe we need to have have critical section + event + callback to upper protocol to //ask it inside(!) critical region if we still able to go in event wait... - size_t cnt = socket().get_io_service().poll_one(); + size_t cnt = GET_IO_SERVICE(socket()).poll_one(); if(!cnt) misc_utils::sleep_no_w(1); } @@ -670,9 +671,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) CHECK_AND_ASSERT_MES( size_now == m_send_que.front().size(), false, "Unexpected queue size"); reset_timer(get_default_timeout(), false); async_write(boost::asio::buffer(m_send_que.front().data(), size_now ) , - //strand_.wrap( + strand_.wrap( boost::bind(&connection<t_protocol_handler>::handle_write, self, _1, _2) - //) + ) ); //_dbg3("(chunk): " << size_now); //logger_handle_net_write(size_now); @@ -761,8 +762,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) // Initiate graceful connection closure. m_timer.cancel(); boost::system::error_code ignored_ec; + if (m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled) + socket_.shutdown(ignored_ec); socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - socket().close(); if (!m_host.empty()) { try { host_count(m_host, -1); } catch (...) { /* ignore */ } @@ -855,9 +857,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) do_send_handler_write_from_queue(e, m_send_que.front().size() , m_send_que.size()); // (((H))) CHECK_AND_ASSERT_MES( size_now == m_send_que.front().size(), void(), "Unexpected queue size"); async_write(boost::asio::buffer(m_send_que.front().data(), size_now) , - // strand_.wrap( + strand_.wrap( boost::bind(&connection<t_protocol_handler>::handle_write, connection<t_protocol_handler>::shared_from_this(), _1, _2) - // ) + ) ); //_dbg3("(normal)" << size_now); } @@ -1207,7 +1209,7 @@ POP_WARNINGS template<class t_protocol_handler> bool boosted_tcp_server<t_protocol_handler>::add_connection(t_connection_context& out, boost::asio::ip::tcp::socket&& sock, network_address real_remote, epee::net_utils::ssl_support_t ssl_support) { - if(std::addressof(get_io_service()) == std::addressof(sock.get_io_service())) + if(std::addressof(get_io_service()) == std::addressof(GET_IO_SERVICE(sock))) { connection_ptr conn(new connection<t_protocol_handler>(std::move(sock), m_state, m_connection_type, ssl_support, m_ssl_context)); if(conn->start(false, 1 < m_threads_count, std::move(real_remote))) diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index 58a8e6888..f0425278d 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -327,10 +327,17 @@ namespace net_utils m_net_client.set_ssl(m_ssl_support, m_ssl_private_key_and_certificate_path, m_ssl_allowed_certificates, m_ssl_allowed_fingerprints, m_ssl_allow_any_cert); } + template<typename F> + void set_connector(F connector) + { + CRITICAL_REGION_LOCAL(m_lock); + m_net_client.set_connector(std::move(connector)); + } + bool connect(std::chrono::milliseconds timeout) { CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.connect(m_host_buff, m_port, timeout, "0.0.0.0"); + return m_net_client.connect(m_host_buff, m_port, timeout); } //--------------------------------------------------------------------------- bool disconnect() diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 742cf916e..aa3df7160 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -33,12 +33,17 @@ //#include <Ws2tcpip.h> #include <string> #include <boost/version.hpp> -#include <boost/asio.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/read.hpp> #include <boost/asio/ssl.hpp> #include <boost/asio/steady_timer.hpp> +#include <boost/thread/future.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/lambda.hpp> #include <boost/interprocess/detail/atomic.hpp> +#include <boost/system/error_code.hpp> +#include <functional> #include "net/net_utils_base.h" #include "net/net_ssl.h" #include "misc_language.h" @@ -55,6 +60,12 @@ namespace epee { namespace net_utils { + struct direct_connect + { + boost::unique_future<boost::asio::ip::tcp::socket> + operator()(const std::string& addr, const std::string& port, boost::asio::steady_timer&) const; + }; + class blocked_mode_client { @@ -85,31 +96,38 @@ namespace net_utils ref_bytes_transferred = bytes_transferred; } }; - + public: inline - blocked_mode_client():m_initialized(false), - m_connected(false), - m_deadline(m_io_service), - m_shutdowned(0), - m_ssl_support(epee::net_utils::ssl_support_t::e_ssl_support_autodetect), - m_ctx({boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}}), - m_ssl_socket(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service,m_ctx.context)) + blocked_mode_client() : + m_io_service(), + m_ctx({boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}}), + m_connector(direct_connect{}), + m_ssl_socket(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service, m_ctx.context)), + m_ssl_support(epee::net_utils::ssl_support_t::e_ssl_support_autodetect), + m_initialized(true), + m_connected(false), + m_deadline(m_io_service), + m_shutdowned(0) { - - - m_initialized = true; + } + /*! The first/second parameters are host/port respectively. The third + parameter is for setting the timeout callback - the timer is + already set by the caller, the callee only needs to set the + behavior. - // 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(std::chrono::steady_clock::time_point::max()); + Additional asynchronous operations should be queued using the + `io_service` from the timer. The implementation should assume + multi-threaded I/O processing. - // Start the persistent actor that checks for deadline expiry. - check_deadline(); + If the callee cannot start an asynchronous operation, an exception + should be thrown to signal an immediate failure. + + The return value is a future to a connected socket. Asynchronous + failures should use the `set_exception` method. */ + using connect_func = boost::unique_future<boost::asio::ip::tcp::socket>(const std::string&, const std::string&, boost::asio::steady_timer&); - } inline ~blocked_mode_client() { @@ -128,33 +146,28 @@ namespace net_utils } inline - bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0") + bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout) { - return connect(addr, std::to_string(port), timeout, bind_ip); + return connect(addr, std::to_string(port), timeout); } inline - try_connect_result_t try_connect(const std::string& addr, const std::string& port, const boost::asio::ip::tcp::endpoint &remote_endpoint, std::chrono::milliseconds timeout, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support) + try_connect_result_t try_connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, epee::net_utils::ssl_support_t ssl_support) { - m_ssl_socket->next_layer().open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(addr.c_str()), 0); - m_ssl_socket->next_layer().bind(local_endpoint); - } - - m_deadline.expires_from_now(timeout); + boost::unique_future<boost::asio::ip::tcp::socket> connection = m_connector(addr, port, m_deadline); + for (;;) + { + m_io_service.reset(); + m_io_service.run_one(); - boost::system::error_code ec = boost::asio::error::would_block; - - m_ssl_socket->next_layer().async_connect(remote_endpoint, boost::lambda::var(ec) = boost::lambda::_1); - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); + if (connection.is_ready()) + break; } - - if (!ec && m_ssl_socket->next_layer().is_open()) + + m_ssl_socket->next_layer() = connection.get(); + m_deadline.cancel(); + if (m_ssl_socket->next_layer().is_open()) { m_connected = true; m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); @@ -183,14 +196,14 @@ namespace net_utils return CONNECT_SUCCESS; }else { - MWARNING("Some problems at connect, message: " << ec.message()); + MWARNING("Some problems at connect, expected open socket"); return CONNECT_FAILURE; } } inline - bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0") + bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout) { m_connected = false; try @@ -205,25 +218,7 @@ namespace net_utils // Get a list of endpoints corresponding to the server name. - ////////////////////////////////////////////////////////////////////////// - - boost::asio::ip::tcp::resolver resolver(m_io_service); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << addr); - return false; - } - - ////////////////////////////////////////////////////////////////////////// - - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - try_connect_result_t try_connect_result = try_connect(addr, port, remote_endpoint, timeout, bind_ip, m_ssl_support); + try_connect_result_t try_connect_result = try_connect(addr, port, timeout, m_ssl_support); if (try_connect_result == CONNECT_FAILURE) return false; if (m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) @@ -233,7 +228,7 @@ namespace net_utils { MERROR("SSL handshake failed on an autodetect connection, reconnecting without SSL"); m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_disabled; - if (try_connect(addr, port, remote_endpoint, timeout, bind_ip, m_ssl_support) != CONNECT_SUCCESS) + if (try_connect(addr, port, timeout, m_ssl_support) != CONNECT_SUCCESS) return false; } } @@ -251,6 +246,11 @@ namespace net_utils return true; } + //! Change the connection routine (proxy, etc.) + void set_connector(std::function<connect_func> connector) + { + m_connector = std::move(connector); + } inline bool disconnect() @@ -265,7 +265,6 @@ namespace net_utils m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both); } } - catch(const boost::system::system_error& /*er*/) { //LOG_ERROR("Some problems at disconnect, message: " << er.what()); @@ -304,6 +303,7 @@ namespace net_utils // Block until the asynchronous operation has completed. while (ec == boost::asio::error::would_block) { + m_io_service.reset(); m_io_service.run_one(); } @@ -433,6 +433,7 @@ namespace net_utils // Block until the asynchronous operation has completed. while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) { + m_io_service.reset(); m_io_service.run_one(); } @@ -573,10 +574,6 @@ namespace net_utils return true; } - void set_connected(bool connected) - { - m_connected = connected; - } boost::asio::io_service& get_io_service() { return m_io_service; @@ -619,6 +616,7 @@ namespace net_utils m_ssl_socket->async_shutdown(boost::lambda::var(ec) = boost::lambda::_1); while (ec == boost::asio::error::would_block) { + m_io_service.reset(); m_io_service.run_one(); } // Ignore "short read" error @@ -665,11 +663,8 @@ namespace net_utils boost::asio::io_service m_io_service; epee::net_utils::ssl_context_t m_ctx; std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_ssl_socket; + std::function<connect_func> m_connector; epee::net_utils::ssl_support_t m_ssl_support; - std::string m_ssl_private_key; - std::string m_ssl_certificate; - std::list<std::string> m_ssl_allowed_certificates; - bool m_ssl_allow_any_cerl; bool m_initialized; bool m_connected; boost::asio::steady_timer m_deadline; @@ -790,3 +785,4 @@ namespace net_utils }; } } + diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index 7b5b07ef2..50536f63b 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -44,6 +44,12 @@ #define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) #endif +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s).get_io_service()) +#endif + namespace net { class tor_address; diff --git a/contrib/epee/include/storages/portable_storage_base.h b/contrib/epee/include/storages/portable_storage_base.h index da84fd8ea..ca7c81ddc 100644 --- a/contrib/epee/include/storages/portable_storage_base.h +++ b/contrib/epee/include/storages/portable_storage_base.h @@ -82,6 +82,7 @@ namespace epee struct array_entry_t { array_entry_t():m_it(m_array.end()){} + array_entry_t(const array_entry_t& other):m_array(other.m_array), m_it(m_array.end()){} const t_entry_type* get_first_val() const { diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index 0787a9d08..2465afebb 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -26,8 +26,9 @@ # 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. -add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c +add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp) + if (USE_READLINE AND GNU_READLINE_FOUND) add_library(epee_readline STATIC readline_buffer.cpp) endif() diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 83db171d8..cafc08ead 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -47,6 +47,12 @@ // TODO: #include "net/network_throttle-detail.hpp" +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s).get_io_service()) +#endif + #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net.conn" @@ -117,8 +123,8 @@ connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, boost::s : m_stats(std::move(stats)), mI( new connection_basic_pimpl("peer") ), - strand_(sock.get_io_service()), - socket_(sock.get_io_service(), ssl_context.context), + strand_(GET_IO_SERVICE(sock)), + socket_(GET_IO_SERVICE(sock), ssl_context.context), m_want_close_connection(false), m_was_shutdown(false), m_ssl_support(ssl_support), @@ -167,7 +173,6 @@ connection_basic::~connection_basic() noexcept(false) { std::string remote_addr_str = "?"; try { boost::system::error_code e; remote_addr_str = socket().remote_endpoint(e).address().to_string(); } catch(...){} ; _note("Destructing connection #"<<mI->m_peer_number << " to " << remote_addr_str); -try { throw 0; } catch(...){} } void connection_basic::set_rate_up_limit(uint64_t limit) { diff --git a/contrib/epee/src/net_helper.cpp b/contrib/epee/src/net_helper.cpp new file mode 100644 index 000000000..3543f5716 --- /dev/null +++ b/contrib/epee/src/net_helper.cpp @@ -0,0 +1,54 @@ +#include "net/net_helper.h" + +namespace epee +{ +namespace net_utils +{ + boost::unique_future<boost::asio::ip::tcp::socket> + direct_connect::operator()(const std::string& addr, const std::string& port, boost::asio::steady_timer& timeout) const + { + // Get a list of endpoints corresponding to the server name. + ////////////////////////////////////////////////////////////////////////// + boost::asio::ip::tcp::resolver resolver(GET_IO_SERVICE(timeout)); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name); + boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + boost::asio::ip::tcp::resolver::iterator end; + if(iterator == end) // Documentation states that successful call is guaranteed to be non-empty + throw boost::system::system_error{boost::asio::error::fault, "Failed to resolve " + addr}; + + ////////////////////////////////////////////////////////////////////////// + + struct new_connection + { + boost::promise<boost::asio::ip::tcp::socket> result_; + boost::asio::ip::tcp::socket socket_; + + explicit new_connection(boost::asio::io_service& io_service) + : result_(), socket_(io_service) + {} + }; + + const auto shared = std::make_shared<new_connection>(GET_IO_SERVICE(timeout)); + timeout.async_wait([shared] (boost::system::error_code error) + { + if (error != boost::system::errc::operation_canceled && shared && shared->socket_.is_open()) + { + shared->socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both); + shared->socket_.close(); + } + }); + shared->socket_.async_connect(*iterator, [shared] (boost::system::error_code error) + { + if (shared) + { + if (error) + shared->result_.set_exception(boost::system::system_error{error}); + else + shared->result_.set_value(std::move(shared->socket_)); + } + }); + return shared->result_.get_future(); + } +} +} + |