Electroneum
net_utils_base.h
Go to the documentation of this file.
1 // Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of the Andrey N. Sabelnikov nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26 
27 
28 
29 #ifndef _NET_UTILS_BASE_H_
30 #define _NET_UTILS_BASE_H_
31 
32 #include <boost/uuid/uuid.hpp>
33 #include <boost/asio/io_service.hpp>
34 #include <typeinfo>
35 #include <type_traits>
36 #include "enums.h"
38 #include "misc_log_ex.h"
39 
40 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
41 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "net"
42 
43 #ifndef MAKE_IP
44 #define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24))
45 #endif
46 
47 #if BOOST_VERSION >= 107000
48 #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
49 #else
50 #define GET_IO_SERVICE(s) ((s).get_io_service())
51 #endif
52 
53 namespace net
54 {
55  class tor_address;
56  class i2p_address;
57 }
58 
59 namespace epee
60 {
61 namespace net_utils
62 {
64  {
65  uint32_t m_ip;
66  uint16_t m_port;
67 
68  public:
69  constexpr ipv4_network_address() noexcept
70  : ipv4_network_address(0, 0)
71  {}
72 
74  : m_ip(ip), m_port(port) {}
75 
76  bool equal(const ipv4_network_address& other) const noexcept;
77  bool less(const ipv4_network_address& other) const noexcept;
78  constexpr bool is_same_host(const ipv4_network_address& other) const noexcept
79  { return ip() == other.ip(); }
80 
81  constexpr uint32_t ip() const noexcept { return m_ip; }
82  constexpr uint16_t port() const noexcept { return m_port; }
83  std::string str() const;
84  std::string host_str() const;
85  bool is_loopback() const;
86  bool is_local() const;
87  static constexpr address_type get_type_id() noexcept { return address_type::ipv4; }
88  static constexpr zone get_zone() noexcept { return zone::public_; }
89  static constexpr bool is_blockable() noexcept { return true; }
90 
92  KV_SERIALIZE(m_ip)
93  KV_SERIALIZE(m_port)
95  };
96 
97  inline bool operator==(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept
98  { return lhs.equal(rhs); }
99  inline bool operator!=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept
100  { return !lhs.equal(rhs); }
101  inline bool operator<(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept
102  { return lhs.less(rhs); }
103  inline bool operator<=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept
104  { return !rhs.less(lhs); }
105  inline bool operator>(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept
106  { return rhs.less(lhs); }
107  inline bool operator>=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept
108  { return !lhs.less(rhs); }
109 
111  {
112  struct interface
113  {
114  virtual ~interface() {};
115 
116  virtual bool equal(const interface&) const = 0;
117  virtual bool less(const interface&) const = 0;
118  virtual bool is_same_host(const interface&) const = 0;
119 
120  virtual std::string str() const = 0;
121  virtual std::string host_str() const = 0;
122  virtual bool is_loopback() const = 0;
123  virtual bool is_local() const = 0;
124  virtual address_type get_type_id() const = 0;
125  virtual zone get_zone() const = 0;
126  virtual bool is_blockable() const = 0;
127  };
128 
129  template<typename T>
130  struct implementation final : interface
131  {
132  T value;
133 
134  implementation(const T& src) : value(src) {}
135  ~implementation() = default;
136 
137  // Type-checks for cast are done in cpp
138  static const T& cast(const interface& src) noexcept
139  { return static_cast<const implementation<T>&>(src).value; }
140 
141  virtual bool equal(const interface& other) const override
142  { return value.equal(cast(other)); }
143 
144  virtual bool less(const interface& other) const override
145  { return value.less(cast(other)); }
146 
147  virtual bool is_same_host(const interface& other) const override
148  { return value.is_same_host(cast(other)); }
149 
150  virtual std::string str() const override { return value.str(); }
151  virtual std::string host_str() const override { return value.host_str(); }
152  virtual bool is_loopback() const override { return value.is_loopback(); }
153  virtual bool is_local() const override { return value.is_local(); }
154  virtual address_type get_type_id() const override { return value.get_type_id(); }
155  virtual zone get_zone() const override { return value.get_zone(); }
156  virtual bool is_blockable() const override { return value.is_blockable(); }
157  };
158 
159  std::shared_ptr<interface> self;
160 
161  template<typename Type>
162  Type& as_mutable() const
163  {
164  // types `implmentation<Type>` and `implementation<const Type>` are unique
165  using Type_ = typename std::remove_const<Type>::type;
166  network_address::interface* const self_ = self.get(); // avoid clang warning in typeid
167  if (!self_ || typeid(implementation<Type_>) != typeid(*self_))
168  throw std::bad_cast{};
169  return static_cast<implementation<Type_>*>(self_)->value;
170  }
171 
172  template<typename T, typename t_storage>
173  bool serialize_addr(std::false_type, t_storage& stg, typename t_storage::hsection hparent)
174  {
175  T addr{};
176  if (!epee::serialization::selector<false>::serialize(addr, stg, hparent, "addr"))
177  return false;
178  *this = std::move(addr);
179  return true;
180  }
181 
182  template<typename T, typename t_storage>
183  bool serialize_addr(std::true_type, t_storage& stg, typename t_storage::hsection hparent) const
184  {
185  return epee::serialization::selector<true>::serialize(as<T>(), stg, hparent, "addr");
186  }
187 
188  public:
189  network_address() : self(nullptr) {}
190  template<typename T>
191  network_address(const T& src)
192  : self(std::make_shared<implementation<T>>(src)) {}
193  bool equal(const network_address &other) const;
194  bool less(const network_address &other) const;
195  bool is_same_host(const network_address &other) const;
196  std::string str() const { return self ? self->str() : "<none>"; }
197  std::string host_str() const { return self ? self->host_str() : "<none>"; }
198  bool is_loopback() const { return self ? self->is_loopback() : false; }
199  bool is_local() const { return self ? self->is_local() : false; }
200  address_type get_type_id() const { return self ? self->get_type_id() : address_type::invalid; }
201  zone get_zone() const { return self ? self->get_zone() : zone::public_; }
202  bool is_blockable() const { return self ? self->is_blockable() : false; }
203  template<typename Type> const Type &as() const { return as_mutable<const Type>(); }
204 
206  // need to `#include "net/[i2p|tor]_address.h"` when serializing `network_address`
207  static constexpr std::integral_constant<bool, is_store> is_store_{};
208 
209  std::uint8_t type = std::uint8_t(is_store ? this_ref.get_type_id() : address_type::invalid);
210  if (!epee::serialization::selector<is_store>::serialize(type, stg, hparent_section, "type"))
211  return false;
212 
213  switch (address_type(type))
214  {
215  case address_type::ipv4:
216  return this_ref.template serialize_addr<ipv4_network_address>(is_store_, stg, hparent_section);
217  case address_type::tor:
218  return this_ref.template serialize_addr<net::tor_address>(is_store_, stg, hparent_section);
219  case address_type::i2p:
220  return this_ref.template serialize_addr<net::i2p_address>(is_store_, stg, hparent_section);
222  default:
223  break;
224  }
225 
226  MERROR("Unsupported network address type: " << (unsigned)type);
227  return false;
229  };
230 
231  inline bool operator==(const network_address& lhs, const network_address& rhs)
232  { return lhs.equal(rhs); }
233  inline bool operator!=(const network_address& lhs, const network_address& rhs)
234  { return !lhs.equal(rhs); }
235  inline bool operator<(const network_address& lhs, const network_address& rhs)
236  { return lhs.less(rhs); }
237  inline bool operator<=(const network_address& lhs, const network_address& rhs)
238  { return !rhs.less(lhs); }
239  inline bool operator>(const network_address& lhs, const network_address& rhs)
240  { return rhs.less(lhs); }
241  inline bool operator>=(const network_address& lhs, const network_address& rhs)
242  { return !lhs.less(rhs); }
243 
244  /************************************************************************/
245  /* */
246  /************************************************************************/
248  {
251  const bool m_is_income;
252  const time_t m_started;
253  const time_t m_ssl;
254  time_t m_last_recv;
255  time_t m_last_send;
262 
264  const network_address &remote_address, bool is_income, bool ssl,
265  time_t last_recv = 0, time_t last_send = 0,
266  uint64_t recv_cnt = 0, uint64_t send_cnt = 0):
267  m_connection_id(connection_id),
268  m_remote_address(remote_address),
269  m_is_income(is_income),
270  m_started(time(NULL)),
271  m_ssl(ssl),
272  m_last_recv(last_recv),
273  m_last_send(last_send),
274  m_recv_cnt(recv_cnt),
275  m_send_cnt(send_cnt),
276  m_current_speed_down(0),
277  m_current_speed_up(0),
278  m_max_speed_down(0),
279  m_max_speed_up(0)
280  {}
281 
282  connection_context_base(): m_connection_id(),
283  m_remote_address(),
284  m_is_income(false),
285  m_started(time(NULL)),
286  m_ssl(false),
287  m_last_recv(0),
288  m_last_send(0),
289  m_recv_cnt(0),
290  m_send_cnt(0),
291  m_current_speed_down(0),
292  m_current_speed_up(0),
293  m_max_speed_down(0),
294  m_max_speed_up(0)
295  {}
296 
298  {
299  set_details(a.m_connection_id, a.m_remote_address, a.m_is_income, a.m_ssl);
300  }
301 
303  {
304  set_details(a.m_connection_id, a.m_remote_address, a.m_is_income, a.m_ssl);
305  return *this;
306  }
307 
308  private:
309  template<class t_protocol_handler>
310  friend class connection;
311  void set_details(boost::uuids::uuid connection_id, const network_address &remote_address, bool is_income, bool ssl)
312  {
313  this->~connection_context_base();
314  new(this) connection_context_base(connection_id, remote_address, is_income, ssl);
315  }
316 
317  };
318 
319  /************************************************************************/
320  /* */
321  /************************************************************************/
323  {
324  virtual bool do_send(const void* ptr, size_t cb)=0;
325  virtual bool close()=0;
326  virtual bool send_done()=0;
327  virtual bool call_run_once_service_io()=0;
328  virtual bool request_callback()=0;
329  virtual boost::asio::io_service& get_io_service()=0;
330  //protect from deletion connection object(with protocol instance) during external call "invoke"
331  virtual bool add_ref()=0;
332  virtual bool release()=0;
333  protected:
334  virtual ~i_service_endpoint() noexcept(false) {}
335  };
336 
337 
338  //some helpers
339 
340 
341  std::string print_connection_context(const connection_context_base& ctx);
342  std::string print_connection_context_short(const connection_context_base& ctx);
343 
345 {
346  os << "[" << epee::net_utils::print_connection_context_short(ct) << "] ";
347  return os;
348 }
349 
350 #define LOG_ERROR_CC(ct, message) MERROR(ct << message)
351 #define LOG_WARNING_CC(ct, message) MWARNING(ct << message)
352 #define LOG_INFO_CC(ct, message) MINFO(ct << message)
353 #define LOG_DEBUG_CC(ct, message) MDEBUG(ct << message)
354 #define LOG_TRACE_CC(ct, message) MTRACE(ct << message)
355 #define LOG_CC(level, ct, message) MLOG(level, ct << message)
356 
357 #define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(ct << message)
358 #define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(ct << message)
359 #define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(ct << message)
360 #define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(ct << message)
361 #define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(ct << message)
362 
363 #define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message)
364 #define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message)
365 #define LOG_PRINT_CCONTEXT_L2(message) LOG_PRINT_CC_L2(context, message)
366 #define LOG_PRINT_CCONTEXT_L3(message) LOG_PRINT_CC_L3(context, message)
367 #define LOG_ERROR_CCONTEXT(message) LOG_ERROR_CC(context, message)
368 
369 #define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message) CHECK_AND_ASSERT_MES(condition, return_val, "[" << epee::net_utils::print_connection_context_short(context) << "]" << err_message)
370 
371 }
372 }
373 
374 #endif //_NET_UTILS_BASE_H_
#define MERROR(x)
Definition: misc_log_ex.h:73
const uint32_t T[512]
bool equal(const ipv4_network_address &other) const noexcept
std::string print_connection_context_short(const connection_context_base &ctx)
constexpr uint16_t port() const noexcept
bool operator!=(const ipv4_network_address &lhs, const ipv4_network_address &rhs) noexcept
b32 i2p address; internal format not condensed/decoded.
Definition: i2p_address.h:51
boost::uuids::uuid uuid
::std::string string
Definition: gtest-port.h:1097
bool operator==(const ipv4_network_address &lhs, const ipv4_network_address &rhs) noexcept
STL namespace.
unsigned short uint16_t
Definition: stdint.h:125
virtual ~i_service_endpoint() noexcept(false)
unsigned char uint8_t
Definition: stdint.h:124
#define KV_SERIALIZE(varialble)
bool_constant< true > true_type
Definition: gtest-port.h:2210
address_type get_type_id() const
time_t time
Definition: blockchain.cpp:93
connection_context_base(boost::uuids::uuid connection_id, const network_address &remote_address, bool is_income, bool ssl, time_t last_recv=0, time_t last_send=0, uint64_t recv_cnt=0, uint64_t send_cnt=0)
constexpr uint32_t ip() const noexcept
bool operator<=(const ipv4_network_address &lhs, const ipv4_network_address &rhs) noexcept
unsigned int uint32_t
Definition: stdint.h:126
void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver)
Represents a single connection from a client.
bool less(const network_address &other) const
static constexpr address_type get_type_id() noexcept
unsigned __int64 uint64_t
Definition: stdint.h:136
#define false
Definition: stdbool.h:38
static constexpr bool is_blockable() noexcept
constexpr ipv4_network_address(uint32_t ip, uint16_t port) noexcept
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
MAKE_LOGGABLE(connection_context_base, ct, os)
bool operator>(const ipv4_network_address &lhs, const ipv4_network_address &rhs) noexcept
bool operator<(const ipv4_network_address &lhs, const ipv4_network_address &rhs) noexcept
const T & move(const T &t)
Definition: gtest-port.h:1317
Tor onion address; internal format not condensed/decoded.
Definition: tor_address.h:51
connection_context_base(const connection_context_base &a)
constexpr bool is_same_host(const ipv4_network_address &other) const noexcept
constexpr ipv4_network_address() noexcept
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
static constexpr zone get_zone() noexcept
bool_constant< false > false_type
Definition: gtest-port.h:2209
std::string print_connection_context(const connection_context_base &ctx)
connection_context_base & operator=(const connection_context_base &a)
bool operator>=(const ipv4_network_address &lhs, const ipv4_network_address &rhs) noexcept
#define END_KV_SERIALIZE_MAP()
Type
Type of JSON value.
Definition: rapidjson.h:620
bool less(const ipv4_network_address &other) const noexcept
bool equal(const network_address &other) const
const boost::uuids::uuid m_connection_id
#define BEGIN_KV_SERIALIZE_MAP()
#define inline
Definition: inline_c.h:35