aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee/include/net/net_helper.h
diff options
context:
space:
mode:
authorLee Clagett <code@leeclagett.com>2019-01-23 21:37:43 +0000
committerLee Clagett <code@leeclagett.com>2019-03-25 01:35:13 +0000
commit7acfa9f3cc7b52c0f4776dde3c3f80674cc3306f (patch)
tree5d1903ab4b132c137b1bb838037f024d6fb8b0d3 /contrib/epee/include/net/net_helper.h
parentMerge pull request #5286 (diff)
downloadmonero-7acfa9f3cc7b52c0f4776dde3c3f80674cc3306f.tar.xz
Added socks proxy (tor/i2pd/kovri) support to wallet
Diffstat (limited to 'contrib/epee/include/net/net_helper.h')
-rw-r--r--contrib/epee/include/net/net_helper.h134
1 files changed, 65 insertions, 69 deletions
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
};
}
}
+