mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
Added socks proxy (tor/i2pd/kovri) support to wallet
This commit is contained in:
parent
e4b049da05
commit
7acfa9f3cc
21 changed files with 505 additions and 98 deletions
|
@ -58,11 +58,6 @@
|
|||
#define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes
|
||||
#define TIMEOUT_EXTRA_MS_PER_BYTE 0.2
|
||||
|
||||
#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
|
||||
|
||||
PRAGMA_WARNING_PUSH
|
||||
namespace epee
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
// 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());
|
||||
|
||||
// Start the persistent actor that checks for deadline expiry.
|
||||
check_deadline();
|
||||
|
||||
}
|
||||
|
||||
/*! 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.
|
||||
|
||||
Additional asynchronous operations should be queued using the
|
||||
`io_service` from the timer. The implementation should assume
|
||||
multi-threaded I/O processing.
|
||||
|
||||
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
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
54
contrib/epee/src/net_helper.cpp
Normal file
54
contrib/epee/src/net_helper.cpp
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue