aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee/include/net
diff options
context:
space:
mode:
authorLee Clagett <code@leeclagett.com>2018-12-16 17:57:44 +0000
committerLee Clagett <code@leeclagett.com>2019-01-28 23:56:33 +0000
commit973403bc9f54ab0722b67a3c76ab6e7bafbfeedc (patch)
tree01f74938dc99a56c5d20840baa9bce66142847ae /contrib/epee/include/net
parentMerge pull request #5062 (diff)
downloadmonero-973403bc9f54ab0722b67a3c76ab6e7bafbfeedc.tar.xz
Adding initial support for broadcasting transactions over Tor
- Support for ".onion" in --add-exclusive-node and --add-peer - Add --anonymizing-proxy for outbound Tor connections - Add --anonymous-inbounds for inbound Tor connections - Support for sharing ".onion" addresses over Tor connections - Support for broadcasting transactions received over RPC exclusively over Tor (else broadcast over public IP when Tor not enabled).
Diffstat (limited to 'contrib/epee/include/net')
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.h56
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl136
-rw-r--r--contrib/epee/include/net/connection_basic.hpp17
-rw-r--r--contrib/epee/include/net/enums.h65
-rw-r--r--contrib/epee/include/net/net_utils_base.h91
5 files changed, 267 insertions, 98 deletions
diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h
index e6b2755af..37f4c782d 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.h
+++ b/contrib/epee/include/net/abstract_tcp_server2.h
@@ -41,6 +41,7 @@
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <atomic>
+#include <cassert>
#include <map>
#include <memory>
@@ -87,14 +88,25 @@ namespace net_utils
{
public:
typedef typename t_protocol_handler::connection_context t_connection_context;
+
+ struct shared_state : socket_stats
+ {
+ shared_state()
+ : socket_stats(), pfilter(nullptr), config()
+ {}
+
+ i_connection_filter* pfilter;
+ typename t_protocol_handler::config_type config;
+ };
+
/// Construct a connection with the given io_service.
-
explicit connection( boost::asio::io_service& io_service,
- typename t_protocol_handler::config_type& config,
- std::atomic<long> &ref_sock_count, // the ++/-- counter
- std::atomic<long> &sock_number, // the only increasing ++ number generator
- i_connection_filter * &pfilter
- ,t_connection_type connection_type);
+ boost::shared_ptr<shared_state> state,
+ t_connection_type connection_type);
+
+ explicit connection( boost::asio::ip::tcp::socket&& sock,
+ boost::shared_ptr<shared_state> state,
+ t_connection_type connection_type);
virtual ~connection() noexcept(false);
/// Get the socket associated with the connection.
@@ -103,6 +115,9 @@ namespace net_utils
/// Start the first asynchronous operation for the connection.
bool start(bool is_income, bool is_multithreaded);
+ // `real_remote` is the actual endpoint (if connection is to proxy, etc.)
+ bool start(bool is_income, bool is_multithreaded, network_address real_remote);
+
void get_context(t_connection_context& context_){context_ = context;}
void call_back_starter();
@@ -148,7 +163,6 @@ namespace net_utils
//boost::array<char, 1024> buffer_;
t_connection_context context;
- i_connection_filter* &m_pfilter;
// TODO what do they mean about wait on destructor?? --rfree :
//this should be the last one, because it could be wait on destructor, while other activities possible on other threads
@@ -210,7 +224,9 @@ namespace net_utils
/// Stop the server.
void send_stop_signal();
- bool is_stop_signal_sent();
+ bool is_stop_signal_sent() const noexcept { return m_stop_signal_sent; };
+
+ const std::atomic<bool>& get_stop_signal() const noexcept { return m_stop_signal_sent; }
void set_threads_prefix(const std::string& prefix_name);
@@ -220,17 +236,28 @@ namespace net_utils
void set_connection_filter(i_connection_filter* pfilter);
+ void set_default_remote(epee::net_utils::network_address remote)
+ {
+ default_remote = std::move(remote);
+ }
+
+ bool add_connection(t_connection_context& out, boost::asio::ip::tcp::socket&& sock, network_address real_remote);
bool connect(const std::string& adr, const std::string& port, uint32_t conn_timeot, t_connection_context& cn, const std::string& bind_ip = "0.0.0.0");
template<class t_callback>
bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback &cb, const std::string& bind_ip = "0.0.0.0");
- typename t_protocol_handler::config_type& get_config_object(){return m_config;}
+ typename t_protocol_handler::config_type& get_config_object()
+ {
+ assert(m_state != nullptr); // always set in constructor
+ return m_state->config;
+ }
int get_binded_port(){return m_port;}
long get_connections_count() const
{
- auto connections_count = (m_sock_count > 0) ? (m_sock_count - 1) : 0; // Socket count minus listening socket
+ assert(m_state != nullptr); // always set in constructor
+ auto connections_count = m_state->sock_count > 0 ? (m_state->sock_count - 1) : 0; // Socket count minus listening socket
return connections_count;
}
@@ -292,9 +319,6 @@ namespace net_utils
return true;
}
- protected:
- typename t_protocol_handler::config_type m_config;
-
private:
/// Run the server's io_service loop.
bool worker_thread();
@@ -303,21 +327,21 @@ namespace net_utils
bool is_thread_worker();
+ const boost::shared_ptr<typename connection<t_protocol_handler>::shared_state> m_state;
+
/// The io_service used to perform asynchronous operations.
std::unique_ptr<boost::asio::io_service> m_io_service_local_instance;
boost::asio::io_service& io_service_;
/// Acceptor used to listen for incoming connections.
boost::asio::ip::tcp::acceptor acceptor_;
+ epee::net_utils::network_address default_remote;
std::atomic<bool> m_stop_signal_sent;
uint32_t m_port;
- std::atomic<long> m_sock_count;
- std::atomic<long> m_sock_number;
std::string m_address;
std::string m_thread_name_prefix; //TODO: change to enum server_type, now used
size_t m_threads_count;
- i_connection_filter* m_pfilter;
std::vector<boost::shared_ptr<boost::thread> > m_threads;
boost::thread::id m_main_thread_id;
critical_section m_threads_lock;
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index 457ee2dd4..9c89a18cf 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -40,6 +40,7 @@
#include <boost/asio/deadline_timer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> // TODO
#include <boost/thread/condition_variable.hpp> // TODO
+#include <boost/make_shared.hpp>
#include "warnings.h"
#include "string_tools.h"
#include "misc_language.h"
@@ -62,6 +63,13 @@ namespace epee
{
namespace net_utils
{
+ template<typename T>
+ T& check_and_get(boost::shared_ptr<T>& ptr)
+ {
+ CHECK_AND_ASSERT_THROW_MES(bool(ptr), "shared_state cannot be null");
+ return *ptr;
+ }
+
/************************************************************************/
/* */
/************************************************************************/
@@ -69,25 +77,31 @@ PRAGMA_WARNING_DISABLE_VS(4355)
template<class t_protocol_handler>
connection<t_protocol_handler>::connection( boost::asio::io_service& io_service,
- typename t_protocol_handler::config_type& config,
- std::atomic<long> &ref_sock_count, // the ++/-- counter
- std::atomic<long> &sock_number, // the only increasing ++ number generator
- i_connection_filter* &pfilter
- ,t_connection_type connection_type
+ boost::shared_ptr<shared_state> state,
+ t_connection_type connection_type
+ )
+ : connection(boost::asio::ip::tcp::socket{io_service}, std::move(state), connection_type)
+ {
+ }
+
+ template<class t_protocol_handler>
+ connection<t_protocol_handler>::connection( boost::asio::ip::tcp::socket&& sock,
+ boost::shared_ptr<shared_state> state,
+ t_connection_type connection_type
)
:
- connection_basic(io_service, ref_sock_count, sock_number),
- m_protocol_handler(this, config, context),
- m_pfilter( pfilter ),
+ connection_basic(std::move(sock), state),
+ m_protocol_handler(this, check_and_get(state).config, context),
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(io_service),
+ m_timer(socket_.get_io_service()),
m_local(false),
m_ready_to_close(false)
{
MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type);
}
+
PRAGMA_WARNING_DISABLE_VS(4355)
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@@ -127,34 +141,44 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{
TRY_ENTRY();
+ boost::system::error_code ec;
+ auto remote_ep = socket_.remote_endpoint(ec);
+ CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " << ec.message() << ':' << ec.value());
+ CHECK_AND_NO_ASSERT_MES(remote_ep.address().is_v4(), false, "IPv6 not supported here");
+
+ const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())};
+ return start(is_income, is_multithreaded, ipv4_network_address{uint32_t(ip_), remote_ep.port()});
+ CATCH_ENTRY_L0("connection<t_protocol_handler>::start()", false);
+ }
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
+ bool connection<t_protocol_handler>::start(bool is_income, bool is_multithreaded, network_address real_remote)
+ {
+ TRY_ENTRY();
+
// Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted
auto self = safe_shared_from_this();
if(!self)
return false;
m_is_multithreaded = is_multithreaded;
+ m_local = real_remote.is_loopback() || real_remote.is_local();
- boost::system::error_code ec;
- auto remote_ep = socket_.remote_endpoint(ec);
- CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " << ec.message() << ':' << ec.value());
- CHECK_AND_NO_ASSERT_MES(remote_ep.address().is_v4(), false, "IPv6 not supported here");
+ // create a random uuid, we don't need crypto strength here
+ const boost::uuids::uuid random_uuid = boost::uuids::random_generator()();
+
+ context = t_connection_context{};
+ context.set_details(random_uuid, std::move(real_remote), is_income);
+ boost::system::error_code ec;
auto local_ep = socket_.local_endpoint(ec);
CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " << ec.message() << ':' << ec.value());
- context = boost::value_initialized<t_connection_context>();
- const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())};
- m_local = epee::net_utils::is_ip_loopback(ip_) || epee::net_utils::is_ip_local(ip_);
-
- // create a random uuid, we don't need crypto strength here
- const boost::uuids::uuid random_uuid = boost::uuids::random_generator()();
-
- context.set_details(random_uuid, epee::net_utils::ipv4_network_address(ip_, remote_ep.port()), is_income);
_dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) <<
" to " << local_ep.address().to_string() << ':' << local_ep.port() <<
- ", total sockets objects " << m_ref_sock_count);
+ ", total sockets objects " << get_stats().sock_count);
- if(m_pfilter && !m_pfilter->is_remote_host_allowed(context.m_remote_address))
+ if(static_cast<shared_state&>(get_stats()).pfilter && !static_cast<shared_state&>(get_stats()).pfilter->is_remote_host_allowed(context.m_remote_address))
{
_dbg2("[sock " << socket_.native_handle() << "] host denied " << context.m_remote_address.host_str() << ", shutdowning connection");
close();
@@ -279,7 +303,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
MDEBUG(" connection type " << to_string( m_connection_type ) << " "
<< socket_.local_endpoint().address().to_string() << ":" << socket_.local_endpoint().port()
- << " <--> " << address << ":" << port);
+ << " <--> " << context.m_remote_address.str() << " (via " << address << ":" << port << ")");
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@@ -784,12 +808,14 @@ PRAGMA_WARNING_DISABLE_VS(4355)
template<class t_protocol_handler>
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server( t_connection_type connection_type ) :
+ m_state(boost::make_shared<typename connection<t_protocol_handler>::shared_state>()),
m_io_service_local_instance(new boost::asio::io_service()),
io_service_(*m_io_service_local_instance.get()),
acceptor_(io_service_),
+ default_remote(),
m_stop_signal_sent(false), m_port(0),
- m_sock_count(0), m_sock_number(0), m_threads_count(0),
- m_pfilter(NULL), m_thread_index(0),
+ m_threads_count(0),
+ m_thread_index(0),
m_connection_type( connection_type ),
new_connection_()
{
@@ -799,11 +825,13 @@ PRAGMA_WARNING_DISABLE_VS(4355)
template<class t_protocol_handler>
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server(boost::asio::io_service& extarnal_io_service, t_connection_type connection_type) :
+ m_state(boost::make_shared<typename connection<t_protocol_handler>::shared_state>()),
io_service_(extarnal_io_service),
acceptor_(io_service_),
- m_stop_signal_sent(false), m_port(0),
- m_sock_count(0), m_sock_number(0), m_threads_count(0),
- m_pfilter(NULL), m_thread_index(0),
+ default_remote(),
+ m_stop_signal_sent(false), m_port(0),
+ m_threads_count(0),
+ m_thread_index(0),
m_connection_type(connection_type),
new_connection_()
{
@@ -844,7 +872,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint();
m_port = binded_endpoint.port();
MDEBUG("start accept");
- new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type));
+ new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept, this,
boost::asio::placeholders::error));
@@ -922,7 +950,8 @@ POP_WARNINGS
template<class t_protocol_handler>
void boosted_tcp_server<t_protocol_handler>::set_connection_filter(i_connection_filter* pfilter)
{
- m_pfilter = pfilter;
+ assert(m_state != nullptr); // always set in constructor
+ m_state->pfilter = pfilter;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@@ -1030,12 +1059,6 @@ POP_WARNINGS
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
- bool boosted_tcp_server<t_protocol_handler>::is_stop_signal_sent()
- {
- return m_stop_signal_sent;
- }
- //---------------------------------------------------------------------------------
- template<class t_protocol_handler>
void boosted_tcp_server<t_protocol_handler>::handle_accept(const boost::system::error_code& e)
{
MDEBUG("handle_accept");
@@ -1048,7 +1071,7 @@ POP_WARNINGS
new_connection_->setRpcStation(); // hopefully this is not needed actually
}
connection_ptr conn(std::move(new_connection_));
- new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type));
+ new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept, this,
boost::asio::placeholders::error));
@@ -1056,7 +1079,10 @@ POP_WARNINGS
boost::asio::socket_base::keep_alive opt(true);
conn->socket().set_option(opt);
- conn->start(true, 1 < m_threads_count);
+ if (default_remote.get_type_id() == net_utils::address_type::invalid)
+ conn->start(true, 1 < m_threads_count);
+ else
+ conn->start(true, 1 < m_threads_count, default_remote);
conn->save_dbg_log();
return;
}
@@ -1071,20 +1097,41 @@ POP_WARNINGS
}
// error path, if e or exception
- _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count);
+ assert(m_state != nullptr); // always set in constructor
+ _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_state->sock_count);
misc_utils::sleep_no_w(100);
- new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type));
+ new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept, this,
boost::asio::placeholders::error));
}
//---------------------------------------------------------------------------------
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)
+ {
+ if(std::addressof(get_io_service()) == std::addressof(sock.get_io_service()))
+ {
+ connection_ptr conn(new connection<t_protocol_handler>(std::move(sock), m_state, m_connection_type));
+ if(conn->start(false, 1 < m_threads_count, std::move(real_remote)))
+ {
+ conn->get_context(out);
+ conn->save_dbg_log();
+ return true;
+ }
+ }
+ else
+ {
+ MWARNING(out << " was not added, socket/io_service mismatch");
+ }
+ return false;
+ }
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
bool boosted_tcp_server<t_protocol_handler>::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip)
{
TRY_ENTRY();
- connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type) );
+ connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type) );
connections_mutex.lock();
connections_.insert(new_connection_l);
MDEBUG("connections_ size now " << connections_.size());
@@ -1187,7 +1234,8 @@ POP_WARNINGS
}
else
{
- _erro("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection, connections_count = " << m_sock_count);
+ assert(m_state != nullptr); // always set in constructor
+ _erro("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection, connections_count = " << m_state->sock_count);
}
new_connection_l->save_dbg_log();
@@ -1201,7 +1249,7 @@ POP_WARNINGS
bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip)
{
TRY_ENTRY();
- connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type) );
+ connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type) );
connections_mutex.lock();
connections_.insert(new_connection_l);
MDEBUG("connections_ size now " << connections_.size());
diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp
index 9b6fc14a7..b1b271db9 100644
--- a/contrib/epee/include/net/connection_basic.hpp
+++ b/contrib/epee/include/net/connection_basic.hpp
@@ -55,6 +55,15 @@ namespace epee
{
namespace net_utils
{
+ struct socket_stats
+ {
+ socket_stats()
+ : sock_count(0), sock_number(0)
+ {}
+
+ std::atomic<long> sock_count;
+ std::atomic<long> sock_number;
+ };
/************************************************************************/
/* */
@@ -72,6 +81,8 @@ class connection_basic_pimpl; // PIMPL for this class
std::string to_string(t_connection_type type);
class connection_basic { // not-templated base class for rapid developmet of some code parts
+ // beware of removing const, net_utils::connection is sketchily doing a cast to prevent storing ptr twice
+ const boost::shared_ptr<socket_stats> m_stats;
public:
std::unique_ptr< connection_basic_pimpl > mI; // my Implementation
@@ -86,13 +97,15 @@ class connection_basic { // not-templated base class for rapid developmet of som
/// Socket for the connection.
boost::asio::ip::tcp::socket socket_;
- std::atomic<long> &m_ref_sock_count; // reference to external counter of existing sockets that we will ++/--
public:
// first counter is the ++/-- count of current sockets, the other socket_number is only-increasing ++ number generator
- connection_basic(boost::asio::io_service& io_service, std::atomic<long> &ref_sock_count, std::atomic<long> &sock_number);
+ connection_basic(boost::asio::ip::tcp::socket&& socket, boost::shared_ptr<socket_stats> stats);
virtual ~connection_basic() noexcept(false);
+ //! \return `socket_stats` object passed in construction (ptr never changes).
+ socket_stats& get_stats() noexcept { return *m_stats; /* verified in constructor */ }
+
// various handlers to be called from connection class:
void do_send_handler_write(const void * ptr , size_t cb);
void do_send_handler_write_from_queue(const boost::system::error_code& e, size_t cb , int q_len); // from handle_write, sending next part
diff --git a/contrib/epee/include/net/enums.h b/contrib/epee/include/net/enums.h
new file mode 100644
index 000000000..078a4b274
--- /dev/null
+++ b/contrib/epee/include/net/enums.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS 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 <boost/utility/string_ref.hpp>
+#include <cstdint>
+
+namespace epee
+{
+namespace net_utils
+{
+ enum class address_type : std::uint8_t
+ {
+ // Do not change values, this will break serialization
+ invalid = 0,
+ ipv4 = 1,
+ ipv6 = 2,
+ i2p = 3,
+ tor = 4
+ };
+
+ enum class zone : std::uint8_t
+ {
+ invalid = 0,
+ public_ = 1, // public is keyword
+ i2p = 2,
+ tor = 3
+ };
+
+ // implementations in src/net_utils_base.cpp
+
+ //! \return String name of zone or "invalid" on error.
+ const char* zone_to_string(zone value) noexcept;
+
+ //! \return `zone` enum of `value` or `zone::invalid` on error.
+ zone zone_from_string(boost::string_ref value) noexcept;
+} // net_utils
+} // epee
+
diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h
index a9e458626..82f8a7fe8 100644
--- a/contrib/epee/include/net/net_utils_base.h
+++ b/contrib/epee/include/net/net_utils_base.h
@@ -33,6 +33,7 @@
#include <boost/asio/io_service.hpp>
#include <typeinfo>
#include <type_traits>
+#include "enums.h"
#include "serialization/keyvalue_serialization.h"
#include "misc_log_ex.h"
@@ -43,6 +44,11 @@
#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24))
#endif
+namespace net
+{
+ class tor_address;
+}
+
namespace epee
{
namespace net_utils
@@ -53,6 +59,10 @@ namespace net_utils
uint16_t m_port;
public:
+ constexpr ipv4_network_address() noexcept
+ : ipv4_network_address(0, 0)
+ {}
+
constexpr ipv4_network_address(uint32_t ip, uint16_t port) noexcept
: m_ip(ip), m_port(port) {}
@@ -67,9 +77,10 @@ namespace net_utils
std::string host_str() const;
bool is_loopback() const;
bool is_local() const;
- static constexpr uint8_t get_type_id() noexcept { return ID; }
+ static constexpr address_type get_type_id() noexcept { return address_type::ipv4; }
+ static constexpr zone get_zone() noexcept { return zone::public_; }
+ static constexpr bool is_blockable() noexcept { return true; }
- static const uint8_t ID = 1;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_ip)
KV_SERIALIZE(m_port)
@@ -103,7 +114,9 @@ namespace net_utils
virtual std::string host_str() const = 0;
virtual bool is_loopback() const = 0;
virtual bool is_local() const = 0;
- virtual uint8_t get_type_id() const = 0;
+ virtual address_type get_type_id() const = 0;
+ virtual zone get_zone() const = 0;
+ virtual bool is_blockable() const = 0;
};
template<typename T>
@@ -131,7 +144,9 @@ namespace net_utils
virtual std::string host_str() const override { return value.host_str(); }
virtual bool is_loopback() const override { return value.is_loopback(); }
virtual bool is_local() const override { return value.is_local(); }
- virtual uint8_t get_type_id() const override { return value.get_type_id(); }
+ virtual address_type get_type_id() const override { return value.get_type_id(); }
+ virtual zone get_zone() const override { return value.get_zone(); }
+ virtual bool is_blockable() const override { return value.is_blockable(); }
};
std::shared_ptr<interface> self;
@@ -146,6 +161,23 @@ namespace net_utils
throw std::bad_cast{};
return static_cast<implementation<Type_>*>(self_)->value;
}
+
+ template<typename T, typename t_storage>
+ bool serialize_addr(std::false_type, t_storage& stg, typename t_storage::hsection hparent)
+ {
+ T addr{};
+ if (!epee::serialization::selector<false>::serialize(addr, stg, hparent, "addr"))
+ return false;
+ *this = std::move(addr);
+ return true;
+ }
+
+ template<typename T, typename t_storage>
+ bool serialize_addr(std::true_type, t_storage& stg, typename t_storage::hsection hparent) const
+ {
+ return epee::serialization::selector<true>::serialize(as<T>(), stg, hparent, "addr");
+ }
+
public:
network_address() : self(nullptr) {}
template<typename T>
@@ -158,43 +190,32 @@ namespace net_utils
std::string host_str() const { return self ? self->host_str() : "<none>"; }
bool is_loopback() const { return self ? self->is_loopback() : false; }
bool is_local() const { return self ? self->is_local() : false; }
- uint8_t get_type_id() const { return self ? self->get_type_id() : 0; }
+ address_type get_type_id() const { return self ? self->get_type_id() : address_type::invalid; }
+ zone get_zone() const { return self ? self->get_zone() : zone::invalid; }
+ bool is_blockable() const { return self ? self->is_blockable() : false; }
template<typename Type> const Type &as() const { return as_mutable<const Type>(); }
BEGIN_KV_SERIALIZE_MAP()
- uint8_t type = is_store ? this_ref.get_type_id() : 0;
+ // need to `#include "net/tor_address.h"` when serializing `network_address`
+ static constexpr std::integral_constant<bool, is_store> is_store_{};
+
+ std::uint8_t type = std::uint8_t(is_store ? this_ref.get_type_id() : address_type::invalid);
if (!epee::serialization::selector<is_store>::serialize(type, stg, hparent_section, "type"))
return false;
- switch (type)
+
+ switch (address_type(type))
{
- case ipv4_network_address::ID:
- {
- if (!is_store)
- {
- const_cast<network_address&>(this_ref) = ipv4_network_address{0, 0};
- auto &addr = this_ref.template as_mutable<ipv4_network_address>();
- if (epee::serialization::selector<is_store>::serialize(addr, stg, hparent_section, "addr"))
- MDEBUG("Found as addr: " << this_ref.str());
- else if (epee::serialization::selector<is_store>::serialize(addr, stg, hparent_section, "template as<ipv4_network_address>()"))
- MDEBUG("Found as template as<ipv4_network_address>(): " << this_ref.str());
- else if (epee::serialization::selector<is_store>::serialize(addr, stg, hparent_section, "template as_mutable<ipv4_network_address>()"))
- MDEBUG("Found as template as_mutable<ipv4_network_address>(): " << this_ref.str());
- else
- {
- MWARNING("Address not found");
- return false;
- }
- }
- else
- {
- auto &addr = this_ref.template as_mutable<ipv4_network_address>();
- if (!epee::serialization::selector<is_store>::serialize(addr, stg, hparent_section, "addr"))
- return false;
- }
+ case address_type::ipv4:
+ return this_ref.template serialize_addr<ipv4_network_address>(is_store_, stg, hparent_section);
+ case address_type::tor:
+ return this_ref.template serialize_addr<net::tor_address>(is_store_, stg, hparent_section);
+ case address_type::invalid:
+ default:
break;
- }
- default: MERROR("Unsupported network address type: " << (unsigned)type); return false;
}
+
+ MERROR("Unsupported network address type: " << (unsigned)type);
+ return false;
END_KV_SERIALIZE_MAP()
};
@@ -211,8 +232,6 @@ namespace net_utils
inline bool operator>=(const network_address& lhs, const network_address& rhs)
{ return !lhs.less(rhs); }
- bool create_network_address(network_address &address, const std::string &string, uint16_t default_port = 0);
-
/************************************************************************/
/* */
/************************************************************************/
@@ -250,7 +269,7 @@ namespace net_utils
{}
connection_context_base(): m_connection_id(),
- m_remote_address(ipv4_network_address{0,0}),
+ m_remote_address(),
m_is_income(false),
m_started(time(NULL)),
m_last_recv(0),