Monero
Loading...
Searching...
No Matches
net_node.inl
Go to the documentation of this file.
1// Copyright (c) 2014-2022, The Monero Project
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification, are
6// permitted provided that the following conditions are met:
7//
8// 1. Redistributions of source code must retain the above copyright notice, this list of
9// conditions and the following disclaimer.
10//
11// 2. Redistributions in binary form must reproduce the above copyright notice, this list
12// of conditions and the following disclaimer in the documentation and/or other
13// materials provided with the distribution.
14//
15// 3. Neither the name of the copyright holder nor the names of its contributors may be
16// used to endorse or promote products derived from this software without specific
17// prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
30
31// IP blocking adapted from Boolberry
32
33#include <algorithm>
34#include <boost/bind/bind.hpp>
35#include <boost/date_time/posix_time/posix_time.hpp>
36#include <boost/filesystem/operations.hpp>
37#include <boost/optional/optional.hpp>
38#include <boost/thread/thread.hpp>
39#include <boost/uuid/uuid_io.hpp>
40#include <boost/algorithm/string.hpp>
41#include <atomic>
42#include <functional>
43#include <limits>
44#include <memory>
45#include <tuple>
46#include <vector>
47
48#include "version.h"
49#include "string_tools.h"
50#include "common/util.h"
51#include "common/dns_utils.h"
52#include "common/pruning.h"
53#include "net/error.h"
54#include "net/net_helper.h"
55#include "math_helper.h"
56#include "misc_log_ex.h"
57#include "p2p_protocol_defs.h"
58#include "crypto/crypto.h"
61#include "net/parse.h"
62
63
64#undef MONERO_DEFAULT_LOG_CATEGORY
65#define MONERO_DEFAULT_LOG_CATEGORY "net.p2p"
66
67#define NET_MAKE_IP(b1,b2,b3,b4) ((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
68
69#define MIN_WANTED_SEED_NODES 12
70
71static inline boost::asio::ip::address_v4 make_address_v4_from_v6(const boost::asio::ip::address_v6& a)
72{
73 const auto &bytes = a.to_bytes();
74 uint32_t v4 = 0;
75 v4 = (v4 << 8) | bytes[12];
76 v4 = (v4 << 8) | bytes[13];
77 v4 = (v4 << 8) | bytes[14];
78 v4 = (v4 << 8) | bytes[15];
79 return boost::asio::ip::address_v4(v4);
80}
81
82namespace nodetool
83{
84 template<class t_payload_net_handler>
86 {
87 // tcp server uses io_context in destructor, and every zone uses
88 // io_service from public zone.
89 for (auto current = m_network_zones.begin(); current != m_network_zones.end(); /* below */)
90 {
91 if (current->first != epee::net_utils::zone::public_)
92 current = m_network_zones.erase(current);
93 else
94 ++current;
95 }
96 }
97 //-----------------------------------------------------------------------------------
98 inline bool append_net_address(std::vector<epee::net_utils::network_address> & seed_nodes, std::string const & addr, uint16_t default_port);
99 //-----------------------------------------------------------------------------------
100 template<class t_payload_net_handler>
101 void node_server<t_payload_net_handler>::init_options(boost::program_options::options_description& desc)
102 {
131 }
132 //-----------------------------------------------------------------------------------
133 template<class t_payload_net_handler>
135 {
136 TRY_ENTRY();
138 if (storage)
139 m_peerlist_storage = std::move(*storage);
140
142 public_zone.m_config.m_support_flags = P2P_SUPPORT_FLAGS;
143 public_zone.m_config.m_peer_id = crypto::rand<uint64_t>();
145
146 CATCH_ENTRY_L0("node_server::init_config", false);
147 return true;
148 }
149 //-----------------------------------------------------------------------------------
150 template<class t_payload_net_handler>
151 void node_server<t_payload_net_handler>::for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f)
152 {
153 for(auto& zone : m_network_zones)
154 {
155 zone.second.m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntx){
156 return f(cntx, cntx.peer_id, cntx.support_flags);
157 });
158 }
159 }
160 //-----------------------------------------------------------------------------------
161 template<class t_payload_net_handler>
162 bool node_server<t_payload_net_handler>::for_connection(const boost::uuids::uuid &connection_id, std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f)
163 {
164 for(auto& zone : m_network_zones)
165 {
166 const bool result = zone.second.m_net_server.get_config_object().for_connection(connection_id, [&](p2p_connection_context& cntx){
167 return f(cntx, cntx.peer_id, cntx.support_flags);
168 });
169 if (result)
170 return true;
171 }
172 return false;
173 }
174 //-----------------------------------------------------------------------------------
175 template<class t_payload_net_handler>
177 {
179
180 const time_t now = time(nullptr);
181
182 // look in the hosts list
183 auto it = m_blocked_hosts.find(address.host_str());
184 if (it != m_blocked_hosts.end())
185 {
186 if (now >= it->second)
187 {
188 m_blocked_hosts.erase(it);
189 MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked.");
190 it = m_blocked_hosts.end();
191 }
192 else
193 {
194 if (t)
195 *t = it->second - now;
196 return false;
197 }
198 }
199
200 // manually loop in subnets
201 if (address.get_type_id() == epee::net_utils::address_type::ipv4)
202 {
203 auto ipv4_address = address.template as<epee::net_utils::ipv4_network_address>();
204 std::map<epee::net_utils::ipv4_network_subnet, time_t>::iterator it;
205 for (it = m_blocked_subnets.begin(); it != m_blocked_subnets.end(); )
206 {
207 if (now >= it->second)
208 {
209 MCLOG_CYAN(el::Level::Info, "global", "Subnet " << it->first.host_str() << " unblocked.");
210 it = m_blocked_subnets.erase(it);
211 continue;
212 }
213 if (it->first.matches(ipv4_address))
214 {
215 if (t)
216 *t = it->second - now;
217 return false;
218 }
219 ++it;
220 }
221 }
222
223 // not found in hosts or subnets, allowed
224 return true;
225 }
226 //-----------------------------------------------------------------------------------
227 template<class t_payload_net_handler>
229 {
230 const network_zone& zone = m_network_zones.at(address.get_zone());
231 if (zone.m_current_number_of_in_peers >= zone.m_config.m_net_config.max_in_connection_count) // in peers limit
232 {
233 MWARNING("Exceeded max incoming connections, so dropping this one.");
234 return true;
235 }
236
238 {
239 MWARNING("CONNECTION FROM " << address.host_str() << " REFUSED, too many connections from the same address");
240 return true;
241 }
242
243 return false;
244 }
245
246 //-----------------------------------------------------------------------------------
247 template<class t_payload_net_handler>
249 {
250 if(!addr.is_blockable())
251 return false;
252
253 const time_t now = time(nullptr);
254 bool added = false;
255
257 time_t limit;
258 if (now > std::numeric_limits<time_t>::max() - seconds)
259 limit = std::numeric_limits<time_t>::max();
260 else
261 limit = now + seconds;
262 const std::string host_str = addr.host_str();
263 auto it = m_blocked_hosts.find(host_str);
264 if (it == m_blocked_hosts.end())
266 m_blocked_hosts[host_str] = limit;
268 // if the host was already blocked due to being in a blocked subnet, let it be silent
269 bool matches_blocked_subnet = false;
272 auto ipv4_address = addr.template as<epee::net_utils::ipv4_network_address>();
273 for (auto jt = m_blocked_subnets.begin(); jt != m_blocked_subnets.end(); ++jt)
275 if (jt->first.matches(ipv4_address))
277 matches_blocked_subnet = true;
278 break;
280 }
282 if (!matches_blocked_subnet)
283 added = true;
285 else if (it->second < limit || !add_only)
286 it->second = limit;
288 // drop any connection to that address. This should only have to look into
289 // the zone related to the connection, but really make sure everything is
290 // swept ...
291 std::vector<boost::uuids::uuid> conns;
292 for(auto& zone : m_network_zones)
294 zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
296 if (cntxt.m_remote_address.is_same_host(addr))
297 {
298 conns.push_back(cntxt.m_connection_id);
299 }
300 return true;
301 });
302
303 peerlist_entry pe{};
304 pe.adr = addr;
305 if (addr.port() == 0)
306 {
307 zone.second.m_peerlist.evict_host_from_peerlist(true, pe);
308 zone.second.m_peerlist.evict_host_from_peerlist(false, pe);
309 }
310 else
311 {
312 zone.second.m_peerlist.remove_from_peer_white(pe);
313 zone.second.m_peerlist.remove_from_peer_gray(pe);
314 zone.second.m_peerlist.remove_from_peer_anchor(addr);
315 }
316
317 for (const auto &c: conns)
318 zone.second.m_net_server.get_config_object().close(c, false);
319
320 conns.clear();
321 }
322
323 if (added)
324 MCLOG_CYAN(el::Level::Info, "global", "Host " << host_str << " blocked.");
325 else
326 MINFO("Host " << host_str << " block time updated.");
327 return true;
329 //-----------------------------------------------------------------------------------
330 template<class t_payload_net_handler>
334 auto i = m_blocked_hosts.find(address.host_str());
335 if (i == m_blocked_hosts.end())
336 return false;
338 MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked.");
339 return true;
341 //-----------------------------------------------------------------------------------
342 template<class t_payload_net_handler>
345 const time_t now = time(nullptr);
348 time_t limit;
349 if (now > std::numeric_limits<time_t>::max() - seconds)
350 limit = std::numeric_limits<time_t>::max();
351 else
352 limit = now + seconds;
353 const bool added = m_blocked_subnets.find(subnet) == m_blocked_subnets.end();
354 m_blocked_subnets[subnet] = limit;
356 // drop any connection to that subnet. This should only have to look into
357 // the zone related to the connection, but really make sure everything is
358 // swept ...
359 std::vector<boost::uuids::uuid> conns;
360 for(auto& zone : m_network_zones)
361 {
362 zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
364 if (cntxt.m_remote_address.get_type_id() != epee::net_utils::ipv4_network_address::get_type_id())
365 return true;
366 auto ipv4_address = cntxt.m_remote_address.template as<epee::net_utils::ipv4_network_address>();
367 if (subnet.matches(ipv4_address))
369 conns.push_back(cntxt.m_connection_id);
370 }
371 return true;
372 });
373 for (const auto &c: conns)
374 zone.second.m_net_server.get_config_object().close(c, false);
376 for (int i = 0; i < 2; ++i)
377 zone.second.m_peerlist.filter(i == 0, [&subnet](const peerlist_entry &pe){
378 if (pe.adr.get_type_id() != epee::net_utils::ipv4_network_address::get_type_id())
379 return false;
380 return subnet.matches(pe.adr.as<const epee::net_utils::ipv4_network_address>());
381 });
383 conns.clear();
386 if (added)
387 MCLOG_CYAN(el::Level::Info, "global", "Subnet " << subnet.host_str() << " blocked.");
388 else
389 MINFO("Subnet " << subnet.host_str() << " blocked.");
390 return true;
392 //-----------------------------------------------------------------------------------
393 template<class t_payload_net_handler>
395 {
397 auto i = m_blocked_subnets.find(subnet);
398 if (i == m_blocked_subnets.end())
399 return false;
401 MCLOG_CYAN(el::Level::Info, "global", "Subnet " << subnet.host_str() << " unblocked.");
402 return true;
403 }
404 //-----------------------------------------------------------------------------------
405 template<class t_payload_net_handler>
408 if(!address.is_blockable())
409 return false;
412 uint64_t fails = m_host_fails_score[address.host_str()] += score;
413 MDEBUG("Host " << address.host_str() << " fail score=" << fails);
414 if(fails > P2P_IP_FAILS_BEFORE_BLOCK)
415 {
416 auto it = m_host_fails_score.find(address.host_str());
417 CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error");
418 it->second = P2P_IP_FAILS_BEFORE_BLOCK/2;
420 }
421 return true;
422 }
423 //-----------------------------------------------------------------------------------
424 template<class t_payload_net_handler>
426 const boost::program_options::variables_map& vm
427 )
428 {
432 const bool pad_txs = command_line::get_arg(vm, arg_pad_transactions);
434
436 public_zone.m_connect = &public_connect;
441 public_zone.m_can_pingback = true;
445 MWARNING("UPnP port mapping support was removed. The --igd option is currently non-functional.");
446 }
451 public_zone.m_net_server.get_io_context(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core()
452 };
453
455 {
456 std::vector<std::string> perrs = command_line::get_arg(vm, arg_p2p_add_peer);
457 for(const std::string& pr_str: perrs)
458 {
463 if (adr)
464 {
465 add_zone(adr->get_zone());
466 pe.adr = std::move(*adr);
467 m_command_line_peers.push_back(std::move(pe));
468 continue;
469 }
470 CHECK_AND_ASSERT_MES(
471 adr == net::error::unsupported_address, false, "Bad address (\"" << pr_str << "\"): " << adr.error().message()
472 );
473
474 std::vector<epee::net_utils::network_address> resolved_addrs;
475 bool r = append_net_address(resolved_addrs, pr_str, default_port);
476 CHECK_AND_ASSERT_MES(r, false, "Failed to parse or resolve address from string: " << pr_str);
477 for (const epee::net_utils::network_address& addr : resolved_addrs)
480 pe.adr = addr;
481 m_command_line_peers.push_back(pe);
482 }
483 }
484 }
485
487 {
488 if (!parse_peers_and_add_to_container(vm, arg_p2p_add_exclusive_node, m_exclusive_peers))
489 return false;
490 }
491
493 {
494 if (!parse_peers_and_add_to_container(vm, arg_p2p_add_priority_node, m_priority_peers))
495 return false;
496 }
497
499 {
500 boost::unique_lock<boost::shared_mutex> lock(public_zone.m_seed_nodes_lock);
501
502 if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, public_zone.m_seed_nodes))
503 return false;
504 }
505
507 {
508 const std::string ban_list = command_line::get_arg(vm, arg_ban_list);
509
510 const boost::filesystem::path ban_list_path(ban_list);
511 boost::system::error_code ec;
512 if (!boost::filesystem::exists(ban_list_path, ec))
513 {
514 throw std::runtime_error("Can't find ban list file " + ban_list + " - " + ec.message());
515 }
516
517 std::string banned_ips;
518 if (!epee::file_io_utils::load_file_to_string(ban_list_path.string(), banned_ips))
519 {
520 throw std::runtime_error("Failed to read ban list file " + ban_list);
521 }
522
523 std::istringstream iss(banned_ips);
524 for (std::string line; std::getline(iss, line); )
525 {
526 // ignore comments after '#' character
527 const size_t pound_idx = line.find('#');
528 if (pound_idx != std::string::npos)
529 line.resize(pound_idx);
530
531 // trim whitespace and ignore empty lines
532 boost::trim(line);
533 if (line.empty())
534 continue;
535
536 auto subnet = net::get_ipv4_subnet_address(line);
537 if (subnet)
538 {
539 block_subnet(*subnet, std::numeric_limits<time_t>::max());
540 continue;
541 }
542 const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(line, 0);
543 if (parsed_addr)
544 {
545 block_host(*parsed_addr, std::numeric_limits<time_t>::max());
546 continue;
547 }
548 MERROR("Invalid IP address or IPv4 subnet: " << line);
549 }
550 }
551
553 m_hide_my_port = true;
554
556 m_payload_handler.set_no_sync(true);
557
558 m_enable_dns_blocklist = command_line::get_arg(vm, arg_enable_dns_blocklist);
559
560 if ( !set_max_out_peers(public_zone, command_line::get_arg(vm, arg_out_peers) ) )
561 return false;
562 else
563 m_payload_handler.set_max_out_peers(epee::net_utils::zone::public_, public_zone.m_config.m_net_config.max_out_connection_count);
564
565
566 if ( !set_max_in_peers(public_zone, command_line::get_arg(vm, arg_in_peers) ) )
567 return false;
568
569 if ( !set_tos_flag(vm, command_line::get_arg(vm, arg_tos_flag) ) )
570 return false;
571
572 if ( !set_rate_up_limit(vm, command_line::get_arg(vm, arg_limit_rate_up) ) )
573 return false;
574
575 if ( !set_rate_down_limit(vm, command_line::get_arg(vm, arg_limit_rate_down) ) )
576 return false;
577
578 if ( !set_rate_limit(vm, command_line::get_arg(vm, arg_limit_rate) ) )
579 return false;
580
581
582 epee::byte_slice noise = nullptr;
583 auto proxies = get_proxies(vm);
584 if (!proxies)
585 return false;
586
587 for (auto& proxy : *proxies)
588 {
589 network_zone& zone = add_zone(proxy.zone);
590 if (zone.m_connect != nullptr)
591 {
592 MERROR("Listed --" << arg_tx_proxy.name << " twice with " << epee::net_utils::zone_to_string(proxy.zone));
593 return false;
594 }
595 zone.m_connect = &socks_connect;
596 zone.m_proxy_address = std::move(proxy.address);
597
598 if (!set_max_out_peers(zone, proxy.max_connections))
599 return false;
600 else
601 m_payload_handler.set_max_out_peers(proxy.zone, proxy.max_connections);
602
603 epee::byte_slice this_noise = nullptr;
604 if (proxy.noise)
605 {
606 static_assert(sizeof(epee::levin::bucket_head2) < CRYPTONOTE_NOISE_BYTES, "noise bytes too small");
607 if (noise.empty())
609
610 this_noise = noise.clone();
611 }
612
613 zone.m_notifier = cryptonote::levin::notify{
614 zone.m_net_server.get_io_context(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core()
615 };
616 }
617
618 for (const auto& zone : m_network_zones)
619 {
620 if (zone.second.m_connect == nullptr)
621 {
622 MERROR("Set outgoing peer for " << epee::net_utils::zone_to_string(zone.first) << " but did not set --" << arg_tx_proxy.name);
623 return false;
624 }
625 }
626
627 auto inbounds = get_anonymous_inbounds(vm);
628 if (!inbounds)
629 return false;
630
631 const std::size_t tx_relay_zones = m_network_zones.size();
632 for (auto& inbound : *inbounds)
633 {
634 network_zone& zone = add_zone(inbound.our_address.get_zone());
635
636 if (!zone.m_bind_ip.empty())
637 {
638 MERROR("Listed --" << arg_anonymous_inbound.name << " twice with " << epee::net_utils::zone_to_string(inbound.our_address.get_zone()) << " network");
639 return false;
640 }
641
642 if (zone.m_connect == nullptr && tx_relay_zones <= 1)
643 {
644 MERROR("Listed --" << arg_anonymous_inbound.name << " without listing any --" << arg_tx_proxy.name << ". The latter is necessary for sending local txes over anonymity networks");
645 return false;
646 }
647
648 zone.m_bind_ip = std::move(inbound.local_ip);
649 zone.m_port = std::move(inbound.local_port);
650 zone.m_net_server.set_default_remote(std::move(inbound.default_remote));
651 zone.m_our_address = std::move(inbound.our_address);
652
653 if (!set_max_in_peers(zone, inbound.max_connections))
654 return false;
655 }
656
658
659 return true;
660 }
661 //-----------------------------------------------------------------------------------
663 std::vector<epee::net_utils::network_address> & seed_nodes
664 , std::string const & addr
665 , uint16_t default_port
666 )
667 {
668 using namespace boost::asio;
669
670 // Split addr string into host string and port string
671 std::string host;
672 std::string port = std::to_string(default_port);
674 MINFO("Resolving node address: host=" << host << ", port=" << port);
675
676 boost::system::error_code ec;
677 io_context io_srv;
678 ip::tcp::resolver resolver(io_srv);
679 const auto results = resolver.resolve(host, port, boost::asio::ip::tcp::resolver::canonical_name, ec);
680 CHECK_AND_ASSERT_MES(!ec && !results.empty(), false, "Failed to resolve host name '" << host << "': " << ec.message() << ':' << ec.value());
681
682 for (const auto& result : results)
683 {
684 const auto& endpoint = result.endpoint();
685 if (endpoint.address().is_v4())
686 {
687 epee::net_utils::network_address na{epee::net_utils::ipv4_network_address{boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_uint()), endpoint.port()}};
688 seed_nodes.push_back(na);
689 MINFO("Added node: " << na.str());
690 }
691 else
692 {
693 epee::net_utils::network_address na{epee::net_utils::ipv6_network_address{endpoint.address().to_v6(), endpoint.port()}};
694 seed_nodes.push_back(na);
695 MINFO("Added node: " << na.str());
696 }
697 }
698 return true;
699 }
700
701 //-----------------------------------------------------------------------------------
702 template<class t_payload_net_handler>
704 {
705 std::set<std::string> full_addrs;
707 {
708 full_addrs.insert("176.9.0.187:28080");
709 full_addrs.insert("192.99.8.110:28080");
710 full_addrs.insert("37.187.74.171:28080");
711 full_addrs.insert("88.99.195.15:28080");
712 full_addrs.insert("5.104.84.64:28080");
713 }
715 {
716 full_addrs.insert("176.9.0.187:38080");
717 full_addrs.insert("192.99.8.110:38080");
718 full_addrs.insert("37.187.74.171:38080");
719 full_addrs.insert("88.99.195.15:38080");
720 full_addrs.insert("5.104.84.64:38080");
721 }
723 {
724 }
725 else
726 {
727 full_addrs.insert("176.9.0.187:18080");
728 full_addrs.insert("88.198.163.90:18080");
729 full_addrs.insert("192.99.8.110:18080");
730 full_addrs.insert("37.187.74.171:18080");
731 full_addrs.insert("88.99.195.15:18080");
732 full_addrs.insert("5.104.84.64:18080");
733 }
734 return full_addrs;
735 }
736 //-----------------------------------------------------------------------------------
737 template<class t_payload_net_handler>
739 {
740 if (!m_exclusive_peers.empty() || m_offline)
741 {
742 return {};
743 }
745 {
746 return get_ip_seed_nodes();
747 }
749 {
750 return get_ip_seed_nodes();
751 }
753 {
754 return {};
755 }
757 {
758 // TODO: a domain can be set through socks, so that the remote side does the lookup for the DNS seed nodes.
759 m_fallback_seed_nodes_added.test_and_set();
760 return get_ip_seed_nodes();
761 }
762
763 std::set<std::string> full_addrs;
764
765 // for each hostname in the seed nodes list, attempt to DNS resolve and
766 // add the result addresses as seed nodes
767 // TODO: at some point add IPv6 support, but that won't be relevant
768 // for some time yet.
769
770 struct frame_t
771 {
772 std::vector<std::vector<std::string>> dns_results;
773 boost::mutex sync;
774 };
775
776 const auto frame = std::make_shared<frame_t>();
777 frame->dns_results.resize(m_seed_nodes_list.size());
778
779 // some libc implementation provide only a very small stack
780 // for threads, e.g. musl only gives +- 80kb, which is not
781 // enough to do a resolve with unbound. we request a stack
782 // of 1 mb, which should be plenty
783 boost::thread::attributes thread_attributes;
784 thread_attributes.set_stack_size(1024*1024);
785
786 std::list<boost::thread> dns_threads;
787 uint64_t result_index = 0;
788 const std::weak_ptr<frame_t> frame_weak{frame};
789 for (const std::string& addr_str : m_seed_nodes_list)
790 {
791 boost::thread th = boost::thread(thread_attributes, [frame_weak, addr_str, result_index]
792 {
793 MDEBUG("dns_threads[" << result_index << "] created for: " << addr_str);
794 // TODO: care about dnssec avail/valid
795 bool avail, valid;
796 std::vector<std::string> addr_list = tools::DNSResolver::instance().get_ipv4(addr_str, avail, valid);
797 MINFO("dns_threads[" << result_index << "] addr_str: " << addr_str << " number of results: " << addr_list.size());
798 const auto frame = frame_weak.lock();
799 if (frame)
800 {
801 const boost::lock_guard<boost::mutex> lock{frame->sync};
802 frame->dns_results.at(result_index) = std::move(addr_list);
803 }
804 });
805
806 dns_threads.push_back(std::move(th));
807 ++result_index;
808 }
809
810 MDEBUG("dns_threads created, now waiting for completion or timeout of " << CRYPTONOTE_DNS_TIMEOUT_MS << "ms");
811 boost::chrono::system_clock::time_point deadline = boost::chrono::system_clock::now() + boost::chrono::milliseconds(CRYPTONOTE_DNS_TIMEOUT_MS);
812 uint64_t i = 0;
813 for (boost::thread& th : dns_threads)
814 {
815 if (! th.try_join_until(deadline))
816 {
817 MWARNING("dns_threads[" << i << "] timed out");
818 th.detach();
819 }
820 ++i;
821 }
822
823 i = 0;
824 const boost::lock_guard<boost::mutex> lock{frame->sync};
825 for (const auto& result : frame->dns_results)
826 {
827 MDEBUG("DNS lookup for " << m_seed_nodes_list[i] << ": " << result.size() << " results");
828 // if no results for node, thread's lookup likely timed out
829 if (result.size())
830 {
831 for (const auto& addr_string : result)
832 full_addrs.insert(addr_string + ":" + std::to_string(cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT));
833 }
834 ++i;
835 }
836
837 // append the fallback nodes if we have too few seed nodes to start with
838 if (full_addrs.size() < MIN_WANTED_SEED_NODES)
839 {
840 if (full_addrs.empty())
841 MINFO("DNS seed node lookup either timed out or failed, falling back to defaults");
842 else
843 MINFO("Not enough DNS seed nodes found, using fallback defaults too");
844
845 for (const auto &peer: get_ip_seed_nodes())
846 full_addrs.insert(peer);
847 m_fallback_seed_nodes_added.test_and_set();
848 }
849
850 return full_addrs;
851 }
852 //-----------------------------------------------------------------------------------
853 template<class t_payload_net_handler>
855 {
856 switch (zone)
857 {
859 return get_dns_seed_nodes();
862 {
863 return {
864 "zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083",
865 "plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion:18083",
866 "plowsoffjexmxalw73tkjmf422gq6575fc7vicuu4javzn2ynnte6tyd.onion:18083",
867 "plowsofe6cleftfmk2raiw5h2x66atrik3nja4bfd3zrfa2hdlgworad.onion:18083",
868 "aclc4e2jhhtr44guufbnwk5bzwhaecinax4yip4wr4tjn27sjsfg6zqd.onion:18083",
869 "lykcas4tus7mkm4bhsgqe4drtd4awi7gja24goscc47xfgzj54yofyqd.onion:18083",
870 };
871 }
872 return {};
875 {
876 return {
877 "uqj3aphckqtjsitz7kxx5flqpwjlq5ppr3chazfued7xucv3nheq.b32.i2p",
878 "vdmnehdjkpkg57nthgnjfuaqgku673r5bpbqg56ix6fyqoywgqrq.b32.i2p",
879 "ugnlcdciyhghh2zert7c3kl4biwkirc43ke33jiy5slnd3mv2trq.b32.i2p",
880 };
881 }
882 return {};
883 default:
884 break;
885 }
886 throw std::logic_error{"Bad zone given to get_seed_nodes"};
887 }
888 //-----------------------------------------------------------------------------------
889 template<class t_payload_net_handler>
891 {
892 const auto zone_ = m_network_zones.lower_bound(zone);
893 if (zone_ != m_network_zones.end() && zone_->first == zone)
894 return zone_->second;
895
897 return m_network_zones.emplace_hint(zone_, std::piecewise_construct, std::make_tuple(zone), std::tie(public_zone.m_net_server.get_io_context()))->second;
898 }
899 //-----------------------------------------------------------------------------------
900 template<class t_payload_net_handler>
901 bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm, const std::string& proxy, bool proxy_dns_leaks_allowed)
902 {
903 bool res = handle_command_line(vm);
904 CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line");
905 if (proxy.size())
906 {
907 const auto endpoint = net::socks::endpoint::get(proxy);
908 CHECK_AND_ASSERT_MES(endpoint, false, "Failed to parse proxy: " << proxy << " - " << endpoint.error().message());
910 public_zone.m_connect = &socks_connect;
911 public_zone.m_proxy_address = *endpoint;
912 public_zone.m_can_pingback = false;
913 m_enable_dns_seed_nodes &= proxy_dns_leaks_allowed;
914 m_enable_dns_blocklist &= proxy_dns_leaks_allowed;
915 }
916
918 {
920 }
922 {
924 }
925 else
926 {
928 }
929
932
933 if ((m_nettype == cryptonote::MAINNET && public_zone.m_port != std::to_string(::config::P2P_DEFAULT_PORT))
934 || (m_nettype == cryptonote::TESTNET && public_zone.m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))
935 || (m_nettype == cryptonote::STAGENET && public_zone.m_port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) {
936 m_config_folder = m_config_folder + "/" + public_zone.m_port;
937 }
938
939 res = init_config();
940 CHECK_AND_ASSERT_MES(res, false, "Failed to init config.");
941
942 for (auto& zone : m_network_zones)
943 {
944 res = zone.second.m_peerlist.init(m_peerlist_storage.take_zone(zone.first), m_allow_local_ip);
945 CHECK_AND_ASSERT_MES(res, false, "Failed to init peerlist.");
946 }
947
948 for(const auto& p: m_command_line_peers)
949 m_network_zones.at(p.adr.get_zone()).m_peerlist.append_with_peer_white(p);
950
951 //only in case if we really sure that we have external visible ip
952 m_have_address = true;
953
954 //configure self
955
956 public_zone.m_net_server.set_threads_prefix("P2P"); // all zones use these threads/asio::io_service
957
958 // from here onwards, it's online stuff
959 if (m_offline)
960 return res;
961
962 //try to bind
964 for (auto& zone : m_network_zones)
965 {
966 zone.second.m_net_server.get_config_object().set_handler(this);
967 zone.second.m_net_server.get_config_object().m_invoke_timeout = P2P_DEFAULT_INVOKE_TIMEOUT;
968
969 if (!zone.second.m_bind_ip.empty())
970 {
971 std::string ipv6_addr = "";
972 std::string ipv6_port = "";
973 zone.second.m_net_server.set_connection_filter(this);
974 zone.second.m_net_server.set_connection_limit(this);
975 MINFO("Binding (IPv4) on " << zone.second.m_bind_ip << ":" << zone.second.m_port);
976 if (!zone.second.m_bind_ipv6_address.empty() && m_use_ipv6)
977 {
978 ipv6_addr = zone.second.m_bind_ipv6_address;
979 ipv6_port = zone.second.m_port_ipv6;
980 MINFO("Binding (IPv6) on " << zone.second.m_bind_ipv6_address << ":" << zone.second.m_port_ipv6);
981 }
982 res = zone.second.m_net_server.init_server(zone.second.m_port, zone.second.m_bind_ip, ipv6_port, ipv6_addr, m_use_ipv6, m_require_ipv4, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
983 CHECK_AND_ASSERT_MES(res, false, "Failed to bind server");
984 }
985 }
986
988 MLOG_GREEN(el::Level::Info, "Net service bound (IPv4) to " << public_zone.m_bind_ip << ":" << m_listening_port);
989 if (m_use_ipv6)
990 {
992 MLOG_GREEN(el::Level::Info, "Net service bound (IPv6) to " << public_zone.m_bind_ipv6_address << ":" << m_listening_port_ipv6);
993 }
995 MDEBUG("External port defined as " << m_external_port);
996
997 return res;
998 }
999 //-----------------------------------------------------------------------------------
1000 template<class t_payload_net_handler>
1005 //-----------------------------------------------------------------------------------
1006 template<class t_payload_net_handler>
1008 {
1009 // creating thread to log number of connections
1010 mPeersLoggerThread.reset(new boost::thread([&]()
1011 {
1012 _note("Thread monitor number of peers - start");
1014 while (!is_closing && !public_zone.m_net_server.is_stop_signal_sent())
1015 { // main loop of thread
1016 //number_of_peers = m_net_server.get_config_object().get_connections_count();
1017 for (auto& zone : m_network_zones)
1018 {
1019 unsigned int number_of_in_peers = 0;
1020 unsigned int number_of_out_peers = 0;
1021 zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
1022 {
1023 if (cntxt.m_is_income)
1024 {
1025 ++number_of_in_peers;
1026 }
1027 else if (!cntxt.is_ping)
1028 {
1029 ++number_of_out_peers;
1030 }
1031 return true;
1032 }); // lambda
1033 zone.second.m_current_number_of_in_peers = number_of_in_peers;
1034 zone.second.m_current_number_of_out_peers = number_of_out_peers;
1035 }
1036 boost::this_thread::sleep_for(boost::chrono::seconds(1));
1037 } // main loop of thread
1038 _note("Thread monitor number of peers - done");
1039 })); // lambda
1040
1043 public_zone.m_net_server.add_idle_handler(boost::bind(&t_payload_net_handler::on_idle, &m_payload_handler), 1000);
1044
1045 //here you can set worker threads count
1046 int thrds_count = 10;
1047 boost::thread::attributes attrs;
1048 attrs.set_stack_size(THREAD_STACK_SIZE);
1049 //go to loop
1050 MINFO("Run net_service loop( " << thrds_count << " threads)...");
1051 if(!public_zone.m_net_server.run_server(thrds_count, true, attrs))
1052 {
1053 LOG_ERROR("Failed to run net tcp server!");
1054 }
1055
1056 MINFO("net_service loop stopped.");
1057 return true;
1058 }
1059 //-----------------------------------------------------------------------------------
1060 template<class t_payload_net_handler>
1062 {
1063 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
1064 if (public_zone == m_network_zones.end())
1065 return 0;
1066 return public_zone->second.m_net_server.get_config_object().get_connections_count();
1067 }
1068 //-----------------------------------------------------------------------------------
1069 template<class t_payload_net_handler>
1071 {
1072 kill();
1073
1074 if (!m_offline)
1075 {
1076 for(auto& zone : m_network_zones)
1077 zone.second.m_net_server.deinit_server();
1078 }
1079 return store_config();
1080 }
1081 //-----------------------------------------------------------------------------------
1082 template<class t_payload_net_handler>
1084 {
1085 TRY_ENTRY();
1086
1088 {
1089 MWARNING("Failed to create data directory \"" << m_config_folder);
1090 return false;
1091 }
1092
1093 peerlist_types active{};
1094 for (auto& zone : m_network_zones)
1095 zone.second.m_peerlist.get_peerlist(active);
1096
1097 const std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME;
1098 if (!m_peerlist_storage.store(state_file_path, active))
1099 {
1100 MWARNING("Failed to save config to file " << state_file_path);
1101 return false;
1102 }
1103 CATCH_ENTRY_L0("node_server::store", false);
1104 return true;
1105 }
1106 //-----------------------------------------------------------------------------------
1107 template<class t_payload_net_handler>
1109 {
1110 if (m_stop_signal_sent_once.exchange(true))
1111 {
1112 MDEBUG("[node] Stop signal already sent");
1113 return true;
1114 }
1115 MDEBUG("[node] stopping server payload handler");
1116 m_payload_handler.stop();
1117
1118 MDEBUG("[node] marking net servers as stopping");
1119 for (auto& zone : m_network_zones)
1120 {
1121 zone.second.m_net_server.mark_stop_signal_sent();
1122 }
1123
1124 MDEBUG("[node] closing connections");
1125 for (auto& zone : m_network_zones)
1126 {
1127 zone.second.m_net_server.close_server_connections();
1128
1129 std::list<boost::uuids::uuid> connection_ids;
1130 zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
1131 {
1132 connection_ids.push_back(cntxt.m_connection_id);
1133 return true;
1134 });
1135 for (const auto &connection_id: connection_ids)
1136 {
1137 MDEBUG("Closing connection " << connection_id);
1138 // All zone connections must finish shutting down before any shared io_context is stopped.
1139 zone.second.m_net_server.get_config_object().close(connection_id, true/*wait_for_shutdown*/);
1140 MDEBUG("Closed connection " << connection_id);
1141 }
1142 }
1143
1144 MDEBUG("[node] stopping net server io_contexts");
1145 for (auto& zone : m_network_zones)
1146 {
1147 zone.second.m_net_server.stop_io_context();
1148 }
1149 MDEBUG("[node] Stop signal sent");
1150 return true;
1151 }
1152 //-----------------------------------------------------------------------------------
1153 template<class t_payload_net_handler>
1155 {
1156 network_zone& zone = m_network_zones.at(context_.m_remote_address.get_zone());
1157
1158 typename COMMAND_HANDSHAKE::request arg;
1159 typename COMMAND_HANDSHAKE::response rsp;
1160 get_local_node_data(arg.node_data, zone);
1161 m_payload_handler.get_payload_sync_data(arg.payload_data);
1162
1164 std::atomic<bool> hsh_result(false);
1165 bool timeout = false;
1166
1167 bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_, COMMAND_HANDSHAKE::ID, arg, zone.m_net_server.get_config_object(),
1168 [this, &pi, &ev, &hsh_result, &just_take_peerlist, &context_, &timeout](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
1169 {
1170 epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();});
1171
1172 if(code < 0)
1173 {
1174 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")");
1176 timeout = true;
1177 return;
1178 }
1179
1180 if(rsp.node_data.network_id != m_network_id)
1181 {
1182 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE Failed, wrong network! (" << rsp.node_data.network_id << "), closing connection.");
1183 return;
1184 }
1185
1186 if(!handle_remote_peerlist(rsp.local_peerlist_new, context))
1187 {
1188 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection.");
1189 add_host_fail(context.m_remote_address);
1190 return;
1191 }
1192 hsh_result = true;
1193 if(!just_take_peerlist)
1194 {
1195 if(!m_payload_handler.process_payload_sync_data(rsp.payload_data, context, true))
1196 {
1197 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE invoked, but process_payload_sync_data returned false, dropping connection.");
1198 hsh_result = false;
1199 return;
1200 }
1201
1202 pi = context.peer_id = rsp.node_data.peer_id;
1203 context.m_rpc_port = rsp.node_data.rpc_port;
1204 context.m_rpc_credits_per_hash = rsp.node_data.rpc_credits_per_hash;
1205 context.support_flags = rsp.node_data.support_flags;
1206 const auto azone = context.m_remote_address.get_zone();
1207 network_zone& zone = m_network_zones.at(azone);
1208 zone.m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_address, context.m_pruning_seed, context.m_rpc_port, context.m_rpc_credits_per_hash);
1209
1210 // move
1211 if(azone == epee::net_utils::zone::public_ && rsp.node_data.peer_id == zone.m_config.m_peer_id)
1212 {
1213 LOG_DEBUG_CC(context, "Connection to self detected, dropping connection");
1214 hsh_result = false;
1215 return;
1216 }
1217 LOG_INFO_CC(context, "New connection handshaked, pruning seed " << epee::string_tools::to_string_hex(context.m_pruning_seed));
1218 LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE INVOKED OK");
1219 }else
1220 {
1221 LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK");
1222 }
1223 context_ = context;
1225
1226 if(r)
1227 {
1228 ev.wait();
1229 }
1230
1231 if(!hsh_result)
1232 {
1233 LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed");
1234 if (!timeout)
1235 zone.m_net_server.get_config_object().close(context_.m_connection_id, false);
1236 }
1237 else if (!just_take_peerlist)
1238 {
1239 if (context_.support_flags == 0)
1240 try_get_support_flags(context_, [](p2p_connection_context& flags_context, const uint32_t& support_flags)
1241 {
1242 flags_context.support_flags = support_flags;
1243 });
1244 }
1245
1246 return hsh_result;
1247 }
1248 //-----------------------------------------------------------------------------------
1249 template<class t_payload_net_handler>
1251 {
1252 typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg);
1253 m_payload_handler.get_payload_sync_data(arg.payload_data);
1254
1256 bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_, COMMAND_TIMED_SYNC::ID, arg, zone.m_net_server.get_config_object(),
1257 [this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context)
1258 {
1259 context.m_in_timedsync = false;
1260 if(code < 0)
1261 {
1262 LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")");
1263 return;
1264 }
1265
1266 if(!handle_remote_peerlist(rsp.local_peerlist_new, context))
1267 {
1268 LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection.");
1269 m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id, false);
1270 add_host_fail(context.m_remote_address);
1271 }
1272 if(!context.m_is_income)
1273 m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address, context.m_pruning_seed, context.m_rpc_port, context.m_rpc_credits_per_hash);
1274 if (!m_payload_handler.process_payload_sync_data(rsp.payload_data, context, false))
1275 {
1276 m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id, false);
1277 }
1278 });
1279
1280 if(!r)
1281 {
1282 LOG_WARNING_CC(context_, "COMMAND_TIMED_SYNC Failed");
1283 return false;
1284 }
1285 return true;
1286 }
1287 //-----------------------------------------------------------------------------------
1288 template<class t_payload_net_handler>
1290 {
1291 //divide by zero workaround
1292 if(!max_index)
1293 return 0;
1294
1295 size_t x = crypto::rand<size_t>()%(16*max_index+1);
1296 size_t res = (x*x*x)/(max_index*max_index*16*16*16); //parabola \/
1297 MDEBUG("Random connection index=" << res << "(x="<< x << ", max_index=" << max_index << ")");
1298 return res;
1299 }
1300 //-----------------------------------------------------------------------------------
1301 template<class t_payload_net_handler>
1303 {
1304 const auto zone = peer.adr.get_zone();
1305 const auto server = m_network_zones.find(zone);
1306 if (server == m_network_zones.end())
1307 return false;
1308
1309 const bool is_public = (zone == epee::net_utils::zone::public_);
1310 if(is_public && server->second.m_config.m_peer_id == peer.id)
1311 return true;//dont make connections to ourself
1312
1313 bool used = false;
1314 server->second.m_net_server.get_config_object().foreach_connection([&, is_public](const p2p_connection_context& cntxt)
1315 {
1316 if((is_public && cntxt.peer_id == peer.id && peer.adr.is_same_host(cntxt.m_remote_address)) || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
1317 {
1318 used = true;
1319 return false;//stop enumerating
1320 }
1321 return true;
1322 });
1323 return used;
1324 }
1325 //-----------------------------------------------------------------------------------
1326 template<class t_payload_net_handler>
1328 {
1329 const auto zone = peer.adr.get_zone();
1330 const auto server = m_network_zones.find(zone);
1331 if (server == m_network_zones.end())
1332 return false;
1333
1334 const bool is_public = (zone == epee::net_utils::zone::public_);
1335 if(is_public && server->second.m_config.m_peer_id == peer.id)
1336 return true;//dont make connections to ourself
1337
1338 bool used = false;
1339 server->second.m_net_server.get_config_object().foreach_connection([&, is_public](const p2p_connection_context& cntxt)
1340 {
1341 if((is_public && cntxt.peer_id == peer.id && peer.adr.is_same_host(cntxt.m_remote_address)) || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
1342 {
1343 used = true;
1344 return false;//stop enumerating
1345 }
1346 return true;
1347 });
1348 return used;
1349 }
1350 //-----------------------------------------------------------------------------------
1351 template<class t_payload_net_handler>
1353 {
1354 const auto zone = m_network_zones.find(peer.get_zone());
1355 if (zone == m_network_zones.end())
1356 return false;
1357
1358 bool connected = false;
1359 zone->second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
1360 {
1361 if(!cntxt.m_is_income && peer == cntxt.m_remote_address)
1362 {
1363 connected = true;
1364 return false;//stop enumerating
1365 }
1366 return true;
1367 });
1368
1369 return connected;
1370 }
1371
1372#define LOG_PRINT_CC_PRIORITY_NODE(priority, con, msg) \
1373 do { \
1374 if (priority) {\
1375 LOG_INFO_CC(con, "[priority]" << msg); \
1376 } else {\
1377 LOG_INFO_CC(con, msg); \
1378 } \
1379 } while(0)
1380
1381 template<class t_payload_net_handler>
1383 {
1384 network_zone& zone = m_network_zones.at(na.get_zone());
1385 if (zone.m_connect == nullptr) // outgoing connections in zone not possible
1386 return false;
1387
1388 if (zone.m_our_address == na)
1389 return false;
1390
1391 if (zone.m_current_number_of_out_peers == zone.m_config.m_net_config.max_out_connection_count) // out peers limit
1392 {
1393 return false;
1394 }
1395 else if (zone.m_current_number_of_out_peers > zone.m_config.m_net_config.max_out_connection_count)
1396 {
1397 zone.m_net_server.get_config_object().del_out_connections(1);
1398 --(zone.m_current_number_of_out_peers); // atomic variable, update time = 1s
1399 return false;
1400 }
1401
1402
1403 MDEBUG("Connecting to " << na.str() << " (peer_type=" << peer_type << ", last_seen: "
1404 << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
1405 << ")...");
1406
1407 auto con = zone.m_connect(zone, na, m_ssl_support);
1408 if(!con)
1409 {
1410 bool is_priority = is_priority_node(na);
1411 LOG_PRINT_CC_PRIORITY_NODE(is_priority, bool(con), "Connect failed to " << na.str()
1412 /*<< ", try " << try_count*/);
1414 return false;
1415 }
1416
1417 con->m_anchor = peer_type == anchor;
1418 peerid_type pi = AUTO_VAL_INIT(pi);
1419 bool res = do_handshake_with_peer(pi, *con, just_take_peerlist);
1420
1421 if(!res)
1422 {
1423 bool is_priority = is_priority_node(na);
1424 LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer "
1425 << na.str()
1426 /*<< ", try " << try_count*/);
1428 return false;
1429 }
1430
1431 if(just_take_peerlist)
1432 {
1433 zone.m_net_server.get_config_object().close(con->m_connection_id, false);
1434 LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
1435 return true;
1436 }
1437
1438 peerlist_entry pe_local = AUTO_VAL_INIT(pe_local);
1439 pe_local.adr = na;
1440 pe_local.id = pi;
1441 time_t last_seen;
1442 time(&last_seen);
1443 pe_local.last_seen = static_cast<int64_t>(last_seen);
1444 pe_local.pruning_seed = con->m_pruning_seed;
1445 pe_local.rpc_port = con->m_rpc_port;
1446 pe_local.rpc_credits_per_hash = con->m_rpc_credits_per_hash;
1447 zone.m_peerlist.append_with_peer_white(pe_local);
1448 //update last seen and push it to peerlist manager
1449
1451 ape.adr = na;
1452 ape.id = pi;
1453 ape.first_seen = first_seen_stamp ? first_seen_stamp : time(nullptr);
1454
1455 zone.m_peerlist.append_with_peer_anchor(ape);
1456 zone.m_notifier.on_handshake_complete(con->m_connection_id, con->m_is_income);
1457 zone.m_notifier.new_out_connection();
1458
1459 LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK.");
1460 return true;
1461 }
1462
1463 template<class t_payload_net_handler>
1465 {
1466 network_zone& zone = m_network_zones.at(na.get_zone());
1467 if (zone.m_connect == nullptr)
1468 return false;
1469
1470 LOG_PRINT_L1("Connecting to " << na.str() << "(last_seen: "
1471 << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
1472 << ")...");
1473
1474 auto con = zone.m_connect(zone, na, m_ssl_support);
1475 if (!con) {
1476 bool is_priority = is_priority_node(na);
1477
1478 LOG_PRINT_CC_PRIORITY_NODE(is_priority, p2p_connection_context{}, "Connect failed to " << na.str());
1480
1481 return false;
1482 }
1483
1484 con->m_anchor = false;
1485 peerid_type pi = AUTO_VAL_INIT(pi);
1486 const bool res = do_handshake_with_peer(pi, *con, true);
1487 if (!res) {
1488 bool is_priority = is_priority_node(na);
1489
1490 LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer " << na.str());
1492 return false;
1493 }
1494
1495 zone.m_net_server.get_config_object().close(con->m_connection_id, false);
1496
1497 LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
1498
1499 return true;
1500 }
1501
1502#undef LOG_PRINT_CC_PRIORITY_NODE
1503
1504 //-----------------------------------------------------------------------------------
1505 template<class t_payload_net_handler>
1511 //-----------------------------------------------------------------------------------
1512 template<class t_payload_net_handler>
1514 {
1516 auto it = m_conn_fails_cache.find(addr.host_str());
1517 if(it == m_conn_fails_cache.end())
1518 return false;
1519
1520 if(time(NULL) - it->second > P2P_FAILED_ADDR_FORGET_SECONDS)
1521 return false;
1522 else
1523 return true;
1524 }
1525 //-----------------------------------------------------------------------------------
1526 template<class t_payload_net_handler>
1527 bool node_server<t_payload_net_handler>::make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist)
1528 {
1529 for (const auto& pe: anchor_peerlist) {
1530 _note("Considering connecting (out) to anchor peer: " << peerid_to_string(pe.id) << " " << pe.adr.str());
1531
1532 if(is_peer_used(pe)) {
1533 _note("Peer is used");
1534 continue;
1535 }
1536
1537 if(!is_remote_host_allowed(pe.adr)) {
1538 continue;
1539 }
1540
1542 continue;
1543 }
1544
1545 MDEBUG("Selected peer: " << peerid_to_string(pe.id) << " " << pe.adr.str()
1546 << "[peer_type=" << anchor
1547 << "] first_seen: " << epee::misc_utils::get_time_interval_string(time(NULL) - pe.first_seen));
1548
1549 if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, 0, anchor, pe.first_seen)) {
1550 _note("Handshake failed");
1551 continue;
1552 }
1553
1554 return true;
1555 }
1556
1557 return false;
1558 }
1559 //-----------------------------------------------------------------------------------
1560 // Find a single candidate from the given peer list in the given zone and connect to it if possible
1561 template<class t_payload_net_handler>
1563 {
1564
1565 // Local helper method to get the host string, i.e. the pure IP address without port
1566 const auto get_host_string = [](const epee::net_utils::network_address &address) {
1568 {
1569 const boost::asio::ip::address_v6 actual_ip = address.as<const epee::net_utils::ipv6_network_address>().ip();
1570 if (actual_ip.is_v4_mapped())
1571 {
1572 boost::asio::ip::address_v4 v4ip = make_address_v4_from_v6(actual_ip);
1573 uint32_t actual_ipv4;
1574 memcpy(&actual_ipv4, v4ip.to_bytes().data(), sizeof(actual_ipv4));
1575 return epee::net_utils::ipv4_network_address(actual_ipv4, 0).host_str();
1576 }
1577 }
1578 return address.host_str();
1579 };
1580
1581 // Get the current list of known peers of the desired kind, ordered by 'last_seen'.
1582 // Deduplicate ports right away, i.e. if we know several peers on the same host address but
1583 // with different ports, take only one of them, to avoid giving such peers undue weight
1584 // and make it impossible to game peer selection by advertising on a large number of ports.
1585 // Making this list also insulates us from any changes that may happen to the original list
1586 // while we are working here, and allows an easy retry in the inner try loop.
1587 std::vector<peerlist_entry> peers;
1588 std::unordered_set<std::string> hosts;
1589 size_t total_peers_size = 0;
1590 zone.m_peerlist.foreach(use_white_list, [&peers, &hosts, &total_peers_size, &get_host_string](const peerlist_entry &peer)
1591 {
1592 ++total_peers_size;
1593 const std::string host_string = get_host_string(peer.adr);
1594 if (hosts.insert(host_string).second)
1595 {
1596 peers.push_back(peer);
1597 }
1598 // else ignore this additional peer on the same IP number
1599
1600 return true;
1601 });
1602
1603 const size_t peers_size = peers.size();
1604 MDEBUG("Looking at " << peers_size << " port-deduplicated peers out of " << total_peers_size
1605 << ", i.e. dropping " << (total_peers_size - peers_size));
1606
1607 std::set<uint64_t> tried_peers; // all peers ever tried
1608
1609 // Outer try loop, with up to 3 attempts to actually connect to a suitable randomly choosen candidate
1610 size_t outer_loop_count = 0;
1611 while ((outer_loop_count < 3) && !zone.m_net_server.is_stop_signal_sent())
1612 {
1613 ++outer_loop_count;
1614
1615 const uint32_t next_needed_pruning_stripe = m_payload_handler.get_next_needed_pruning_stripe().second;
1616
1617 // Build a list of all distinct /24 subnets we are connected to now right now; to catch
1618 // any connection changes, re-build the list for every outer try loop pass
1619 std::set<uint32_t> connected_subnets;
1620 const uint32_t subnet_mask = ntohl(0xffffff00);
1621 const bool is_public_zone = &zone == &m_network_zones.at(epee::net_utils::zone::public_);
1622 if (is_public_zone)
1623 {
1624 zone.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
1625 {
1626 if (cntxt.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
1627 {
1628 const epee::net_utils::network_address na = cntxt.m_remote_address;
1629 const uint32_t actual_ip = na.as<const epee::net_utils::ipv4_network_address>().ip();
1630 connected_subnets.insert(actual_ip & subnet_mask);
1631 }
1632 else if (cntxt.m_remote_address.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id())
1633 {
1634 const epee::net_utils::network_address na = cntxt.m_remote_address;
1635 const boost::asio::ip::address_v6 &actual_ip = na.as<const epee::net_utils::ipv6_network_address>().ip();
1636 if (actual_ip.is_v4_mapped())
1637 {
1638 boost::asio::ip::address_v4 v4ip = make_address_v4_from_v6(actual_ip);
1639 uint32_t actual_ipv4;
1640 memcpy(&actual_ipv4, v4ip.to_bytes().data(), sizeof(actual_ipv4));
1641 connected_subnets.insert(actual_ipv4 & subnet_mask);
1642 }
1643 }
1644 return true;
1645 });
1646 }
1647
1648 std::vector<peerlist_entry> subnet_peers;
1649 std::vector<peerlist_entry> filtered;
1650
1651 // Inner try loop: Find candidates first with subnet deduplication, if none found again without.
1652 // Finding none happens if all candidates are from subnets we are already connected to and/or
1653 // they don't offer the needed stripe when pruning. Only actually loop and deduplicate if we are
1654 // in the public zone because private zones don't have subnets.
1655 for (int step = 0; step < 2; ++step)
1656 {
1657 if ((step == 1) && !is_public_zone)
1658 break;
1659
1660 const bool try_subnet_dedup = step == 0 && is_public_zone;
1661 const std::vector<peerlist_entry> &candidate_peers = try_subnet_dedup ? subnet_peers : peers;
1662 if (try_subnet_dedup)
1663 {
1664 // Deduplicate subnets using 3 steps
1665
1666 // Step 1: Prepare to access the peers in a random order
1667 std::vector<size_t> shuffled_indexes(peers.size());
1668 std::iota(shuffled_indexes.begin(), shuffled_indexes.end(), 0);
1669 std::shuffle(shuffled_indexes.begin(), shuffled_indexes.end(), crypto::random_device{});
1670
1671 // Step 2: Deduplicate by only taking 1 candidate from each /24 subnet that occurs, the FIRST
1672 // candidate seen from each subnet within the now random order
1673 std::set<uint32_t> subnets = connected_subnets;
1674 for (size_t index : shuffled_indexes)
1675 {
1676 const peerlist_entry &peer = peers.at(index);
1677 bool take = true;
1679 {
1680 const epee::net_utils::network_address na = peer.adr;
1681 const uint32_t actual_ip = na.as<const epee::net_utils::ipv4_network_address>().ip();
1682 const uint32_t subnet = actual_ip & subnet_mask;
1683 take = subnets.find(subnet) == subnets.end();
1684 if (take)
1685 // This subnet is now "occupied", don't take any more candidates from this one
1686 subnets.insert(subnet);
1687 }
1689 {
1690 const epee::net_utils::network_address na = peer.adr;
1691 const boost::asio::ip::address_v6 &actual_ip = na.as<const epee::net_utils::ipv6_network_address>().ip();
1692 if (actual_ip.is_v4_mapped())
1693 {
1694 boost::asio::ip::address_v4 v4ip = make_address_v4_from_v6(actual_ip);
1695 uint32_t actual_ipv4;
1696 memcpy(&actual_ipv4, v4ip.to_bytes().data(), sizeof(actual_ipv4));
1697 uint32_t subnet = actual_ipv4 & subnet_mask;
1698 take = subnets.find(subnet) == subnets.end();
1699 if (take)
1700 subnets.insert(subnet);
1701 }
1702 // else 'take' stays true, we will take an IPv6 address that is not V4 mapped
1703 }
1704 if (take)
1705 subnet_peers.push_back(peer);
1706 }
1707
1708 // Step 3: Put back into order according to 'last_seen', i.e. most recently seen first
1709 std::sort(subnet_peers.begin(), subnet_peers.end(), [](const peerlist_entry &a, const peerlist_entry &b)
1710 {
1711 return a.last_seen > b.last_seen;
1712 });
1713
1714 const size_t subnet_peers_size = subnet_peers.size();
1715 MDEBUG("Looking at " << subnet_peers_size << " subnet-deduplicated peers out of " << peers_size
1716 << ", i.e. dropping " << (peers_size - subnet_peers_size));
1717 } // deduplicate
1718 // else, for step 1 / second pass of inner try loop, take all peers from all subnets
1719
1720 // Take as many candidates as we need and care about stripes if pruning
1721 const size_t limit = use_white_list ? 20 : std::numeric_limits<size_t>::max();
1722 for (const peerlist_entry &peer : candidate_peers) {
1723 if (filtered.size() >= limit)
1724 break;
1725 if (tried_peers.count(peer.id))
1726 // Already tried, not a possible candidate
1727 continue;
1728
1729 if (next_needed_pruning_stripe == 0 || peer.pruning_seed == 0)
1730 filtered.push_back(peer);
1731 else if (next_needed_pruning_stripe == tools::get_pruning_stripe(peer.pruning_seed))
1732 filtered.insert(filtered.begin(), peer);
1733 // else wrong stripe, skip
1734 }
1735
1736 if (!filtered.empty())
1737 break;
1738 } // inner try loop
1739
1740 if (filtered.empty())
1741 {
1742 MINFO("No available peer in " << (use_white_list ? "white" : "gray") << " list filtered by " << next_needed_pruning_stripe);
1743 return false;
1744 }
1745
1746 size_t random_index;
1747 if (use_white_list)
1748 {
1749 // If using the white list, we first pick in the set of peers we've already been using earlier;
1750 // that "fixed probability" heavily favors the peers most recently seen in the candidate list
1751 random_index = get_random_index_with_fixed_probability(filtered.size() - 1);
1752
1754 if (next_needed_pruning_stripe > 0 && next_needed_pruning_stripe <= (1ul << CRYPTONOTE_PRUNING_LOG_STRIPES) && !m_used_stripe_peers[next_needed_pruning_stripe-1].empty())
1755 {
1756 const epee::net_utils::network_address na = m_used_stripe_peers[next_needed_pruning_stripe-1].front();
1757 m_used_stripe_peers[next_needed_pruning_stripe-1].pop_front();
1758 for (size_t i = 0; i < filtered.size(); ++i)
1759 {
1760 const peerlist_entry &peer = filtered.at(i);
1761 if (peer.adr == na)
1762 {
1763 MDEBUG("Reusing stripe " << next_needed_pruning_stripe << " peer " << peer.adr.str());
1764 random_index = i;
1765 break;
1766 }
1767 }
1768 }
1769 }
1770 else
1771 random_index = crypto::rand_idx(filtered.size());
1772 CHECK_AND_ASSERT_MES(random_index < filtered.size(), false, "random_index < filtered.size() failed!!");
1773
1774 // We have our final candidate for this pass of the outer try loop
1775 const peerlist_entry &candidate = filtered.at(random_index);
1776
1777 if (tried_peers.count(candidate.id))
1778 // Already tried, don't try that one again
1779 continue;
1780 tried_peers.insert(candidate.id);
1781
1782 _note("Considering connecting (out) to " << (use_white_list ? "white" : "gray") << " list peer: " <<
1783 peerid_to_string(candidate.id) << " " << candidate.adr.str() << ", pruning seed " << epee::string_tools::to_string_hex(candidate.pruning_seed) <<
1784 " (stripe " << next_needed_pruning_stripe << " needed), in loop pass " << outer_loop_count);
1785
1786 if (zone.m_our_address == candidate.adr)
1787 // It's ourselves, obviously don't take that
1788 continue;
1789
1790 if (is_peer_used(candidate)) {
1791 _note("Peer is used");
1792 continue;
1793 }
1794
1795 if (!is_remote_host_allowed(candidate.adr)) {
1796 _note("Not allowed");
1797 continue;
1798 }
1799
1800 if (is_addr_recently_failed(candidate.adr)) {
1801 _note("Recently failed");
1802 continue;
1803 }
1804
1805 MDEBUG("Selected peer: " << peerid_to_string(candidate.id) << " " << candidate.adr.str()
1806 << ", pruning seed " << epee::string_tools::to_string_hex(candidate.pruning_seed) << " "
1807 << "[peer_list=" << (use_white_list ? white : gray)
1808 << "] last_seen: " << (candidate.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - candidate.last_seen) : "never"));
1809
1810 const time_t begin_connect = time(NULL);
1811 if (!try_to_connect_and_handshake_with_new_peer(candidate.adr, false, candidate.last_seen, use_white_list ? white : gray)) {
1812 time_t fail_connect = time(NULL);
1813 _note("Handshake failed after " << epee::misc_utils::get_time_interval_string(fail_connect - begin_connect));
1814 continue;
1815 }
1816
1817 return true;
1818 } // outer try loop
1819
1820 return false;
1821 }
1822 //-----------------------------------------------------------------------------------
1823 template<class t_payload_net_handler>
1825 {
1826 network_zone& server = m_network_zones.at(zone);
1827 boost::upgrade_lock<boost::shared_mutex> seed_nodes_upgrade_lock(server.m_seed_nodes_lock);
1828
1829 if (!server.m_seed_nodes_initialized)
1830 {
1831 const std::uint16_t default_port = cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT;
1832 boost::upgrade_to_unique_lock<boost::shared_mutex> seed_nodes_lock(seed_nodes_upgrade_lock);
1833 server.m_seed_nodes_initialized = true;
1834 for (const auto& full_addr : get_seed_nodes(zone))
1835 {
1836 // seeds should have hostname converted to IP already
1837 MDEBUG("Seed node: " << full_addr);
1838 server.m_seed_nodes.push_back(MONERO_UNWRAP(net::get_network_address(full_addr, default_port)));
1839 }
1840 MDEBUG("Number of seed nodes: " << server.m_seed_nodes.size());
1841 }
1842
1843 if (server.m_seed_nodes.empty() || m_offline || !m_exclusive_peers.empty())
1844 return true;
1845
1846 size_t try_count = 0;
1847 bool is_connected_to_at_least_one_seed_node = false;
1848 size_t current_index = crypto::rand_idx(server.m_seed_nodes.size());
1849 while(true)
1850 {
1852 return false;
1853
1854 peerlist_entry pe_seed{};
1855 pe_seed.adr = server.m_seed_nodes[current_index];
1856 if (is_peer_used(pe_seed))
1857 is_connected_to_at_least_one_seed_node = true;
1858 else if (try_to_connect_and_handshake_with_new_peer(server.m_seed_nodes[current_index], true))
1859 break;
1860 if(++try_count > server.m_seed_nodes.size())
1861 {
1862 // only IP zone has fallback (to direct IP) seeds
1863 if (zone == epee::net_utils::zone::public_ && !m_fallback_seed_nodes_added.test_and_set())
1864 {
1865 MWARNING("Failed to connect to any of seed peers, trying fallback seeds");
1866 current_index = server.m_seed_nodes.size() - 1;
1867 {
1868 boost::upgrade_to_unique_lock<boost::shared_mutex> seed_nodes_lock(seed_nodes_upgrade_lock);
1869
1870 for (const auto &peer: get_ip_seed_nodes())
1871 {
1872 MDEBUG("Fallback seed node: " << peer);
1873 append_net_address(server.m_seed_nodes, peer, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
1874 }
1875 }
1876 if (current_index == server.m_seed_nodes.size() - 1)
1877 {
1878 MWARNING("No fallback seeds, continuing without seeds");
1879 break;
1880 }
1881 // continue for another few cycles
1882 }
1883 else
1884 {
1885 if (!is_connected_to_at_least_one_seed_node)
1886 MWARNING("Failed to connect to any of seed peers, continuing without seeds");
1887 break;
1888 }
1889 }
1890 if(++current_index >= server.m_seed_nodes.size())
1891 current_index = 0;
1892 }
1893 return true;
1894 }
1895 //-----------------------------------------------------------------------------------
1896 template<class t_payload_net_handler>
1898 {
1899 using zone_type = epee::net_utils::zone;
1900
1901 if (m_offline) return true;
1902 if (!connect_to_peerlist(m_exclusive_peers)) return false;
1903
1904 if (!m_exclusive_peers.empty()) return true;
1905
1906 bool one_succeeded = false;
1907 for(auto& zone : m_network_zones)
1908 {
1909 size_t start_conn_count = get_outgoing_connections_count(zone.second);
1910 if(!zone.second.m_peerlist.get_white_peers_count() && !connect_to_seed(zone.first))
1911 {
1912 continue;
1913 }
1914
1915 if (zone.first == zone_type::public_ && !connect_to_peerlist(m_priority_peers)) continue;
1916
1917 size_t base_expected_white_connections = (zone.second.m_config.m_net_config.max_out_connection_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
1918
1919 // carefully avoid `continue` in nested loop
1920
1921 size_t conn_count = get_outgoing_connections_count(zone.second);
1922 while(conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
1923 {
1924 const size_t expected_white_connections = m_payload_handler.get_next_needed_pruning_stripe().second ? zone.second.m_config.m_net_config.max_out_connection_count : base_expected_white_connections;
1925 if(conn_count < expected_white_connections)
1926 {
1927 //start from anchor list
1930 //then do white list
1931 while (get_outgoing_connections_count(zone.second) < expected_white_connections
1932 && make_expected_connections_count(zone.second, white, expected_white_connections));
1933 //then do grey list
1934 while (get_outgoing_connections_count(zone.second) < zone.second.m_config.m_net_config.max_out_connection_count
1935 && make_expected_connections_count(zone.second, gray, zone.second.m_config.m_net_config.max_out_connection_count));
1936 }else
1937 {
1938 //start from grey list
1939 while (get_outgoing_connections_count(zone.second) < zone.second.m_config.m_net_config.max_out_connection_count
1940 && make_expected_connections_count(zone.second, gray, zone.second.m_config.m_net_config.max_out_connection_count));
1941 //and then do white list
1942 while (get_outgoing_connections_count(zone.second) < zone.second.m_config.m_net_config.max_out_connection_count
1943 && make_expected_connections_count(zone.second, white, zone.second.m_config.m_net_config.max_out_connection_count));
1944 }
1945 if(zone.second.m_net_server.is_stop_signal_sent())
1946 return false;
1947 size_t new_conn_count = get_outgoing_connections_count(zone.second);
1948 if (new_conn_count <= conn_count)
1949 {
1950 // we did not make any connection, sleep a bit to avoid a busy loop in case we don't have
1951 // any peers to try, then break so we will try seeds to get more peers
1952 boost::this_thread::sleep_for(boost::chrono::seconds(1));
1953 break;
1954 }
1955 conn_count = new_conn_count;
1956 }
1957
1958 if (start_conn_count == get_outgoing_connections_count(zone.second) && start_conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
1959 {
1960 MINFO("Failed to connect to any, trying seeds");
1961 if (!connect_to_seed(zone.first))
1962 continue;
1963 }
1964 one_succeeded = true;
1965 }
1966
1967 return one_succeeded;
1968 }
1969 //-----------------------------------------------------------------------------------
1970 template<class t_payload_net_handler>
1972 {
1973 if (m_offline)
1974 return false;
1975
1976 std::vector<anchor_peerlist_entry> apl;
1977
1978 if (peer_type == anchor) {
1979 zone.m_peerlist.get_and_empty_anchor_peerlist(apl);
1980 }
1981
1982 size_t conn_count = get_outgoing_connections_count(zone);
1983 //add new connections from white peers
1984 if(conn_count < expected_connections)
1985 {
1986 if(zone.m_net_server.is_stop_signal_sent())
1987 return false;
1988
1989 MDEBUG("Making expected connection, type " << peer_type << ", " << conn_count << "/" << expected_connections << " connections");
1990
1991 if (peer_type == anchor && !make_new_connection_from_anchor_peerlist(apl)) {
1992 return false;
1993 }
1994
1995 if (peer_type == white && !make_new_connection_from_peerlist(zone, true)) {
1996 return false;
1997 }
1998
1999 if (peer_type == gray && !make_new_connection_from_peerlist(zone, false)) {
2000 return false;
2001 }
2002 }
2003 return true;
2004 }
2005 //-----------------------------------------------------------------------------------
2006 template<class t_payload_net_handler>
2008 {
2009 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2010 if (public_zone == m_network_zones.end())
2011 return 0;
2012 return get_outgoing_connections_count(public_zone->second);
2013 }
2014 //-----------------------------------------------------------------------------------
2015 template<class t_payload_net_handler>
2017 {
2018 size_t count = 0;
2019 zone.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
2020 {
2021 if(cntxt.m_is_income)
2022 ++count;
2023 return true;
2024 });
2025 return count;
2026 }
2027 //-----------------------------------------------------------------------------------
2028 template<class t_payload_net_handler>
2030 {
2031 size_t count = 0;
2032 zone.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
2033 {
2034 if(!cntxt.m_is_income && !cntxt.is_ping)
2035 ++count;
2036 return true;
2037 });
2038
2039 // Refresh the counter in the zone. The thread that the 'run' method sets up for the
2040 // job to update the counters runs only once every second. If we only rely on that,
2041 // 'try_to_connect_and_handshake_with_new_peer' called in 'make_new_connection_from_peerlist'
2042 // will often fail right away because it thinks there are still enough connections, with
2043 // perfectly good new peer candidates totally wasted, and a bad success rate choosing peers
2044 zone.m_current_number_of_out_peers = count;
2045
2046 return count;
2047 }
2048 //-----------------------------------------------------------------------------------
2049 template<class t_payload_net_handler>
2051 {
2052 size_t count = 0;
2053 for(auto& zone : m_network_zones)
2054 count += get_outgoing_connections_count(zone.second);
2055 return count;
2056 }
2057 //-----------------------------------------------------------------------------------
2058 template<class t_payload_net_handler>
2060 {
2061 size_t count = 0;
2062 for (auto& zone : m_network_zones)
2063 {
2064 zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
2065 {
2066 if(cntxt.m_is_income)
2067 ++count;
2068 return true;
2069 });
2070 }
2071 return count;
2072 }
2073 //-----------------------------------------------------------------------------------
2074 template<class t_payload_net_handler>
2076 {
2077 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2078 if (public_zone == m_network_zones.end())
2079 return 0;
2080 return public_zone->second.m_peerlist.get_white_peers_count();
2081 }
2082 //-----------------------------------------------------------------------------------
2083 template<class t_payload_net_handler>
2085 {
2086 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2087 if (public_zone == m_network_zones.end())
2088 return 0;
2089 return public_zone->second.m_peerlist.get_gray_peers_count();
2090 }
2091 //-----------------------------------------------------------------------------------
2092 template<class t_payload_net_handler>
2093 void node_server<t_payload_net_handler>::get_public_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white)
2094 {
2095 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2096 if (public_zone != m_network_zones.end())
2097 public_zone->second.m_peerlist.get_peerlist(gray, white);
2098 }
2099 //-----------------------------------------------------------------------------------
2100 template<class t_payload_net_handler>
2101 void node_server<t_payload_net_handler>::get_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white)
2102 {
2103 for (auto &zone: m_network_zones)
2104 {
2105 zone.second.m_peerlist.get_peerlist(gray, white); // appends
2106 }
2107 }
2108 //-----------------------------------------------------------------------------------
2109 template<class t_payload_net_handler>
2120 //-----------------------------------------------------------------------------------
2121 template<class t_payload_net_handler>
2123 {
2125 return true;
2127 return true;
2128
2129 static const std::vector<std::string> dns_urls = {
2130 "blocklist.moneropulse.se"
2131 , "blocklist.moneropulse.org"
2132 , "blocklist.moneropulse.net"
2133 , "blocklist.moneropulse.co"
2134 , "blocklist.moneropulse.fr"
2135 , "blocklist.moneropulse.de"
2136 , "blocklist.moneropulse.ch"
2137 };
2138
2139 std::vector<std::string> records;
2140 if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls))
2141 return true;
2142
2143 unsigned good = 0, bad = 0;
2144 for (const auto& record : records)
2145 {
2146 std::vector<std::string> ips;
2147 boost::split(ips, record, boost::is_any_of(";"));
2148 for (const auto &ip: ips)
2149 {
2150 if (ip.empty())
2151 continue;
2152 auto subnet = net::get_ipv4_subnet_address(ip);
2153 if (subnet)
2154 {
2156 ++good;
2157 continue;
2158 }
2160 if (parsed_addr)
2161 {
2162 block_host(*parsed_addr, DNS_BLOCKLIST_LIFETIME, true);
2163 ++good;
2164 continue;
2165 }
2166 MWARNING("Invalid IP address or subnet from DNS blocklist: " << ip << " - " << parsed_addr.error());
2167 ++bad;
2168 }
2169 }
2170 if (good > 0)
2171 MINFO(good << " addresses added to the blocklist");
2172 return true;
2173 }
2174 //-----------------------------------------------------------------------------------
2175 template<class t_payload_net_handler>
2177 {
2178 if (m_offline)
2179 return true;
2180
2181 const auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2182 if (public_zone != m_network_zones.end() && get_incoming_connections_count(public_zone->second) == 0)
2183 {
2184 if (m_hide_my_port || public_zone->second.m_config.m_net_config.max_in_connection_count == 0)
2185 {
2186 MGINFO("Incoming connections disabled, enable them for full connectivity");
2187 }
2188 else
2189 {
2190 const el::Level level = el::Level::Warning;
2191 MCLOG_RED(level, "global", "No incoming connections - check firewalls/routers allow port " << get_this_peer_port());
2192 }
2193 }
2194 return true;
2195 }
2196 //-----------------------------------------------------------------------------------
2197 template<class t_payload_net_handler>
2199 {
2200 MDEBUG("STARTED PEERLIST IDLE HANDSHAKE");
2201 typedef std::list<std::pair<epee::net_utils::connection_context_base, peerid_type> > local_connects_type;
2202 local_connects_type cncts;
2203 for(auto& zone : m_network_zones)
2204 {
2205 zone.second.m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntxt)
2206 {
2207 if(cntxt.peer_id && !cntxt.m_in_timedsync)
2208 {
2209 cntxt.m_in_timedsync = true;
2210 cncts.push_back(local_connects_type::value_type(cntxt, cntxt.peer_id));//do idle sync only with handshaked connections
2211 }
2212 return true;
2213 });
2214 }
2215
2216 std::for_each(cncts.begin(), cncts.end(), [&](const typename local_connects_type::value_type& vl){do_peer_timed_sync(vl.first, vl.second);});
2217
2218 MDEBUG("FINISHED PEERLIST IDLE HANDSHAKE");
2219 return true;
2220 }
2221 //-----------------------------------------------------------------------------------
2222 template<class t_payload_net_handler>
2223 bool node_server<t_payload_net_handler>::sanitize_peerlist(std::vector<peerlist_entry>& local_peerlist)
2224 {
2225 for (size_t i = 0; i < local_peerlist.size(); ++i)
2226 {
2227 bool ignore = false;
2228 peerlist_entry &be = local_peerlist[i];
2230 if (na.is_loopback() || na.is_local())
2231 {
2232 ignore = true;
2233 }
2235 {
2237 if (ipv4.ip() == 0)
2238 ignore = true;
2239 else if (ipv4.port() == be.rpc_port)
2240 ignore = true;
2241 }
2243 ignore = true;
2244 if (ignore)
2245 {
2246 MDEBUG("Ignoring " << be.adr.str());
2247 std::swap(local_peerlist[i], local_peerlist[local_peerlist.size() - 1]);
2248 local_peerlist.resize(local_peerlist.size() - 1);
2249 --i;
2250 continue;
2251 }
2252 local_peerlist[i].last_seen = 0;
2253 }
2254 return true;
2255 }
2256 //-----------------------------------------------------------------------------------
2257 template<class t_payload_net_handler>
2259 {
2260 if (peerlist.size() > P2P_MAX_PEERS_IN_HANDSHAKE)
2261 {
2262 MWARNING(context << "peer sent " << peerlist.size() << " peers, considered spamming");
2263 return false;
2264 }
2265 std::vector<peerlist_entry> peerlist_ = peerlist;
2266 if(!sanitize_peerlist(peerlist_))
2267 return false;
2268
2269 const epee::net_utils::zone zone = context.m_remote_address.get_zone();
2270 for(const auto& peer : peerlist_)
2271 {
2272 if(peer.adr.get_zone() != zone)
2273 {
2274 MWARNING(context << " sent peerlist from another zone, dropping");
2275 return false;
2276 }
2277 }
2278
2279 LOG_DEBUG_CC(context, "REMOTE PEERLIST: remote peerlist size=" << peerlist_.size());
2280 LOG_TRACE_CC(context, "REMOTE PEERLIST: " << ENDL << print_peerlist_to_string(peerlist_));
2282 return m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.merge_peerlist(peerlist_, [this](const peerlist_entry &pe) {
2284 });
2285 }
2286 //-----------------------------------------------------------------------------------
2287 template<class t_payload_net_handler>
2289 {
2290 node_data.peer_id = zone.m_config.m_peer_id;
2291 if(!m_hide_my_port && zone.m_can_pingback)
2293 else
2294 node_data.my_port = 0;
2295 node_data.rpc_port = zone.m_can_pingback ? m_rpc_port : 0;
2296 node_data.rpc_credits_per_hash = zone.m_can_pingback ? m_rpc_credits_per_hash : 0;
2297 node_data.network_id = m_network_id;
2298 node_data.support_flags = zone.m_config.m_support_flags;
2299 return true;
2300 }
2301 //-----------------------------------------------------------------------------------
2302 template<class t_payload_net_handler>
2304 {
2305 rsp.support_flags = m_network_zones.at(context.m_remote_address.get_zone()).m_config.m_support_flags;
2306 return 1;
2307 }
2308 //-----------------------------------------------------------------------------------
2309 template<class t_payload_net_handler>
2311 {
2312 m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().request_callback(context.m_connection_id);
2313 }
2314 //-----------------------------------------------------------------------------------
2315 template<class t_payload_net_handler>
2316 bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, epee::levin::message_writer data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)
2317 {
2318 epee::byte_slice message = data_buff.finalize_notify(command);
2319 std::sort(connections.begin(), connections.end());
2320 auto zone = m_network_zones.begin();
2321 for(const auto& c_id: connections)
2322 {
2323 for (;;)
2324 {
2325 if (zone == m_network_zones.end())
2326 {
2327 MWARNING("Unable to relay all messages, " << epee::net_utils::zone_to_string(c_id.first) << " not available");
2328 return false;
2329 }
2330 if (c_id.first <= zone->first)
2331 break;
2332
2333 ++zone;
2334 }
2335 if (zone->first == c_id.first)
2336 zone->second.m_net_server.get_config_object().send(message.clone(), c_id.second);
2337 }
2338 return true;
2339 }
2340 //-----------------------------------------------------------------------------------
2341 template<class t_payload_net_handler>
2342 epee::net_utils::zone node_server<t_payload_net_handler>::send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, const cryptonote::relay_method tx_relay)
2343 {
2344 namespace enet = epee::net_utils;
2345
2346 const auto send = [&txs, &source, tx_relay] (std::pair<const enet::zone, network_zone>& network)
2347 {
2348 if (network.second.m_notifier.send_txs(std::move(txs), source, tx_relay))
2349 return network.first;
2350 return enet::zone::invalid;
2351 };
2352
2353 if (m_network_zones.empty())
2354 return enet::zone::invalid;
2355
2356 if (origin != enet::zone::invalid)
2357 return send(*m_network_zones.begin()); // send all txs received via p2p over public network
2358
2359 if (m_network_zones.size() <= 2)
2360 return send(*m_network_zones.rbegin()); // see static asserts below; sends over anonymity network iff enabled
2361
2362 /* These checks are to ensure that i2p is highest priority if multiple
2363 zones are selected. Make sure to update logic if the values cannot be
2364 in the same relative order. `m_network_zones` must be sorted map too. */
2365 static_assert(std::is_same<std::underlying_type<enet::zone>::type, std::uint8_t>{}, "expected uint8_t zone");
2366 static_assert(unsigned(enet::zone::invalid) == 0, "invalid expected to be 0");
2367 static_assert(unsigned(enet::zone::public_) == 1, "public_ expected to be 1");
2368 static_assert(unsigned(enet::zone::i2p) == 2, "i2p expected to be 2");
2369 static_assert(unsigned(enet::zone::tor) == 3, "tor expected to be 3");
2370
2371 // check for anonymity networks with noise and connections
2372 for (auto network = ++m_network_zones.begin(); network != m_network_zones.end(); ++network)
2373 {
2374 if (enet::zone::tor < network->first)
2375 break; // unknown network
2376
2377 const auto status = network->second.m_notifier.get_status();
2378 if (status.has_noise && status.connections_filled)
2379 return send(*network);
2380 }
2381
2382 // use the anonymity network with outbound support
2383 for (auto network = ++m_network_zones.begin(); network != m_network_zones.end(); ++network)
2384 {
2385 if (enet::zone::tor < network->first)
2386 break; // unknown network
2387
2388 const auto status = network->second.m_notifier.get_status();
2389 if (network->second.m_connect && status.has_outgoing)
2390 return send(*network);
2391 }
2392
2393 MWARNING("Unable to send " << txs.size() << " transaction(s): anonymity networks had no outgoing connections");
2394 return enet::zone::invalid;
2395 }
2396 //-----------------------------------------------------------------------------------
2397 template<class t_payload_net_handler>
2399 {
2400 m_payload_handler.on_callback(context);
2401 }
2402 //-----------------------------------------------------------------------------------
2403 template<class t_payload_net_handler>
2405 {
2406 if(is_filtered_command(context.m_remote_address, command))
2407 return false;
2408
2409 network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
2410 int res = zone.m_net_server.get_config_object().send(message.finalize_notify(command), context.m_connection_id);
2411 return res > 0;
2412 }
2413 //-----------------------------------------------------------------------------------
2414 template<class t_payload_net_handler>
2416 {
2417 m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id, false);
2418 return true;
2419 }
2420 //-----------------------------------------------------------------------------------
2421 template<class t_payload_net_handler> template<class t_callback>
2423 {
2424 if(!node_data.my_port)
2425 return false;
2426
2427 bool address_ok = (context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id() || context.m_remote_address.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id());
2428 CHECK_AND_ASSERT_MES(address_ok, false,
2429 "Only IPv4 or IPv6 addresses are supported here");
2430
2431 const epee::net_utils::network_address na = context.m_remote_address;
2432 std::string ip;
2433 uint32_t ipv4_addr = 0;
2434 boost::asio::ip::address_v6 ipv6_addr;
2435 bool is_ipv4;
2437 {
2438 ipv4_addr = na.as<const epee::net_utils::ipv4_network_address>().ip();
2440 is_ipv4 = true;
2441 }
2442 else
2443 {
2444 ipv6_addr = na.as<const epee::net_utils::ipv6_network_address>().ip();
2445 ip = ipv6_addr.to_string();
2446 is_ipv4 = false;
2447 }
2448 network_zone& zone = m_network_zones.at(na.get_zone());
2449
2450 if(!zone.m_peerlist.is_host_allowed(context.m_remote_address))
2451 return false;
2452
2453 std::string port = epee::string_tools::num_to_string_fast(node_data.my_port);
2454
2456 if (is_ipv4)
2457 {
2459 }
2460 else
2461 {
2463 }
2464 peerid_type pr = node_data.peer_id;
2465 bool r = zone.m_net_server.connect_async(ip, port, zone.m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ address, pr, this](
2466 const typename net_server::t_connection_context& ping_context,
2467 const boost::system::error_code& ec)->bool
2468 {
2469 if(ec)
2470 {
2471 LOG_WARNING_CC(ping_context, "back ping connect failed to " << address.str());
2472 return false;
2473 }
2476 //vc2010 workaround
2477 /*std::string ip_ = ip;
2478 std::string port_=port;
2479 peerid_type pr_ = pr;
2480 auto cb_ = cb;*/
2481
2482 // GCC 5.1.0 gives error with second use of uint64_t (peerid_type) variable.
2483 peerid_type pr_ = pr;
2484
2485 network_zone& zone = m_network_zones.at(address.get_zone());
2486
2487 bool inv_call_res = epee::net_utils::async_invoke_remote_command2<COMMAND_PING::response>(ping_context, COMMAND_PING::ID, req, zone.m_net_server.get_config_object(),
2488 [=](int code, const COMMAND_PING::response& rsp, p2p_connection_context& context)
2489 {
2490 if(code <= 0)
2491 {
2492 LOG_WARNING_CC(ping_context, "Failed to invoke COMMAND_PING to " << address.str() << "(" << code << ", " << epee::levin::get_err_descr(code) << ")");
2493 return;
2494 }
2495
2496 network_zone& zone = m_network_zones.at(address.get_zone());
2497 if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id)
2498 {
2499 LOG_WARNING_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << address.str() << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << peerid_to_string(rsp.peer_id));
2500 zone.m_net_server.get_config_object().close(ping_context.m_connection_id, false);
2501 return;
2502 }
2503 zone.m_net_server.get_config_object().close(ping_context.m_connection_id, false);
2504 cb();
2505 });
2506
2507 if(!inv_call_res)
2508 {
2509 LOG_WARNING_CC(ping_context, "back ping invoke failed to " << address.str());
2510 zone.m_net_server.get_config_object().close(ping_context.m_connection_id, false);
2511 return false;
2512 }
2513 return true;
2514 }, "0.0.0.0", m_ssl_support, p2p_connection_context{true /* is_ping */});
2515 if(!r)
2516 {
2517 LOG_WARNING_CC(context, "Failed to call connect_async, network error.");
2518 }
2519 return r;
2520 }
2521 //-----------------------------------------------------------------------------------
2522 template<class t_payload_net_handler>
2524 {
2525 if(context.m_remote_address.get_zone() != epee::net_utils::zone::public_)
2526 return false;
2527
2528 COMMAND_REQUEST_SUPPORT_FLAGS::request support_flags_request;
2530 (
2531 context,
2533 support_flags_request,
2534 m_network_zones.at(epee::net_utils::zone::public_).m_net_server.get_config_object(),
2535 [=](int code, const typename COMMAND_REQUEST_SUPPORT_FLAGS::response& rsp, p2p_connection_context& context_)
2536 {
2537 if(code < 0)
2538 {
2539 LOG_WARNING_CC(context_, "COMMAND_REQUEST_SUPPORT_FLAGS invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")");
2540 return;
2541 }
2542
2543 f(context_, rsp.support_flags);
2544 },
2546 );
2547
2548 return r;
2549 }
2550 //-----------------------------------------------------------------------------------
2551 template<class t_payload_net_handler>
2553 {
2554 if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, false))
2555 {
2556 LOG_WARNING_CC(context, "Failed to process_payload_sync_data(), dropping connection");
2557 drop_connection(context);
2558 return 1;
2559 }
2560
2561 //fill response
2562 const epee::net_utils::zone zone_type = context.m_remote_address.get_zone();
2563 network_zone& zone = m_network_zones.at(zone_type);
2564
2565 //will add self to peerlist if in same zone as outgoing later in this function
2566 const bool outgoing_to_same_zone = !context.m_is_income && zone.m_our_address.get_zone() == zone_type;
2567 const uint32_t max_peerlist_size = P2P_DEFAULT_PEERS_IN_HANDSHAKE - (outgoing_to_same_zone ? 1 : 0);
2568
2569 std::vector<peerlist_entry> local_peerlist_new;
2570 zone.m_peerlist.get_peerlist_head(local_peerlist_new, true, max_peerlist_size);
2571
2572 /* Tor/I2P nodes receiving connections via forwarding (from tor/i2p daemon)
2573 do not know the address of the connecting peer. This is relayed to them,
2574 iff the node has setup an inbound hidden service.
2575
2576 \note Insert into `local_peerlist_new` so that it is only sent once like
2577 the other peers. */
2578 if(outgoing_to_same_zone)
2579 {
2580 local_peerlist_new.insert(
2581 local_peerlist_new.begin() + crypto::rand_range(std::size_t(0), local_peerlist_new.size()),
2582 peerlist_entry{zone.m_our_address, zone.m_config.m_peer_id, 0}
2583 );
2584 }
2585
2586 //only include out peers we did not already send
2587 rsp.local_peerlist_new.reserve(local_peerlist_new.size());
2588 for (auto &pe: local_peerlist_new)
2589 {
2590 if (!context.sent_addresses.insert(pe.adr).second)
2591 continue;
2592 rsp.local_peerlist_new.push_back(std::move(pe));
2593 }
2594 m_payload_handler.get_payload_sync_data(rsp.payload_data);
2595
2596 LOG_DEBUG_CC(context, "COMMAND_TIMED_SYNC");
2597 return 1;
2598 }
2599 //-----------------------------------------------------------------------------------
2600 template<class t_payload_net_handler>
2602 {
2603 if(arg.node_data.network_id != m_network_id)
2604 {
2605
2606 LOG_INFO_CC(context, "WRONG NETWORK AGENT CONNECTED! id=" << arg.node_data.network_id);
2607 drop_connection(context);
2608 add_host_fail(context.m_remote_address);
2609 return 1;
2610 }
2611
2612 if(!context.m_is_income)
2613 {
2614 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came not from incoming connection");
2615 drop_connection(context);
2616 add_host_fail(context.m_remote_address);
2617 return 1;
2618 }
2619
2620 if(context.peer_id)
2621 {
2622 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but seems that connection already have associated peer_id (double COMMAND_HANDSHAKE?)");
2623 drop_connection(context);
2624 return 1;
2625 }
2626
2627 const auto azone = context.m_remote_address.get_zone();
2628 network_zone& zone = m_network_zones.at(azone);
2629
2630 // test only the remote end's zone, otherwise an attacker could connect to you on clearnet
2631 // and pass in a tor connection's peer id, and deduce the two are the same if you reject it
2632 if(azone == epee::net_utils::zone::public_ && arg.node_data.peer_id == zone.m_config.m_peer_id)
2633 {
2634 LOG_DEBUG_CC(context, "Connection to self detected, dropping connection");
2635 drop_connection(context);
2636 return 1;
2637 }
2638
2639 if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, true))
2640 {
2641 LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but process_payload_sync_data returned false, dropping connection.");
2642 drop_connection(context);
2643 return 1;
2644 }
2645
2646 zone.m_notifier.on_handshake_complete(context.m_connection_id, context.m_is_income);
2647
2648 //associate peer_id with this connection
2649 context.peer_id = arg.node_data.peer_id;
2650 context.m_in_timedsync = false;
2651 context.m_rpc_port = arg.node_data.rpc_port;
2652 context.m_rpc_credits_per_hash = arg.node_data.rpc_credits_per_hash;
2653 context.support_flags = arg.node_data.support_flags;
2654
2655 if(arg.node_data.my_port && zone.m_can_pingback)
2656 {
2657 peerid_type peer_id_l = arg.node_data.peer_id;
2658 uint32_t port_l = arg.node_data.my_port;
2659 //try ping to be sure that we can add this peer to peer_list
2660 try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]()
2661 {
2662 CHECK_AND_ASSERT_MES((context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id() || context.m_remote_address.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id()), void(),
2663 "Only IPv4 or IPv6 addresses are supported here");
2664 //called only(!) if success pinged, update local peerlist
2665 peerlist_entry pe;
2666 const epee::net_utils::network_address na = context.m_remote_address;
2667 if (context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
2668 {
2669 pe.adr = epee::net_utils::ipv4_network_address(na.as<epee::net_utils::ipv4_network_address>().ip(), port_l);
2670 }
2671 else
2672 {
2673 pe.adr = epee::net_utils::ipv6_network_address(na.as<epee::net_utils::ipv6_network_address>().ip(), port_l);
2674 }
2675 time_t last_seen;
2676 time(&last_seen);
2677 pe.last_seen = static_cast<int64_t>(last_seen);
2678 pe.id = peer_id_l;
2679 pe.pruning_seed = context.m_pruning_seed;
2680 pe.rpc_port = context.m_rpc_port;
2681 pe.rpc_credits_per_hash = context.m_rpc_credits_per_hash;
2682 this->m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.append_with_peer_white(pe);
2683 LOG_DEBUG_CC(context, "PING SUCCESS " << context.m_remote_address.host_str() << ":" << port_l);
2684 });
2685 }
2686
2687 if (context.support_flags == 0)
2688 try_get_support_flags(context, [](p2p_connection_context& flags_context, const uint32_t& support_flags)
2689 {
2690 flags_context.support_flags = support_flags;
2691 });
2692
2693 //fill response
2694 zone.m_peerlist.get_peerlist_head(rsp.local_peerlist_new, true);
2695 for (const auto &e: rsp.local_peerlist_new)
2696 context.sent_addresses.insert(e.adr);
2697 get_local_node_data(rsp.node_data, zone);
2698 m_payload_handler.get_payload_sync_data(rsp.payload_data);
2699 LOG_DEBUG_CC(context, "COMMAND_HANDSHAKE");
2700 return 1;
2701 }
2702 //-----------------------------------------------------------------------------------
2703 template<class t_payload_net_handler>
2705 {
2706 LOG_DEBUG_CC(context, "COMMAND_PING");
2707 rsp.status = PING_OK_RESPONSE_STATUS_TEXT;
2708 rsp.peer_id = m_network_zones.at(context.m_remote_address.get_zone()).m_config.m_peer_id;
2709 return 1;
2710 }
2711 //-----------------------------------------------------------------------------------
2712 template<class t_payload_net_handler>
2714 {
2715 std::vector<peerlist_entry> pl_white;
2716 std::vector<peerlist_entry> pl_gray;
2717 for (auto& zone : m_network_zones)
2718 zone.second.m_peerlist.get_peerlist(pl_gray, pl_white);
2719 MINFO(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_white) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) );
2720 return true;
2721 }
2722 //-----------------------------------------------------------------------------------
2723 template<class t_payload_net_handler>
2725 {
2726 MINFO("Connections: \r\n" << print_connections_container() );
2727 return true;
2728 }
2729 //-----------------------------------------------------------------------------------
2730 template<class t_payload_net_handler>
2732 {
2733
2734 std::stringstream ss;
2735 for (auto& zone : m_network_zones)
2736 {
2737 zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
2738 {
2739 ss << cntxt.m_remote_address.str()
2740 << " \t\tpeer_id " << peerid_to_string(cntxt.peer_id)
2741 << " \t\tconn_id " << cntxt.m_connection_id << (cntxt.m_is_income ? " INC":" OUT")
2742 << std::endl;
2743 return true;
2744 });
2745 }
2746 std::string s = ss.str();
2747 return s;
2748 }
2749 //-----------------------------------------------------------------------------------
2750 template<class t_payload_net_handler>
2752 {
2753 MINFO("["<< epee::net_utils::print_connection_context(context) << "] NEW CONNECTION");
2754 }
2755 //-----------------------------------------------------------------------------------
2756 template<class t_payload_net_handler>
2758 {
2759 network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
2760 if (!zone.m_net_server.is_stop_signal_sent() && !context.m_is_income) {
2762 na = context.m_remote_address;
2763
2764 zone.m_peerlist.remove_from_peer_anchor(na);
2765 }
2766
2767 if (!zone.m_net_server.is_stop_signal_sent()) {
2768 zone.m_notifier.on_connection_close(context.m_connection_id);
2769 }
2770 m_payload_handler.on_connection_close(context);
2771
2772 MINFO("["<< epee::net_utils::print_connection_context(context) << "] CLOSE CONNECTION");
2773 }
2774
2775 template<class t_payload_net_handler>
2777 {
2778 return (std::find(m_priority_peers.begin(), m_priority_peers.end(), na) != m_priority_peers.end()) || (std::find(m_exclusive_peers.begin(), m_exclusive_peers.end(), na) != m_exclusive_peers.end());
2779 }
2780
2781 template<class t_payload_net_handler> template <class Container>
2783 {
2785 for(const epee::net_utils::network_address& na: peers)
2786 {
2787 if(public_zone.m_net_server.is_stop_signal_sent())
2788 return false;
2789
2790 if(is_addr_connected(na))
2791 continue;
2792
2794 }
2795
2796 return true;
2797 }
2798
2799 template<class t_payload_net_handler> template <class Container>
2800 bool node_server<t_payload_net_handler>::parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor<std::vector<std::string> > & arg, Container& container)
2801 {
2802 std::vector<std::string> perrs = command_line::get_arg(vm, arg);
2803
2804 for(const std::string& pr_str: perrs)
2805 {
2808 if (adr)
2809 {
2810 add_zone(adr->get_zone());
2811 container.push_back(std::move(*adr));
2812 continue;
2813 }
2814 std::vector<epee::net_utils::network_address> resolved_addrs;
2815 bool r = append_net_address(resolved_addrs, pr_str, default_port);
2816 CHECK_AND_ASSERT_MES(r, false, "Failed to parse or resolve address from string: " << pr_str);
2817 for (const epee::net_utils::network_address& addr : resolved_addrs)
2818 {
2819 container.push_back(addr);
2820 }
2821 }
2822
2823 return true;
2824 }
2825
2826 template<class t_payload_net_handler>
2828 {
2829 if(max == -1) {
2830 zone.m_config.m_net_config.max_out_connection_count = P2P_DEFAULT_CONNECTIONS_COUNT;
2831 return true;
2832 }
2833 zone.m_config.m_net_config.max_out_connection_count = max;
2834 return true;
2835 }
2836
2837 template<class t_payload_net_handler>
2839 {
2840 zone.m_config.m_net_config.max_in_connection_count = max;
2841 return true;
2842 }
2843
2844 template<class t_payload_net_handler>
2846 {
2847 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2848 if (public_zone != m_network_zones.end())
2849 {
2850 const auto current = public_zone->second.m_net_server.get_config_object().get_out_connections_count();
2851 public_zone->second.m_config.m_net_config.max_out_connection_count = count;
2852 if(current > count)
2853 public_zone->second.m_net_server.get_config_object().del_out_connections(current - count);
2854 m_payload_handler.set_max_out_peers(epee::net_utils::zone::public_, count);
2855 }
2856 }
2857
2858 template<class t_payload_net_handler>
2860 {
2861 const auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2862 if (public_zone == m_network_zones.end())
2863 return 0;
2864 return public_zone->second.m_config.m_net_config.max_out_connection_count;
2865 }
2866
2867 template<class t_payload_net_handler>
2869 {
2870 auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2871 if (public_zone != m_network_zones.end())
2872 {
2873 const auto current = public_zone->second.m_net_server.get_config_object().get_in_connections_count();
2874 public_zone->second.m_config.m_net_config.max_in_connection_count = count;
2875 if(current > count)
2876 public_zone->second.m_net_server.get_config_object().del_in_connections(current - count);
2877 }
2878 }
2879
2880 template<class t_payload_net_handler>
2882 {
2883 const auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
2884 if (public_zone == m_network_zones.end())
2885 return 0;
2886 return public_zone->second.m_config.m_net_config.max_in_connection_count;
2887 }
2888
2889 template<class t_payload_net_handler>
2890 bool node_server<t_payload_net_handler>::set_tos_flag(const boost::program_options::variables_map& vm, int flag)
2891 {
2892 if(flag==-1){
2893 return true;
2894 }
2896 _dbg1("Set ToS flag " << flag);
2897 return true;
2898 }
2899
2900 template<class t_payload_net_handler>
2901 bool node_server<t_payload_net_handler>::set_rate_up_limit(const boost::program_options::variables_map& vm, int64_t limit)
2902 {
2903 this->islimitup=(limit != -1) && (limit != default_limit_up);
2904
2905 if (limit==-1) {
2906 limit=default_limit_up;
2907 }
2908
2910 MINFO("Set limit-up to " << limit << " kB/s");
2911 return true;
2912 }
2913
2914 template<class t_payload_net_handler>
2915 bool node_server<t_payload_net_handler>::set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit)
2916 {
2917 this->islimitdown=(limit != -1) && (limit != default_limit_down);
2918 if(limit==-1) {
2919 limit=default_limit_down;
2920 }
2922 MINFO("Set limit-down to " << limit << " kB/s");
2923 return true;
2924 }
2925
2926 template<class t_payload_net_handler>
2927 bool node_server<t_payload_net_handler>::set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit)
2928 {
2929 int64_t limit_up = 0;
2930 int64_t limit_down = 0;
2931
2932 if(limit == -1)
2933 {
2934 limit_up = default_limit_up;
2935 limit_down = default_limit_down;
2936 }
2937 else
2938 {
2939 limit_up = limit;
2940 limit_down = limit;
2941 }
2942 if(!this->islimitup) {
2944 MINFO("Set limit-up to " << limit_up << " kB/s");
2945 }
2946 if(!this->islimitdown) {
2948 MINFO("Set limit-down to " << limit_down << " kB/s");
2949 }
2950
2951 return true;
2952 }
2953
2954 template<class t_payload_net_handler>
2956 {
2957 if (address.get_zone() != epee::net_utils::zone::public_)
2958 return false; // Unable to determine how many connections from host
2959
2960 uint32_t count = 0;
2961
2962 m_network_zones.at(epee::net_utils::zone::public_).m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
2963 {
2964 if (cntxt.m_is_income && cntxt.m_remote_address.is_same_host(address)) {
2965 count++;
2966
2967 // the only call location happens BEFORE foreach_connection list is updated
2968 if (count >= max_connections) {
2969 return false;
2970 }
2971 }
2972
2973 return true;
2974 });
2975 // the only call location happens BEFORE foreach_connection list is updated
2976 return count >= max_connections;
2977 }
2978
2979 template<class t_payload_net_handler>
2981 {
2982 if (m_offline) return true;
2983 if (!m_exclusive_peers.empty()) return true;
2984
2985 for (auto& zone : m_network_zones)
2986 {
2987 if (m_payload_handler.needs_new_sync_connections(zone.first))
2988 continue;
2989
2990 if (zone.second.m_net_server.is_stop_signal_sent())
2991 return false;
2992
2993 if (zone.second.m_connect == nullptr)
2994 continue;
2995
2996 peerlist_entry pe{};
2997 if (!zone.second.m_peerlist.get_random_gray_peer(pe))
2998 continue;
2999
3001 {
3002 zone.second.m_peerlist.remove_from_peer_gray(pe);
3003 LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST: address: " << pe.adr.host_str() << " Peer ID: " << peerid_to_string(pe.id));
3004 }
3005 else
3006 {
3007 zone.second.m_peerlist.set_peer_just_seen(pe.id, pe.adr, pe.pruning_seed, pe.rpc_port, pe.rpc_credits_per_hash);
3008 LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_to_string(pe.id));
3009 }
3010 }
3011 return true;
3012 }
3013
3014 template<class t_payload_net_handler>
3015 void node_server<t_payload_net_handler>::add_used_stripe_peer(const typename t_payload_net_handler::connection_context &context)
3016 {
3017 const uint32_t stripe = tools::get_pruning_stripe(context.m_pruning_seed);
3018 if (stripe == 0 || stripe > (1ul << CRYPTONOTE_PRUNING_LOG_STRIPES))
3019 return;
3020 const uint32_t index = stripe - 1;
3022 MINFO("adding stripe " << stripe << " peer: " << context.m_remote_address.str());
3023 m_used_stripe_peers[index].erase(std::remove_if(m_used_stripe_peers[index].begin(), m_used_stripe_peers[index].end(),
3024 [&context](const epee::net_utils::network_address &na){ return context.m_remote_address == na; }), m_used_stripe_peers[index].end());
3025 m_used_stripe_peers[index].push_back(context.m_remote_address);
3026 }
3027
3028 template<class t_payload_net_handler>
3029 void node_server<t_payload_net_handler>::remove_used_stripe_peer(const typename t_payload_net_handler::connection_context &context)
3030 {
3031 const uint32_t stripe = tools::get_pruning_stripe(context.m_pruning_seed);
3032 if (stripe == 0 || stripe > (1ul << CRYPTONOTE_PRUNING_LOG_STRIPES))
3033 return;
3034 const uint32_t index = stripe - 1;
3036 MINFO("removing stripe " << stripe << " peer: " << context.m_remote_address.str());
3037 m_used_stripe_peers[index].erase(std::remove_if(m_used_stripe_peers[index].begin(), m_used_stripe_peers[index].end(),
3038 [&context](const epee::net_utils::network_address &na){ return context.m_remote_address == na; }), m_used_stripe_peers[index].end());
3039 }
3040
3041 template<class t_payload_net_handler>
3043 {
3045 MINFO("clearing used stripe peers");
3046 for (auto &e: m_used_stripe_peers)
3047 e.clear();
3048 }
3049
3050 template<typename t_payload_net_handler>
3051 boost::optional<p2p_connection_context_t<typename t_payload_net_handler::connection_context>>
3053 {
3054 auto result = socks_connect_internal(zone.m_net_server.get_stop_signal(), zone.m_net_server.get_io_context(), zone.m_proxy_address, remote);
3055 if (result) // if no error
3056 {
3057 p2p_connection_context context{};
3058 if (zone.m_net_server.add_connection(context, std::move(*result), remote, ssl_support))
3059 return {std::move(context)};
3060 }
3061 return boost::none;
3062 }
3063
3064 template<typename t_payload_net_handler>
3065 boost::optional<p2p_connection_context_t<typename t_payload_net_handler::connection_context>>
3067 {
3070 CHECK_AND_ASSERT_MES(is_ipv4 || is_ipv6, boost::none,
3071 "Only IPv4 or IPv6 addresses are supported here");
3072
3073 std::string address;
3074 std::string port;
3075
3076 if (is_ipv4)
3077 {
3080 port = epee::string_tools::num_to_string_fast(ipv4.port());
3081 }
3082 else if (is_ipv6)
3083 {
3085 address = ipv6.ip().to_string();
3086 port = epee::string_tools::num_to_string_fast(ipv6.port());
3087 }
3088 else
3089 {
3090 LOG_ERROR("Only IPv4 or IPv6 addresses are supported here");
3091 return boost::none;
3092 }
3093
3094 typename net_server::t_connection_context con{};
3095 const bool res = zone.m_net_server.connect(address, port,
3096 zone.m_config.m_net_config.connection_timeout,
3097 con, "0.0.0.0", ssl_support);
3098
3099 if (res)
3100 return {std::move(con)};
3101 return boost::none;
3102 }
3103}
#define s(x, c)
Definition aesb.c:47
cryptonote::block b
Definition block.cpp:40
Provides tx notification privacy.
Definition levin_notify.h:70
Definition byte_slice.h:69
byte_slice clone() const noexcept
Definition byte_slice.h:124
bool empty() const noexcept
Definition byte_slice.h:132
Provides space for levin (p2p) header, so that payload can be sent without copy.
Definition levin_base.h:132
byte_slice finalize_notify(uint32_t command)
Definition levin_base.h:152
bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms)
Definition abstract_tcp_server2.h:481
bool is_stop_signal_sent() const noexcept
Definition abstract_tcp_server2.h:397
boost::asio::io_context & get_io_context()
Definition abstract_tcp_server2.h:450
epee::levin::async_protocol_handler< p2p_connection_context >::connection_context t_connection_context
Definition abstract_tcp_server2.h:357
int get_binded_port_ipv6()
Definition abstract_tcp_server2.h:441
t_protocol_handler::config_type & get_config_object()
Definition abstract_tcp_server2.h:428
bool run_server(size_t threads_count, bool wait=true, const boost::thread::attributes &attrs=boost::thread::attributes())
Run the server's io_context loop.
Definition abstract_tcp_server2.inl:1494
void set_threads_prefix(const std::string &prefix_name)
Definition abstract_tcp_server2.inl:1463
std::shared_ptr< typename t_protocol_handler::config_type > get_config_shared()
Definition abstract_tcp_server2.h:434
int get_binded_port()
Definition abstract_tcp_server2.h:440
Represents a single connection from a client.
Definition abstract_tcp_server2.h:100
Definition net_utils_base.h:69
static constexpr address_type get_type_id() noexcept
Definition net_utils_base.h:92
std::string host_str() const
Definition net_utils_base.cpp:31
Definition net_utils_base.h:125
bool matches(const ipv4_network_address &address) const
Definition net_utils_base.cpp:61
std::string host_str() const
Definition net_utils_base.cpp:58
Definition net_utils_base.h:172
static constexpr address_type get_type_id() noexcept
Definition net_utils_base.h:198
Definition net_utils_base.h:225
bool is_loopback() const
Definition net_utils_base.h:314
std::string str() const
Definition net_utils_base.h:312
address_type get_type_id() const
Definition net_utils_base.h:316
bool is_same_host(const network_address &other) const
Definition net_utils_base.cpp:90
std::uint16_t port() const
Definition net_utils_base.h:319
bool is_local() const
Definition net_utils_base.h:315
std::string host_str() const
Definition net_utils_base.h:313
zone get_zone() const
Definition net_utils_base.h:317
bool is_blockable() const
Definition net_utils_base.h:318
const Type & as() const
Definition net_utils_base.h:320
Definition expect.h:134
*return False if otherwise error()
virtual void callback(p2p_connection_context &context)
Definition net_node.inl:2398
bool set_max_in_peers(network_zone &zone, int64_t max)
Definition net_node.inl:2838
peerlist_storage m_peerlist_storage
Definition net_node.h:460
bool try_ping(basic_node_data &node_data, p2p_connection_context &context, const t_callback &cb)
Definition net_node.inl:2422
std::map< epee::net_utils::zone, network_zone > m_network_zones
Definition net_node.h:486
bool set_max_out_peers(network_zone &zone, int64_t max)
Definition net_node.inl:2827
virtual void on_connection_new(p2p_connection_context &context)
Definition net_node.inl:2751
if(is_filtered_command(context.m_remote_address, command)) return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED
bool m_first_connection_maker_call
Definition net_node.h:442
virtual void for_each_connection(std::function< bool(typename t_payload_net_handler::connection_context &, peerid_type, uint32_t)> f)
Definition net_node.inl:151
std::vector< nodetool::peerlist_entry > m_command_line_peers
Definition net_node.h:472
epee::critical_section m_conn_fails_cache_lock
Definition net_node.h:490
static boost::optional< p2p_connection_context > public_connect(network_zone &, epee::net_utils::network_address const &, epee::net_utils::ssl_support_t)
Definition net_node.inl:3066
virtual void remove_used_stripe_peer(const typename t_payload_net_handler::connection_context &context)
Definition net_node.inl:3029
void change_max_in_public_peers(size_t count)
Definition net_node.inl:2868
bool connect_to_seed(epee::net_utils::zone)
Definition net_node.inl:1824
std::list< epee::net_utils::network_address > m_priority_peers
Definition net_node.h:469
std::string print_connections_container()
Definition net_node.inl:2731
virtual bool block_host(epee::net_utils::network_address address, time_t seconds=P2P_IP_BLOCKTIME, bool add_only=false)
Definition net_node.inl:248
virtual bool relay_notify_to_list(int command, epee::levin::message_writer message, std::vector< std::pair< epee::net_utils::zone, boost::uuids::uuid > > connections) final
Definition net_node.inl:2316
void change_max_out_public_peers(size_t count)
Definition net_node.inl:2845
bool try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address &na, bool just_take_peerlist=false, uint64_t last_seen_stamp=0, PeerType peer_type=white, uint64_t first_seen_stamp=0)
Definition net_node.inl:1382
bool m_enable_dns_seed_nodes
Definition net_node.h:507
boost::mutex m_used_stripe_peers_mutex
Definition net_node.h:499
bool m_offline
Definition net_node.h:450
bool do_peer_timed_sync(const epee::net_utils::connection_context_base &context, peerid_type peer_id)
Definition net_node.inl:1250
std::string m_config_folder
Definition net_node.h:439
uint32_t get_this_peer_port()
Definition net_node.h:266
bool islimitup
Definition net_node.h:305
void kill()
Definition net_node.h:414
PeerType
Definition net_node.h:322
@ gray
Definition net_node.h:322
@ anchor
Definition net_node.h:322
@ white
Definition net_node.h:322
bool set_tos_flag(const boost::program_options::variables_map &vm, int limit)
Definition net_node.inl:2890
std::unique_ptr< boost::thread > mPeersLoggerThread
Definition net_node.h:455
virtual ~node_server()
Definition net_node.inl:85
virtual void clear_used_stripe_peers()
Definition net_node.inl:3042
std::atomic< bool > is_closing
Definition net_node.h:453
bool handle_command_line(const boost::program_options::variables_map &vm)
Definition net_node.inl:425
bool log_peerlist()
Definition net_node.inl:2713
epee::math_helper::once_a_time_seconds< 7000 > m_dns_blocklist_interval
Definition net_node.h:467
int handle_ping(int command, COMMAND_PING::request &arg, COMMAND_PING::response &rsp, p2p_connection_context &context)
Definition net_node.inl:2704
uint32_t get_max_out_public_peers() const
Definition net_node.inl:2859
std::map< std::string, time_t > m_blocked_hosts
Definition net_node.h:493
bool check_connection_and_handshake_with_peer(const epee::net_utils::network_address &na, uint64_t last_seen_stamp)
Definition net_node.inl:1464
virtual bool drop_connection(const epee::net_utils::connection_context_base &context)
Definition net_node.inl:2415
t_payload_net_handler & get_payload_object()
Definition net_node.inl:1001
bool islimitdown
Definition net_node.h:306
virtual uint64_t get_public_connections_count()
Definition net_node.inl:1061
bool m_allow_local_ip
Definition net_node.h:448
bool run()
Definition net_node.inl:1007
size_t get_outgoing_connections_count()
Definition net_node.inl:2050
virtual bool unblock_subnet(const epee::net_utils::ipv4_network_subnet &subnet)
Definition net_node.inl:394
epee::critical_section m_blocked_hosts_lock
Definition net_node.h:492
epee::math_helper::once_a_time_seconds< 60 *30, false > m_peerlist_store_interval
Definition net_node.h:464
uint32_t m_rpc_credits_per_hash
Definition net_node.h:447
virtual void on_connection_close(p2p_connection_context &context)
Definition net_node.inl:2757
bool handle_remote_peerlist(const std::vector< peerlist_entry > &peerlist, const epee::net_utils::connection_context_base &context)
Definition net_node.inl:2258
bool is_addr_recently_failed(const epee::net_utils::network_address &addr)
Definition net_node.inl:1513
static boost::optional< p2p_connection_context > socks_connect(network_zone &, epee::net_utils::network_address const &, epee::net_utils::ssl_support_t)
Definition net_node.inl:3052
network_zone & add_zone(epee::net_utils::zone zone)
Definition net_node.inl:890
size_t get_public_white_peers_count()
Definition net_node.inl:2075
epee::math_helper::once_a_time_seconds< 1 > m_connections_maker_interval
Definition net_node.h:463
bool make_new_connection_from_anchor_peerlist(const std::vector< anchor_peerlist_entry > &anchor_peerlist)
Definition net_node.inl:1527
virtual epee::net_utils::zone send_txs(std::vector< cryptonote::blobdata > txs, const epee::net_utils::zone origin, const boost::uuids::uuid &source, cryptonote::relay_method tx_relay)
Definition net_node.inl:2342
bool make_expected_connections_count(network_zone &zone, PeerType peer_type, size_t expected_connections)
Definition net_node.inl:1971
bool init(const boost::program_options::variables_map &vm, const std::string &proxy={}, bool proxy_dns_leaks_allowed={})
Definition net_node.inl:901
bool idle_worker()
Definition net_node.inl:2110
epee::math_helper::once_a_time_seconds< P2P_DEFAULT_HANDSHAKE_INTERVAL > m_peer_handshake_idle_maker_interval
Definition net_node.h:462
int handle_timed_sync(int command, typename COMMAND_TIMED_SYNC::request &arg, typename COMMAND_TIMED_SYNC::response &rsp, p2p_connection_context &context)
Definition net_node.inl:2552
void get_public_peerlist(std::vector< peerlist_entry > &gray, std::vector< peerlist_entry > &white)
Definition net_node.inl:2093
std::set< std::string > get_seed_nodes(epee::net_utils::zone)
Definition net_node.inl:854
epee::math_helper::once_a_time_seconds< 60 > m_gray_peerlist_housekeeping_interval
Definition net_node.h:465
virtual bool invoke_notify_to_peer(int command, epee::levin::message_writer message, const epee::net_utils::connection_context_base &context) final
Definition net_node.inl:2404
bool connect_to_peerlist(const Container &peers)
Definition net_node.inl:2782
const std::vector< std::string > m_seed_nodes_list
Definition net_node.h:298
bool store_config()
Definition net_node.inl:1083
void get_peerlist(std::vector< peerlist_entry > &gray, std::vector< peerlist_entry > &white)
Definition net_node.inl:2101
bool get_local_node_data(basic_node_data &node_data, const network_zone &zone)
Definition net_node.inl:2288
bool check_incoming_connections()
Definition net_node.inl:2176
static void init_options(boost::program_options::options_description &desc)
Definition net_node.inl:101
void record_addr_failed(const epee::net_utils::network_address &addr)
Definition net_node.inl:1506
bool sanitize_peerlist(std::vector< peerlist_entry > &local_peerlist)
Definition net_node.inl:2223
uint16_t m_rpc_port
Definition net_node.h:446
uint32_t m_external_port
Definition net_node.h:445
std::atomic_flag m_fallback_seed_nodes_added
Definition net_node.h:471
virtual bool block_subnet(const epee::net_utils::ipv4_network_subnet &subnet, time_t seconds=P2P_IP_BLOCKTIME)
Definition net_node.inl:343
bool set_rate_limit(const boost::program_options::variables_map &vm, int64_t limit)
Definition net_node.inl:2927
bool gray_peerlist_housekeeping()
Definition net_node.inl:2980
size_t get_random_index_with_fixed_probability(size_t max_index)
Definition net_node.inl:1289
bool is_peer_used(const peerlist_entry &peer)
Definition net_node.inl:1302
bool connections_maker()
Definition net_node.inl:1897
epee::math_helper::once_a_time_seconds< 3600, false > m_incoming_connections_interval
Definition net_node.h:466
size_t get_incoming_connections_count()
Definition net_node.inl:2059
t_payload_net_handler payload_net_handler
Definition net_node.h:242
bool deinit()
Definition net_node.inl:1070
bool update_dns_blocklist()
Definition net_node.inl:2122
uint32_t max_connections
Definition net_node.h:510
virtual bool is_host_limit(const epee::net_utils::network_address &address)
Definition net_node.inl:228
int handle_get_support_flags(int command, COMMAND_REQUEST_SUPPORT_FLAGS::request &arg, COMMAND_REQUEST_SUPPORT_FLAGS::response &rsp, p2p_connection_context &context)
Definition net_node.inl:2303
virtual bool unblock_host(const epee::net_utils::network_address &address)
Definition net_node.inl:331
bool set_rate_down_limit(const boost::program_options::variables_map &vm, int64_t limit)
Definition net_node.inl:2915
int handle_handshake(int command, typename COMMAND_HANDSHAKE::request &arg, typename COMMAND_HANDSHAKE::response &rsp, p2p_connection_context &context)
Definition net_node.inl:2601
bool set_rate_up_limit(const boost::program_options::variables_map &vm, int64_t limit)
Definition net_node.inl:2901
virtual void add_used_stripe_peer(const typename t_payload_net_handler::connection_context &context)
Definition net_node.inl:3015
std::atomic< bool > m_stop_signal_sent_once
Definition net_node.h:454
std::map< std::string, uint64_t > m_host_fails_score
Definition net_node.h:497
bool is_priority_node(const epee::net_utils::network_address &na)
Definition net_node.inl:2776
boost::uuids::uuid m_network_id
Definition net_node.h:502
virtual bool for_connection(const boost::uuids::uuid &, std::function< bool(typename t_payload_net_handler::connection_context &, peerid_type, uint32_t)> f)
Definition net_node.inl:162
bool do_handshake_with_peer(peerid_type &pi, p2p_connection_context &context, bool just_take_peerlist=false)
Definition net_node.inl:1154
bool make_new_connection_from_peerlist(network_zone &zone, bool use_white_list)
Definition net_node.inl:1562
bool parse_peers_and_add_to_container(const boost::program_options::variables_map &vm, const command_line::arg_descriptor< std::vector< std::string > > &arg, Container &container)
Definition net_node.inl:2800
virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score=1)
Definition net_node.inl:406
cryptonote::network_type m_nettype
Definition net_node.h:503
p2p_connection_context_t< typename t_payload_net_handler::connection_context > p2p_connection_context
Definition net_node.h:137
t_payload_net_handler & m_payload_handler
Definition net_node.h:459
bool init_config()
Definition net_node.inl:134
bool m_hide_my_port
Definition net_node.h:449
bool m_enable_dns_blocklist
Definition net_node.h:508
epee::net_utils::ssl_support_t m_ssl_support
Definition net_node.h:505
std::map< std::string, time_t > m_conn_fails_cache
Definition net_node.h:489
bool send_stop_signal()
Definition net_node.inl:1108
bool log_connections()
Definition net_node.inl:2724
std::set< std::string > get_ip_seed_nodes() const
Definition net_node.inl:703
virtual void request_callback(const epee::net_utils::connection_context_base &context)
Definition net_node.inl:2310
uint32_t m_listening_port
Definition net_node.h:443
bool try_get_support_flags(const p2p_connection_context &context, std::function< void(p2p_connection_context &, const uint32_t &)> f)
Definition net_node.inl:2523
size_t get_public_outgoing_connections_count()
Definition net_node.inl:2007
uint32_t get_max_in_public_peers() const
Definition net_node.inl:2881
std::array< std::list< epee::net_utils::network_address >, 1<< CRYPTONOTE_PRUNING_LOG_STRIPES > m_used_stripe_peers
Definition net_node.h:500
size_t get_public_gray_peers_count()
Definition net_node.inl:2084
bool m_have_address
Definition net_node.h:441
std::set< std::string > get_dns_seed_nodes()
Definition net_node.inl:738
uint32_t m_listening_port_ipv6
Definition net_node.h:444
bool is_addr_connected(const epee::net_utils::network_address &peer)
Definition net_node.inl:1352
bool has_too_many_connections(const epee::net_utils::network_address &address)
Definition net_node.inl:2955
bool m_require_ipv4
Definition net_node.h:452
std::map< epee::net_utils::ipv4_network_subnet, time_t > m_blocked_subnets
Definition net_node.h:494
bool peer_sync_idle_maker()
Definition net_node.inl:2198
std::vector< epee::net_utils::network_address > m_exclusive_peers
Definition net_node.h:470
bool m_use_ipv6
Definition net_node.h:451
virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t=NULL)
Definition net_node.inl:176
void get_peerlist(std::vector< peerlist_entry > &pl_gray, std::vector< peerlist_entry > &pl_white)
Definition net_peerlist.cpp:275
size_t get_gray_peers_count()
Definition net_peerlist.h:104
size_t get_white_peers_count()
Definition net_peerlist.h:103
static boost::optional< peerlist_storage > open(std::istream &src, const bool new_format)
Definition net_peerlist.cpp:163
static DNSResolver & instance()
Gets the singleton instance of DNSResolver.
Definition dns_utils.cpp:401
std::vector< std::string > get_ipv4(const std::string &url, bool &dnssec_available, bool &dnssec_valid)
gets ipv4 addresses from DNS query of a URL
Definition dns_utils.cpp:362
#define CRYPTONOTE_NOISE_BYTES
Definition cryptonote_config.h:118
#define P2P_MAX_PEERS_IN_HANDSHAKE
Definition cryptonote_config.h:143
#define P2P_SUPPORT_FLAGS
Definition cryptonote_config.h:161
#define P2P_NET_DATA_FILENAME
Definition cryptonote_config.h:168
#define P2P_FAILED_ADDR_FORGET_SECONDS
Definition cryptonote_config.h:155
#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT
Definition cryptonote_config.h:148
#define P2P_DEFAULT_PEERS_IN_HANDSHAKE
Definition cryptonote_config.h:142
#define CRYPTONOTE_PRUNING_LOG_STRIPES
Definition cryptonote_config.h:207
#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT
Definition cryptonote_config.h:150
#define P2P_DEFAULT_INVOKE_TIMEOUT
Definition cryptonote_config.h:147
#define THREAD_STACK_SIZE
Definition cryptonote_config.h:172
#define P2P_DEFAULT_CONNECTIONS_COUNT
Definition cryptonote_config.h:139
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT
Definition cryptonote_config.h:149
#define DNS_BLOCKLIST_LIFETIME
Definition cryptonote_config.h:212
#define P2P_IP_FAILS_BEFORE_BLOCK
Definition cryptonote_config.h:157
#define CRYPTONOTE_DNS_TIMEOUT_MS
Definition cryptonote_config.h:38
#define MONERO_UNWRAP(...)
Definition expect.h:61
static const char * code
Definition generate_translations_header.c:25
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16
const char * res
Definition hmac_keccak.cpp:42
#define LEVIN_ERROR_CONNECTION_DESTROYED
Definition levin_base.h:105
#define LEVIN_ERROR_CONNECTION_TIMEDOUT
Definition levin_base.h:106
#define AUTO_VAL_INIT(v)
Definition misc_language.h:36
line
Definition check.py:23
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
Definition command_line.h:187
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
Definition command_line.h:263
std::enable_if<!std::is_same< T, bool >::value, bool >::type has_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
Definition command_line.h:256
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition command_line.h:269
boost::uuids::uuid const NETWORK_ID
Definition cryptonote_config.h:291
uint16_t const P2P_DEFAULT_PORT
Definition cryptonote_config.h:288
boost::uuids::uuid const NETWORK_ID
Definition cryptonote_config.h:276
uint16_t const P2P_DEFAULT_PORT
Definition cryptonote_config.h:273
boost::uuids::uuid const NETWORK_ID
Definition cryptonote_config.h:233
uint16_t const P2P_DEFAULT_PORT
Definition cryptonote_config.h:230
T rand()
Definition crypto.h:174
std::enable_if< std::is_integral< T >::value, T >::type rand_range(T range_min, T range_max)
Definition crypto.h:195
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition crypto.h:204
@ FAKECHAIN
Definition cryptonote_config.h:306
@ TESTNET
Definition cryptonote_config.h:304
@ MAINNET
Definition cryptonote_config.h:303
@ STAGENET
Definition cryptonote_config.h:305
const command_line::arg_descriptor< bool > arg_regtest_on
Definition cryptonote_core.cpp:85
const command_line::arg_descriptor< bool > arg_offline
Definition cryptonote_core.cpp:115
relay_method
Methods tracking how a tx was received and relayed.
Definition enums.h:37
const command_line::arg_descriptor< bool, false > arg_testnet_on
Definition cryptonote_core.cpp:75
const command_line::arg_descriptor< std::string, false, true, 3 > arg_data_dir
Definition cryptonote_core.cpp:100
const command_line::arg_descriptor< bool, false > arg_stagenet_on
Definition cryptonote_core.cpp:80
const config_t & get_config(network_type nettype)
Definition cryptonote_config.h:321
Level
Represents enumeration for severity level used to determine level of logging.
Definition easylogging++.h:591
@ Warning
Useful when application has potentially harmful situtaions.
Definition easylogging++.h:603
@ Info
Mainly useful to represent current progress of application.
Definition easylogging++.h:607
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
Definition file_io_utils.cpp:105
const char * get_err_descr(int err)
Definition levin_base.h:113
byte_slice make_noise_notify(std::size_t noise_bytes)
Definition levin_base.cpp:69
std::string get_time_interval_string(const time_t &time_)
Definition time_helper.h:58
Definition abstract_http_client.h:36
const char * zone_to_string(zone value) noexcept
Definition net_utils_base.cpp:135
@ ipv4
Definition enums.h:43
zone
Definition enums.h:50
@ public_
Definition enums.h:52
@ i2p
Definition enums.h:53
@ tor
Definition enums.h:54
std::string print_connection_context(const connection_context_base &ctx)
Definition net_utils_base.cpp:121
bool async_invoke_remote_command2(const epee::net_utils::connection_context_base &context, int command, const t_arg &out_struct, t_transport &transport, const callback_t &cb, size_t inv_timeout=LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
Definition levin_abstract_invoke2.h:87
ssl_support_t
Definition net_ssl.h:49
@ e_ssl_support_disabled
Definition net_ssl.h:50
std::string get_ip_string_from_int32(uint32_t ip)
Definition string_tools.cpp:68
std::string to_string_hex(const T &val)
Definition string_tools.h:118
std::string num_to_string_fast(int64_t val)
Definition string_tools.cpp:126
expect< epee::net_utils::network_address > get_network_address(const boost::string_ref address, const std::uint16_t default_port)
Definition parse.cpp:159
void get_network_address_host_and_port(const std::string &address, std::string &host, std::string &port)
Takes a valid address string (IP, Tor, I2P, or DNS name) and splits it into host and port.
Definition parse.cpp:131
@ unsupported_address
Type not supported by get_network_address.
Definition error.h:52
expect< epee::net_utils::ipv4_network_subnet > get_ipv4_subnet_address(const boost::string_ref address, bool allow_implicit_32)
Definition parse.cpp:203
Definition levin_notify.h:52
const command_line::arg_descriptor< std::vector< std::string > > arg_p2p_add_priority_node
Definition net_node.cpp:153
bool is_filtered_command(const epee::net_utils::network_address &address, int command)
Definition net_node.cpp:317
const command_line::arg_descriptor< int > arg_tos_flag
Definition net_node.cpp:170
const command_line::arg_descriptor< uint32_t > arg_p2p_external_port
Definition net_node.cpp:150
const int64_t default_limit_up
Definition net_node.h:513
const command_line::arg_descriptor< std::string > arg_ban_list
Definition net_node.cpp:159
static std::string peerid_to_string(peerid_type peer_id)
Definition p2p_protocol_defs.h:51
const command_line::arg_descriptor< bool > arg_enable_dns_blocklist
Definition net_node.cpp:162
const command_line::arg_descriptor< bool > arg_pad_transactions
Definition net_node.cpp:176
uint64_t peerid_type
Definition p2p_protocol_defs.h:49
const command_line::arg_descriptor< bool > arg_no_igd
Definition net_node.cpp:164
const command_line::arg_descriptor< std::vector< std::string > > arg_tx_proxy
Definition net_node.cpp:157
const command_line::arg_descriptor< int64_t > arg_limit_rate
Definition net_node.cpp:174
const command_line::arg_descriptor< std::string, false, true, 2 > arg_p2p_bind_port
Definition net_node.cpp:123
const command_line::arg_descriptor< bool > arg_no_sync
Definition net_node.cpp:161
const command_line::arg_descriptor< bool > arg_p2p_use_ipv6
Definition net_node.cpp:166
boost::optional< std::vector< anonymous_inbound > > get_anonymous_inbounds(boost::program_options::variables_map const &vm)
Definition net_node.cpp:250
std::string print_peerlist_to_string(const std::vector< peerlist_entry > &pl)
Definition p2p_protocol_defs.h:146
boost::optional< boost::asio::ip::tcp::socket > socks_connect_internal(const std::atomic< bool > &stop_signal, boost::asio::io_context &service, const net::socks::endpoint &proxy, const epee::net_utils::network_address &remote)
Definition net_node.cpp:337
bool append_net_address(std::vector< epee::net_utils::network_address > &seed_nodes, std::string const &addr, uint16_t default_port)
Definition net_node.inl:662
const command_line::arg_descriptor< bool > arg_p2p_allow_local_ip
Definition net_node.cpp:151
const command_line::arg_descriptor< int64_t > arg_limit_rate_down
Definition net_node.cpp:173
const command_line::arg_descriptor< std::string > arg_p2p_bind_ip
Definition net_node.cpp:121
const command_line::arg_descriptor< int64_t > arg_limit_rate_up
Definition net_node.cpp:172
boost::optional< std::vector< proxy > > get_proxies(boost::program_options::variables_map const &vm)
Definition net_node.cpp:181
anchor_peerlist_entry_base< epee::net_utils::network_address > anchor_peerlist_entry
Definition p2p_protocol_defs.h:120
const command_line::arg_descriptor< std::vector< std::string > > arg_anonymous_inbound
Definition net_node.cpp:158
const command_line::arg_descriptor< std::string > arg_p2p_bind_ipv6_address
Definition net_node.cpp:122
const command_line::arg_descriptor< int64_t > arg_out_peers
Definition net_node.cpp:168
const command_line::arg_descriptor< std::string, false, true, 2 > arg_p2p_bind_port_ipv6
Definition net_node.cpp:136
const command_line::arg_descriptor< uint32_t > arg_max_connections_per_ip
Definition net_node.cpp:179
const command_line::arg_descriptor< bool > arg_p2p_hide_my_port
Definition net_node.cpp:160
const command_line::arg_descriptor< bool > arg_p2p_ignore_ipv4
Definition net_node.cpp:167
const command_line::arg_descriptor< std::string > arg_igd
Definition net_node.cpp:165
const command_line::arg_descriptor< int64_t > arg_in_peers
Definition net_node.cpp:169
peerlist_entry_base< epee::net_utils::network_address > peerlist_entry
Definition p2p_protocol_defs.h:99
const command_line::arg_descriptor< std::vector< std::string > > arg_p2p_seed_node
Definition net_node.cpp:156
const command_line::arg_descriptor< std::vector< std::string > > arg_p2p_add_peer
Definition net_node.cpp:152
const int64_t default_limit_down
Definition net_node.h:514
const command_line::arg_descriptor< std::vector< std::string > > arg_p2p_add_exclusive_node
Definition net_node.cpp:154
bool load_txt_records_from_dns(std::vector< std::string > &good_records, const std::vector< std::string > &dns_urls)
Definition dns_utils.cpp:499
bool create_directories_if_necessary(const std::string &path)
creates directories for a path
Definition util.cpp:660
uint32_t get_pruning_stripe(uint64_t block_height, uint64_t blockchain_height, uint32_t log_stripes)
Definition pruning.cpp:55
uint32_t make_pruning_seed(uint32_t stripe, uint32_t log_stripes)
Definition pruning.cpp:38
#define LOG_PRINT_CC_PRIORITY_NODE(priority, con, msg)
Definition net_node.inl:1372
#define MIN_WANTED_SEED_NODES
Definition net_node.inl:69
static boost::asio::ip::address_v4 make_address_v4_from_v6(const boost::asio::ip::address_v6 &a)
Definition net_node.inl:71
#define LOG_DEBUG_CC(ct, message)
Definition net_utils_base.h:472
#define LOG_WARNING_CC(ct, message)
Definition net_utils_base.h:470
#define LOG_INFO_CC(ct, message)
Definition net_utils_base.h:471
#define LOG_TRACE_CC(ct, message)
Definition net_utils_base.h:473
#define PING_OK_RESPONSE_STATUS_TEXT
Definition p2p_protocol_defs.h:286
const CharType(& source)[N]
Definition pointer.h:1147
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
tools::wallet2::message_signature_result_t result
Definition signature.cpp:62
static cryptonote::account_public_address address
Definition signature.cpp:38
unsigned short uint16_t
Definition stdint.h:125
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
Definition command_line.h:53
Definition crypto.h:185
uint16_t const P2P_DEFAULT_PORT
Definition cryptonote_config.h:314
Definition net_utils_base.h:367
const network_address m_remote_address
Definition net_utils_base.h:369
Definition syncobj.h:53
static expect< endpoint > get(boost::string_ref uri)
Definition parse.cpp:270
epee::misc_utils::struct_init< request_t > request
Definition p2p_protocol_defs.h:225
epee::misc_utils::struct_init< response_t > response
Definition p2p_protocol_defs.h:239
static const int ID
Definition p2p_protocol_defs.h:284
epee::misc_utils::struct_init< request_t > request
Definition p2p_protocol_defs.h:295
epee::misc_utils::struct_init< response_t > response
Definition p2p_protocol_defs.h:307
epee::misc_utils::struct_init< response_t > response
Definition p2p_protocol_defs.h:333
static const int ID
Definition p2p_protocol_defs.h:316
epee::misc_utils::struct_init< request_t > request
Definition p2p_protocol_defs.h:323
epee::misc_utils::struct_init< response_t > response
Definition p2p_protocol_defs.h:270
epee::misc_utils::struct_init< request_t > request
Definition p2p_protocol_defs.h:258
int64_t first_seen
Definition p2p_protocol_defs.h:106
AddressType adr
Definition p2p_protocol_defs.h:104
peerid_type id
Definition p2p_protocol_defs.h:105
Definition p2p_protocol_defs.h:186
uint32_t support_flags
Definition p2p_protocol_defs.h:192
uint32_t my_port
Definition p2p_protocol_defs.h:188
peerid_type peer_id
Definition p2p_protocol_defs.h:191
uint16_t rpc_port
Definition p2p_protocol_defs.h:189
uint32_t rpc_credits_per_hash
Definition p2p_protocol_defs.h:190
uuid network_id
Definition p2p_protocol_defs.h:187
Definition net_node.h:163
net::socks::endpoint m_proxy_address
Definition net_node.h:219
cryptonote::levin::notify m_notifier
Definition net_node.h:215
net_server m_net_server
Definition net_node.h:209
std::string m_port_ipv6
Definition net_node.h:214
std::string m_bind_ip
Definition net_node.h:211
bool m_can_pingback
Definition net_node.h:223
boost::shared_mutex m_seed_nodes_lock
Definition net_node.h:222
std::vector< epee::net_utils::network_address > m_seed_nodes
Definition net_node.h:210
std::string m_port
Definition net_node.h:213
bool m_seed_nodes_initialized
Definition net_node.h:224
peerlist_manager m_peerlist
Definition net_node.h:217
config m_config
Definition net_node.h:218
connect_func * m_connect
Definition net_node.h:208
std::string m_bind_ipv6_address
Definition net_node.h:212
uint32_t support_flags
Definition net_node.h:121
bool is_ping
Definition net_node.h:123
peerid_type peer_id
Definition net_node.h:120
bool m_in_timedsync
Definition net_node.h:122
uint32_t pruning_seed
Definition p2p_protocol_defs.h:77
AddressType adr
Definition p2p_protocol_defs.h:74
uint16_t rpc_port
Definition p2p_protocol_defs.h:78
peerid_type id
Definition p2p_protocol_defs.h:75
int64_t last_seen
Definition p2p_protocol_defs.h:76
uint32_t rpc_credits_per_hash
Definition p2p_protocol_defs.h:79
Definition net_peerlist.h:56
Definition net_node.h:68
epee::net_utils::zone zone
Definition net_node.h:78
bool noise
Definition net_node.h:79
net::socks::endpoint address
Definition net_node.h:77
std::int64_t max_connections
Definition net_node.h:76
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:153
randomx_vm * vm
Definition tests.cpp:20