Transports.cpp
1 /* 2 * Copyright (c) 2013-2026, The PurpleI2P Project 3 * 4 * This file is part of Purple i2pd project and licensed under BSD3 5 * 6 * See full license text in LICENSE file at top of project tree 7 */ 8 9 #include <boost/algorithm/string.hpp> // for boost::to_lower 10 #include "Log.h" 11 #include "Crypto.h" 12 #include "RouterContext.h" 13 #include "I2NPProtocol.h" 14 #include "NetDb.hpp" 15 #include "Transports.h" 16 #include "Config.h" 17 #include "HTTP.h" 18 #include "util.h" 19 20 using namespace i2p::data; 21 22 namespace i2p 23 { 24 namespace transport 25 { 26 template<typename Keys> 27 EphemeralKeysSupplier<Keys>::EphemeralKeysSupplier (int size): 28 m_QueueSize (size), m_IsRunning (false) 29 { 30 } 31 32 template<typename Keys> 33 EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier () 34 { 35 Stop (); 36 } 37 38 template<typename Keys> 39 void EphemeralKeysSupplier<Keys>::Start () 40 { 41 m_IsRunning = true; 42 m_Thread.reset (new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this))); 43 } 44 45 template<typename Keys> 46 void EphemeralKeysSupplier<Keys>::Stop () 47 { 48 { 49 std::unique_lock<std::mutex> l(m_AcquiredMutex); 50 m_IsRunning = false; 51 m_Acquired.notify_one (); 52 } 53 if (m_Thread) 54 { 55 m_Thread->join (); 56 m_Thread = nullptr; 57 } 58 if (!m_Queue.empty ()) 59 { 60 // clean up queue 61 std::queue<std::shared_ptr<Keys> > tmp; 62 std::swap (m_Queue, tmp); 63 } 64 m_KeysPool.CleanUpMt (); 65 } 66 67 template<typename Keys> 68 void EphemeralKeysSupplier<Keys>::Run () 69 { 70 i2p::util::SetThreadName("Ephemerals"); 71 72 while (m_IsRunning) 73 { 74 int num, total = 0; 75 while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < m_QueueSize) 76 { 77 CreateEphemeralKeys (num); 78 total += num; 79 } 80 if (total > m_QueueSize) 81 { 82 LogPrint (eLogWarning, "Transports: ", total, " ephemeral keys generated at the time"); 83 std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break 84 } 85 else 86 { 87 m_KeysPool.CleanUpMt (); 88 std::unique_lock<std::mutex> l(m_AcquiredMutex); 89 if (!m_IsRunning) break; 90 m_Acquired.wait (l); // wait for element gets acquired 91 } 92 } 93 } 94 95 template<typename Keys> 96 void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num) 97 { 98 if (num > 0) 99 { 100 for (int i = 0; i < num; i++) 101 { 102 auto pair = m_KeysPool.AcquireSharedMt (); 103 pair->GenerateKeys (); 104 std::unique_lock<std::mutex> l(m_AcquiredMutex); 105 m_Queue.push (pair); 106 } 107 } 108 } 109 110 template<typename Keys> 111 std::shared_ptr<Keys> EphemeralKeysSupplier<Keys>::Acquire () 112 { 113 { 114 std::unique_lock<std::mutex> l(m_AcquiredMutex); 115 if (!m_Queue.empty ()) 116 { 117 auto pair = m_Queue.front (); 118 m_Queue.pop (); 119 m_Acquired.notify_one (); 120 return pair; 121 } 122 } 123 // queue is empty, create new 124 auto pair = m_KeysPool.AcquireSharedMt (); 125 pair->GenerateKeys (); 126 return pair; 127 } 128 129 template<typename Keys> 130 void EphemeralKeysSupplier<Keys>::Return (std::shared_ptr<Keys> pair) 131 { 132 if (pair) 133 { 134 std::unique_lock<std::mutex> l(m_AcquiredMutex); 135 if ((int)m_Queue.size () < 2*m_QueueSize) 136 m_Queue.push (pair); 137 } 138 else 139 LogPrint(eLogError, "Transports: Return null keys"); 140 } 141 142 void Peer::UpdateParams (std::shared_ptr<const i2p::data::RouterInfo> router) 143 { 144 if (router) 145 { 146 isHighBandwidth = router->IsHighBandwidth (); 147 isEligible =(bool)router->GetCompatibleTransports (true) && // reachable 148 router->GetCongestion () < i2p::data::RouterInfo::eHighCongestion && // accepts tunnel and not overloaded 149 router->IsECIES () && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION; // not too old 150 } 151 } 152 153 Transports transports; 154 155 Transports::Transports (): 156 m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_CheckReserved(true), m_Thread (nullptr), 157 m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), 158 m_UpdateBandwidthTimer (nullptr), m_SSU2Server (nullptr), m_NTCP2Server (nullptr), 159 m_X25519KeysPairSupplier (NUM_X25519_PRE_GENERATED_KEYS), 160 m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0), 161 m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0), 162 m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0), 163 m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0), 164 m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL) 165 { 166 } 167 168 Transports::~Transports () 169 { 170 Stop (); 171 if (m_Service) 172 { 173 delete m_PeerCleanupTimer; m_PeerCleanupTimer = nullptr; 174 delete m_PeerTestTimer; m_PeerTestTimer = nullptr; 175 delete m_UpdateBandwidthTimer; m_UpdateBandwidthTimer = nullptr; 176 delete m_Work; m_Work = nullptr; 177 delete m_Service; m_Service = nullptr; 178 } 179 } 180 181 void Transports::Start (bool enableNTCP2, bool enableSSU2) 182 { 183 if (!m_Service) 184 { 185 m_Service = new boost::asio::io_context (); 186 m_Work = new boost::asio::executor_work_guard<boost::asio::io_context::executor_type> (m_Service->get_executor ()); 187 m_PeerCleanupTimer = new boost::asio::deadline_timer (*m_Service); 188 m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service); 189 m_UpdateBandwidthTimer = new boost::asio::deadline_timer (*m_Service); 190 m_BanListCleanupTimer = std::make_unique<boost::asio::steady_timer>(*m_Service); 191 } 192 193 bool ipv4; i2p::config::GetOption("ipv4", ipv4); 194 bool ipv6; i2p::config::GetOption("ipv6", ipv6); 195 i2p::config::GetOption("nat", m_IsNAT); 196 m_X25519KeysPairSupplier.Start (); 197 m_IsRunning = true; 198 m_Thread = new std::thread (std::bind (&Transports::Run, this)); 199 std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); 200 int ntcp2version = 2; 201 #if OPENSSL_PQ 202 i2p::config::GetOption("ntcp2.version", ntcp2version); 203 #endif 204 i2p::http::URL proxyurl; 205 // create NTCP2. TODO: move to acceptor 206 if (enableNTCP2 || i2p::context.SupportsMesh ()) 207 { 208 if(!ntcp2proxy.empty() && enableNTCP2) 209 { 210 if(proxyurl.parse(ntcp2proxy)) 211 { 212 if(proxyurl.schema == "socks" || proxyurl.schema == "http") 213 { 214 m_NTCP2Server = new NTCP2Server (); 215 NTCP2Server::ProxyType proxytype = NTCP2Server::eSocksProxy; 216 217 if (proxyurl.schema == "http") 218 proxytype = NTCP2Server::eHTTPProxy; 219 220 m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port, proxyurl.user, proxyurl.pass); 221 i2p::context.SetStatus (eRouterStatusProxy); 222 if (ipv6) 223 i2p::context.SetStatusV6 (eRouterStatusProxy); 224 } 225 else 226 LogPrint(eLogCritical, "Transports: Unsupported NTCP2 proxy URL ", ntcp2proxy); 227 } 228 else 229 LogPrint(eLogCritical, "Transports: Invalid NTCP2 proxy URL ", ntcp2proxy); 230 } 231 else 232 m_NTCP2Server = new NTCP2Server (); 233 m_NTCP2Server->SetVersion (ntcp2version); 234 } 235 236 // create SSU2 server 237 if (enableSSU2) 238 { 239 m_SSU2Server = new SSU2Server (); 240 std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy); 241 if (!ssu2proxy.empty()) 242 { 243 if (proxyurl.parse (ssu2proxy) && proxyurl.schema == "socks") 244 { 245 if (m_SSU2Server->SetProxy (proxyurl.host, proxyurl.port)) 246 { 247 i2p::context.SetStatus (eRouterStatusProxy); 248 if (ipv6) 249 i2p::context.SetStatusV6 (eRouterStatusProxy); 250 } 251 else 252 LogPrint(eLogCritical, "Transports: Can't set SSU2 proxy ", ssu2proxy); 253 } 254 else 255 LogPrint(eLogCritical, "Transports: Invalid SSU2 proxy URL ", ssu2proxy); 256 } 257 } 258 259 // bind to interfaces 260 if (ipv4) 261 { 262 std::string address; i2p::config::GetOption("address4", address); 263 if (!address.empty ()) 264 { 265 boost::system::error_code ec; 266 auto addr = boost::asio::ip::make_address (address, ec); 267 if (!ec) 268 { 269 if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr); 270 if (m_SSU2Server) m_SSU2Server->SetLocalAddress (addr); 271 } 272 } 273 274 if (enableSSU2) 275 { 276 uint16_t mtu; i2p::config::GetOption ("ssu2.mtu4", mtu); 277 if (mtu) 278 { 279 if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; 280 if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; 281 i2p::context.SetMTU (mtu, true); 282 } 283 } 284 } 285 286 if (ipv6) 287 { 288 std::string address; i2p::config::GetOption("address6", address); 289 if (!address.empty ()) 290 { 291 boost::system::error_code ec; 292 auto addr = boost::asio::ip::make_address (address, ec); 293 if (!ec) 294 { 295 if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr); 296 if (m_SSU2Server) m_SSU2Server->SetLocalAddress (addr); 297 } 298 } 299 300 if (enableSSU2) 301 { 302 uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu); 303 if (mtu) 304 { 305 if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; 306 if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; 307 i2p::context.SetMTU (mtu, false); 308 } 309 } 310 } 311 312 bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); 313 if (ygg) 314 { 315 std::string address; i2p::config::GetOption("meshnets.yggaddress", address); 316 if (!address.empty ()) 317 { 318 boost::system::error_code ec; 319 auto addr = boost::asio::ip::make_address (address, ec); 320 if (!ec && m_NTCP2Server && i2p::util::net::IsYggdrasilAddress (addr)) 321 m_NTCP2Server->SetLocalAddress (addr); 322 } 323 } 324 325 // start servers 326 if (m_NTCP2Server) m_NTCP2Server->Start (); 327 if (m_SSU2Server) m_SSU2Server->Start (); 328 if (m_SSU2Server) DetectExternalIP (); 329 330 m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT)); 331 m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); 332 333 uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); 334 for (int i = 0; i < TRAFFIC_SAMPLE_COUNT; i++) 335 { 336 m_TrafficSamples[i].Timestamp = ts - (TRAFFIC_SAMPLE_COUNT - i - 1) * 1000; 337 m_TrafficSamples[i].TotalReceivedBytes = 0; 338 m_TrafficSamples[i].TotalSentBytes = 0; 339 m_TrafficSamples[i].TotalTransitTransmittedBytes = 0; 340 } 341 m_TrafficSamplePtr = TRAFFIC_SAMPLE_COUNT - 1; 342 343 m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); 344 m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); 345 346 if (m_IsNAT) 347 { 348 m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE)); 349 m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); 350 } 351 m_BanListCleanupTimer->expires_after (std::chrono::seconds(BAN_LIST_CLEANUP_INTERVAL + m_Rng () % BAN_LIST_CLEANUP_INTERVAL_VARIANCE)); 352 m_BanListCleanupTimer->async_wait (std::bind (&Transports::HandleBanListCleanupTimer, this, std::placeholders::_1)); 353 } 354 355 void Transports::Stop () 356 { 357 if (m_PeerCleanupTimer) m_PeerCleanupTimer->cancel (); 358 if (m_PeerTestTimer) m_PeerTestTimer->cancel (); 359 if (m_BanListCleanupTimer) m_BanListCleanupTimer->cancel (); 360 361 if (m_SSU2Server) 362 { 363 m_SSU2Server->Stop (); 364 delete m_SSU2Server; 365 m_SSU2Server = nullptr; 366 } 367 368 if (m_NTCP2Server) 369 { 370 m_NTCP2Server->Stop (); 371 delete m_NTCP2Server; 372 m_NTCP2Server = nullptr; 373 } 374 375 m_X25519KeysPairSupplier.Stop (); 376 m_IsRunning = false; 377 if (m_Service) m_Service->stop (); 378 if (m_Thread) 379 { 380 m_Thread->join (); 381 delete m_Thread; 382 m_Thread = nullptr; 383 } 384 m_Peers.clear (); 385 } 386 387 void Transports::Run () 388 { 389 i2p::util::SetThreadName("Transports"); 390 391 while (m_IsRunning && m_Service) 392 { 393 try 394 { 395 m_Service->run (); 396 } 397 catch (std::exception& ex) 398 { 399 LogPrint (eLogError, "Transports: Runtime exception: ", ex.what ()); 400 } 401 } 402 } 403 404 void Transports::UpdateBandwidthValues(int interval, uint32_t& in, uint32_t& out, uint32_t& transit) 405 { 406 TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr]; 407 TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT]; 408 auto delta = (int64_t)sample1.Timestamp - (int64_t)sample2.Timestamp; 409 if (delta <= 0) 410 { 411 LogPrint (eLogError, "Transports: Backward clock jump detected, got ", delta, " instead of ", interval * 1000); 412 return; 413 } 414 in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta; 415 out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta; 416 transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta; 417 } 418 419 void Transports::HandleUpdateBandwidthTimer (const boost::system::error_code& ecode) 420 { 421 if (ecode != boost::asio::error::operation_aborted) 422 { 423 m_TrafficSamplePtr++; 424 if (m_TrafficSamplePtr == TRAFFIC_SAMPLE_COUNT) 425 m_TrafficSamplePtr = 0; 426 427 TrafficSample& sample = m_TrafficSamples[m_TrafficSamplePtr]; 428 sample.Timestamp = i2p::util::GetMillisecondsSinceEpoch(); 429 sample.TotalReceivedBytes = m_TotalReceivedBytes; 430 sample.TotalSentBytes = m_TotalSentBytes; 431 sample.TotalTransitTransmittedBytes = m_TotalTransitTransmittedBytes; 432 433 UpdateBandwidthValues (1, m_InBandwidth, m_OutBandwidth, m_TransitBandwidth); 434 UpdateBandwidthValues (15, m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s); 435 UpdateBandwidthValues (300, m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m); 436 437 m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); 438 m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); 439 } 440 } 441 442 int Transports::GetCongestionLevel (bool longTerm) const 443 { 444 auto bwLimit = i2p::context.GetBandwidthLimit () * 1024; // convert to bytes 445 auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes 446 447 if (tbwLimit == 0 || bwLimit == 0) 448 return CONGESTION_LEVEL_FULL; 449 450 uint32_t bw; 451 uint32_t tbw; 452 if (longTerm) 453 { 454 bw = std::max (m_InBandwidth5m, m_OutBandwidth5m); 455 tbw = m_TransitBandwidth5m; 456 } 457 else 458 { 459 bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); 460 tbw = m_TransitBandwidth; 461 } 462 auto bwCongestionLevel = CONGESTION_LEVEL_FULL * bw / bwLimit; 463 auto tbwCongestionLevel = CONGESTION_LEVEL_FULL * tbw / tbwLimit; 464 return std::max (bwCongestionLevel, tbwCongestionLevel); 465 } 466 467 std::future<std::shared_ptr<TransportSession> > Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg) 468 { 469 if (m_IsOnline) 470 return SendMessages (ident, { msg }); 471 return {}; // invalid future 472 } 473 474 std::future<std::shared_ptr<TransportSession> > Transports::SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >&& msgs) 475 { 476 return boost::asio::post (*m_Service, boost::asio::use_future ([this, ident, msgs = std::move(msgs)] () mutable 477 { 478 return PostMessages (ident, msgs); 479 })); 480 } 481 482 std::shared_ptr<TransportSession> Transports::PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs) 483 { 484 if (ident == i2p::context.GetRouterInfo ().GetIdentHash ()) 485 { 486 // we send it to ourself 487 for (auto& it: msgs) 488 m_LoopbackHandler.PutNextMessage (std::move (it)); 489 m_LoopbackHandler.Flush (); 490 return nullptr; 491 } 492 if(RoutesRestricted() && !IsRestrictedPeer(ident)) return nullptr; 493 std::shared_ptr<Peer> peer; 494 { 495 std::lock_guard<std::mutex> l(m_PeersMutex); 496 auto it = m_Peers.find (ident); 497 if (it != m_Peers.end ()) 498 peer = it->second; 499 } 500 if (!peer) 501 { 502 // check if not banned 503 if (i2p::data::IsRouterBanned (ident)) return nullptr; // don't create peer to unreachable router 504 // try to connect 505 bool connected = false; 506 try 507 { 508 auto r = netdb.FindRouter (ident); 509 if (r && (r->IsUnreachable () || !r->IsReachableFrom (i2p::context.GetRouterInfo ()) || 510 (r->GetVersion () < i2p::data::NETDB_MIN_ALLOWED_VERSION && !r->IsHighBandwidth ()))) 511 return nullptr; // router found but non-reachable or too old 512 513 peer = std::make_shared<Peer>(r, i2p::util::GetSecondsSinceEpoch ()); 514 { 515 std::lock_guard<std::mutex> l(m_PeersMutex); 516 peer = m_Peers.emplace (ident, peer).first->second; 517 } 518 if (peer) 519 connected = ConnectToPeer (ident, peer); 520 } 521 catch (std::exception& ex) 522 { 523 LogPrint (eLogError, "Transports: PostMessages exception:", ex.what ()); 524 } 525 if (!connected) return nullptr; 526 } 527 528 if (!peer) return nullptr; 529 if (peer->IsConnected ()) 530 { 531 auto session = peer->sessions.front (); 532 if (session) session->SendI2NPMessages (msgs); 533 return session; 534 } 535 else 536 { 537 auto sz = peer->delayedMessages.size (); 538 if (sz < MAX_NUM_DELAYED_MESSAGES) 539 { 540 if (sz < CHECK_PROFILE_NUM_DELAYED_MESSAGES && sz + msgs.size () >= CHECK_PROFILE_NUM_DELAYED_MESSAGES) 541 { 542 if (i2p::data::IsRouterBanned (ident)) 543 { 544 LogPrint (eLogWarning, "Transports: Router ", ident.ToBase64 (), " is banned. Peer dropped"); 545 std::lock_guard<std::mutex> l(m_PeersMutex); 546 m_Peers.erase (ident); 547 return nullptr; 548 } 549 } 550 if (sz > MAX_NUM_DELAYED_MESSAGES/2) 551 { 552 for (auto& it1: msgs) 553 if (it1->onDrop) 554 it1->Drop (); // drop earlier because we can handle it 555 else 556 peer->delayedMessages.push_back (it1); 557 } 558 else 559 peer->delayedMessages.splice (peer->delayedMessages.end (), msgs); 560 } 561 else 562 { 563 LogPrint (eLogWarning, "Transports: Delayed messages queue size to ", 564 ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES); 565 std::lock_guard<std::mutex> l(m_PeersMutex); 566 m_Peers.erase (ident); 567 } 568 } 569 return nullptr; 570 } 571 572 bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer) 573 { 574 if (!peer->router) // reconnect 575 { 576 auto r = netdb.FindRouter (ident); // try to get new one from netdb 577 if (r) 578 { 579 peer->SetRouter (r); 580 r->CancelBufferToDelete (); 581 } 582 } 583 if (peer->router) // we have RI already 584 { 585 if (peer->priority.empty ()) 586 SetPriority (peer); 587 while (peer->numAttempts < (int)peer->priority.size ()) 588 { 589 auto tr = peer->priority[peer->numAttempts]; 590 peer->numAttempts++; 591 switch (tr) 592 { 593 case i2p::data::RouterInfo::eNTCP2V4: 594 case i2p::data::RouterInfo::eNTCP2V6: 595 { 596 if (!m_NTCP2Server) continue; 597 std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eNTCP2V6) ? 598 peer->router->GetPublishedNTCP2V6Address () : peer->router->GetPublishedNTCP2V4Address (); 599 if (address && IsInReservedRange(address->host)) 600 address = nullptr; 601 if (address) 602 { 603 auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer->router, address); 604 if( m_NTCP2Server->UsingProxy()) 605 m_NTCP2Server->ConnectWithProxy(s); 606 else 607 m_NTCP2Server->Connect (s); 608 return true; 609 } 610 break; 611 } 612 case i2p::data::RouterInfo::eSSU2V4: 613 case i2p::data::RouterInfo::eSSU2V6: 614 { 615 if (!m_SSU2Server) continue; 616 std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eSSU2V6) ? 617 peer->router->GetSSU2V6Address () : peer->router->GetSSU2V4Address (); 618 if (address && IsInReservedRange(address->host)) 619 address = nullptr; 620 if (address && address->IsReachableSSU ()) 621 { 622 if (m_SSU2Server->CreateSession (peer->router, address)) 623 return true; 624 } 625 break; 626 } 627 case i2p::data::RouterInfo::eNTCP2V6Mesh: 628 { 629 if (!m_NTCP2Server) continue; 630 auto address = peer->router->GetYggdrasilAddress (); 631 if (address) 632 { 633 auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer->router, address); 634 m_NTCP2Server->Connect (s); 635 return true; 636 } 637 break; 638 } 639 default: 640 LogPrint (eLogError, "Transports: Unknown transport ", (int)tr); 641 } 642 } 643 644 LogPrint (eLogInfo, "Transports: No compatible addresses available"); 645 if (!i2p::context.IsLimitedConnectivity () && peer->router->IsReachableFrom (i2p::context.GetRouterInfo ())) 646 i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed but router claimed them 647 peer->Done (); 648 std::lock_guard<std::mutex> l(m_PeersMutex); 649 m_Peers.erase (ident); 650 return false; 651 } 652 else if (i2p::data::IsRouterBanned (ident)) 653 { 654 LogPrint (eLogWarning, "Transports: Router ", ident.ToBase64 (), " is banned. Peer dropped"); 655 peer->Done (); 656 std::lock_guard<std::mutex> l(m_PeersMutex); 657 m_Peers.erase (ident); 658 return false; 659 } 660 else // otherwise request RI 661 { 662 LogPrint (eLogInfo, "Transports: RouterInfo for ", ident.ToBase64 (), " not found, requested"); 663 i2p::data::netdb.RequestDestination (ident, std::bind ( 664 &Transports::RequestComplete, this, std::placeholders::_1, ident)); 665 } 666 return true; 667 } 668 669 void Transports::SetPriority (std::shared_ptr<Peer> peer) 670 { 671 static constexpr std::array 672 ntcp2Priority = 673 { 674 i2p::data::RouterInfo::eNTCP2V6, 675 i2p::data::RouterInfo::eNTCP2V4, 676 i2p::data::RouterInfo::eSSU2V6, 677 i2p::data::RouterInfo::eSSU2V4, 678 i2p::data::RouterInfo::eNTCP2V6Mesh 679 }, 680 ssu2Priority = 681 { 682 i2p::data::RouterInfo::eSSU2V6, 683 i2p::data::RouterInfo::eSSU2V4, 684 i2p::data::RouterInfo::eNTCP2V6, 685 i2p::data::RouterInfo::eNTCP2V4, 686 i2p::data::RouterInfo::eNTCP2V6Mesh 687 }; 688 if (!peer || !peer->router) return; 689 auto compatibleTransports = context.GetRouterInfo ().GetCompatibleTransports (false) & 690 peer->router->GetCompatibleTransports (true); 691 auto directTransports = compatibleTransports & peer->router->GetPublishedTransports (); 692 peer->numAttempts = 0; 693 peer->priority.clear (); 694 695 std::shared_ptr<RouterProfile> profile; 696 if (peer->router->HasProfile ()) profile = peer->router->GetProfile (); // only if in memory 697 bool ssu2 = false; // NTCP2 by default 698 bool isReal = profile ? profile->IsReal () : true; 699 if (isReal) 700 { 701 ssu2 = m_Rng () & 1; // 1/2 702 if (ssu2 && !profile) 703 { 704 profile = peer->router->GetProfile (); // load profile if necessary 705 isReal = profile->IsReal (); 706 if (!isReal) ssu2 = false; // try NTCP2 if router is not confirmed real 707 } 708 } 709 const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority; 710 if (directTransports) 711 { 712 // direct connections have higher priority 713 if (!isReal && (directTransports & (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eNTCP2V6))) 714 { 715 // Non-confirmed router and a NTCP2 direct connection is presented 716 compatibleTransports &= ~directTransports; // exclude SSU2 direct connections 717 directTransports &= ~(i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6); 718 } 719 for (auto transport: priority) 720 if (transport & directTransports) 721 peer->priority.push_back (transport); 722 compatibleTransports &= ~directTransports; 723 } 724 if (compatibleTransports) 725 { 726 // then remaining 727 for (auto transport: priority) 728 if (transport & compatibleTransports) 729 peer->priority.push_back (transport); 730 } 731 if (peer->priority.empty ()) 732 { 733 // try recently connected SSU2 if any 734 auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) & 735 peer->router->GetCompatibleTransports (false); 736 if ((supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6)) && 737 peer->router->HasProfile ()) 738 { 739 auto ep = peer->router->GetProfile ()->GetLastEndpoint (); 740 if (!ep.address ().is_unspecified () && ep.port ()) 741 { 742 if (ep.address ().is_v4 ()) 743 { 744 if ((supportedTransports & i2p::data::RouterInfo::eSSU2V4) && 745 m_SSU2Server->IsConnectedRecently (ep, false)) 746 peer->priority.push_back (i2p::data::RouterInfo::eSSU2V4); 747 } 748 else if (ep.address ().is_v6 ()) 749 { 750 if ((supportedTransports & i2p::data::RouterInfo::eSSU2V6) && 751 m_SSU2Server->IsConnectedRecently (ep)) 752 peer->priority.push_back (i2p::data::RouterInfo::eSSU2V6); 753 } 754 } 755 } 756 } 757 } 758 759 void Transports::RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident) 760 { 761 boost::asio::post (*m_Service, std::bind (&Transports::HandleRequestComplete, this, r, ident)); 762 } 763 764 void Transports::HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident) 765 { 766 std::shared_ptr<Peer> peer; 767 { 768 std::lock_guard<std::mutex> l(m_PeersMutex); 769 auto it = m_Peers.find (ident); 770 if (it != m_Peers.end ()) 771 { 772 if (r) 773 peer = it->second; 774 else 775 m_Peers.erase (it); 776 } 777 } 778 779 if (peer && !peer->router && r) 780 { 781 LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect"); 782 peer->SetRouter (r); 783 if (!peer->IsConnected ()) 784 ConnectToPeer (ident, peer); 785 } 786 else if (!r) 787 LogPrint (eLogInfo, "Transports: RouterInfo not found, failed to send messages"); 788 789 } 790 791 void Transports::DetectExternalIP () 792 { 793 if (RoutesRestricted()) 794 { 795 LogPrint(eLogInfo, "Transports: Restricted routes enabled, not detecting IP"); 796 i2p::context.SetStatus (eRouterStatusOK); 797 return; 798 } 799 if (m_SSU2Server) 800 PeerTest (); 801 else 802 LogPrint (eLogWarning, "Transports: Can't detect external IP. SSU or SSU2 is not available"); 803 } 804 805 void Transports::PeerTest (bool ipv4, bool ipv6) 806 { 807 if (RoutesRestricted() || i2p::context.IsLimitedConnectivity () || 808 !m_SSU2Server || m_SSU2Server->UsesProxy ()) return; 809 if (ipv4 && i2p::context.SupportsV4 ()) 810 { 811 LogPrint (eLogInfo, "Transports: Started peer test IPv4"); 812 std::unordered_set<i2p::data::IdentHash> excluded; 813 excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router 814 int testDelay = 0; 815 for (int i = 0; i < 5; i++) 816 { 817 auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4 818 if (router) 819 { 820 if (!i2p::context.GetTesting ()) 821 { 822 i2p::context.SetTesting (true); 823 // send first peer test immediately 824 m_SSU2Server->StartPeerTest (router, true); 825 } 826 else 827 { 828 testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE; 829 if (m_Service) 830 { 831 auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service); 832 delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay)); 833 delayTimer->async_wait ( 834 [this, router, delayTimer](const boost::system::error_code& ecode) 835 { 836 if (ecode != boost::asio::error::operation_aborted) 837 m_SSU2Server->StartPeerTest (router, true); 838 }); 839 } 840 } 841 excluded.insert (router->GetIdentHash ()); 842 } 843 } 844 if (excluded.size () <= 1) 845 LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv4"); 846 } 847 if (ipv6 && i2p::context.SupportsV6 ()) 848 { 849 LogPrint (eLogInfo, "Transports: Started peer test IPv6"); 850 std::unordered_set<i2p::data::IdentHash> excluded; 851 excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router 852 int testDelay = 0; 853 for (int i = 0; i < 5; i++) 854 { 855 auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6 856 if (router) 857 { 858 if (!i2p::context.GetTestingV6 ()) 859 { 860 i2p::context.SetTestingV6 (true); 861 // send first peer test immediately 862 m_SSU2Server->StartPeerTest (router, false); 863 } 864 else 865 { 866 testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE; 867 if (m_Service) 868 { 869 auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service); 870 delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay)); 871 delayTimer->async_wait ( 872 [this, router, delayTimer](const boost::system::error_code& ecode) 873 { 874 if (ecode != boost::asio::error::operation_aborted) 875 m_SSU2Server->StartPeerTest (router, false); 876 }); 877 } 878 } 879 excluded.insert (router->GetIdentHash ()); 880 } 881 } 882 if (excluded.size () <= 1) 883 LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv6"); 884 } 885 } 886 887 std::shared_ptr<i2p::crypto::X25519Keys> Transports::GetNextX25519KeysPair () 888 { 889 return m_X25519KeysPairSupplier.Acquire (); 890 } 891 892 void Transports::ReuseX25519KeysPair (std::shared_ptr<i2p::crypto::X25519Keys> pair) 893 { 894 m_X25519KeysPairSupplier.Return (pair); 895 } 896 897 void Transports::PeerConnected (std::shared_ptr<TransportSession> session) 898 { 899 boost::asio::post (*m_Service, [session, this]() 900 { 901 auto remoteIdentity = session->GetRemoteIdentity (); 902 if (!remoteIdentity) return; 903 auto ident = remoteIdentity->GetIdentHash (); 904 auto it = m_Peers.find (ident); 905 if (it != m_Peers.end ()) 906 { 907 auto peer = it->second; 908 if (peer->numAttempts > 1) 909 { 910 // exclude failed transports 911 i2p::data::RouterInfo::CompatibleTransports transports = 0; 912 int numExcluded = peer->numAttempts - 1; 913 if (numExcluded > (int)peer->priority.size ()) numExcluded = peer->priority.size (); 914 for (int i = 0; i < numExcluded; i++) 915 transports |= peer->priority[i]; 916 i2p::data::netdb.ExcludeReachableTransports (ident, transports); 917 } 918 if (peer->router && peer->numAttempts) 919 { 920 auto transport = peer->priority[peer->numAttempts-1]; 921 if (transport == i2p::data::RouterInfo::eNTCP2V4 || 922 transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) 923 i2p::data::UpdateRouterProfile (ident, 924 [](std::shared_ptr<i2p::data::RouterProfile> profile) 925 { 926 if (profile) profile->Connected (); // outgoing NTCP2 connection if always real 927 }); 928 i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable 929 } 930 peer->numAttempts = 0; 931 peer->router = nullptr; // we don't need RouterInfo after successive connect 932 bool sendDatabaseStore = true; 933 if (it->second->delayedMessages.size () > 0) 934 { 935 // check if first message is our DatabaseStore (publishing) 936 auto firstMsg = peer->delayedMessages.front (); 937 if (firstMsg && firstMsg->GetTypeID () == eI2NPDatabaseStore && 938 i2p::data::IdentHash(firstMsg->GetPayload () + DATABASE_STORE_KEY_OFFSET) == i2p::context.GetIdentHash ()) 939 sendDatabaseStore = false; // we have it in the list already 940 } 941 if (sendDatabaseStore) 942 session->SendLocalRouterInfo (); 943 else 944 session->SetTerminationTimeout (10); // most likely it's publishing, no follow-up messages expected, set timeout to 10 seconds 945 peer->sessions.push_back (session); 946 session->SendI2NPMessages (peer->delayedMessages); // send and clear 947 } 948 else // incoming connection or peer test 949 { 950 if(RoutesRestricted() && ! IsRestrictedPeer(ident)) { 951 // not trusted 952 LogPrint(eLogWarning, "Transports: Closing untrusted inbound connection from ", ident.ToBase64()); 953 session->Done(); 954 return; 955 } 956 if (!session->IsOutgoing ()) // incoming 957 { 958 std::list<std::shared_ptr<I2NPMessage> > msgs{ CreateDatabaseStoreMsg () }; 959 session->SendI2NPMessages (msgs); // send DatabaseStore 960 } 961 auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed 962 i2p::data::UpdateRouterProfile (ident, 963 [](std::shared_ptr<i2p::data::RouterProfile> profile) 964 { 965 if (profile) profile->Connected (); 966 }); 967 auto ts = i2p::util::GetSecondsSinceEpoch (); 968 auto peer = std::make_shared<Peer>(r, ts); 969 peer->sessions.push_back (session); 970 peer->router = nullptr; 971 std::lock_guard<std::mutex> l(m_PeersMutex); 972 m_Peers.emplace (ident, peer); 973 } 974 }); 975 } 976 977 void Transports::PeerDisconnected (std::shared_ptr<TransportSession> session) 978 { 979 boost::asio::post (*m_Service, [session, this]() 980 { 981 auto remoteIdentity = session->GetRemoteIdentity (); 982 if (!remoteIdentity) return; 983 auto ident = remoteIdentity->GetIdentHash (); 984 auto it = m_Peers.find (ident); 985 if (it != m_Peers.end ()) 986 { 987 auto peer = it->second; 988 bool wasConnected = peer->IsConnected (); 989 peer->sessions.remove (session); 990 if (!peer->IsConnected ()) 991 { 992 if (peer->delayedMessages.size () > 0) 993 { 994 if (wasConnected) // we had an active session before 995 peer->numAttempts = 0; // start over 996 ConnectToPeer (ident, peer); 997 } 998 else 999 { 1000 { 1001 std::lock_guard<std::mutex> l(m_PeersMutex); 1002 m_Peers.erase (it); 1003 } 1004 // delete buffer of just disconnected router 1005 auto r = i2p::data::netdb.FindRouter (ident); 1006 if (r && !r->IsUpdated ()) r->ScheduleBufferToDelete (); 1007 } 1008 } 1009 } 1010 }); 1011 } 1012 1013 bool Transports::IsConnected (const i2p::data::IdentHash& ident) const 1014 { 1015 std::lock_guard<std::mutex> l(m_PeersMutex); 1016 #if __cplusplus >= 202002L // C++20 1017 return m_Peers.contains (ident); 1018 #else 1019 auto it = m_Peers.find (ident); 1020 return it != m_Peers.end (); 1021 #endif 1022 } 1023 1024 void Transports::UpdatePeerParams (std::shared_ptr<const i2p::data::RouterInfo> r) 1025 { 1026 if (!r) return; 1027 std::shared_ptr<Peer> peer; 1028 { 1029 std::lock_guard<std::mutex> l(m_PeersMutex); 1030 auto it = m_Peers.find (r->GetIdentHash ()); 1031 if (it != m_Peers.end ()) 1032 peer = it->second; 1033 } 1034 if (peer) 1035 peer->UpdateParams (r); 1036 } 1037 1038 void Transports::HandlePeerCleanupTimer (const boost::system::error_code& ecode) 1039 { 1040 if (ecode != boost::asio::error::operation_aborted) 1041 { 1042 auto ts = i2p::util::GetSecondsSinceEpoch (); 1043 for (auto it = m_Peers.begin (); it != m_Peers.end (); ) 1044 { 1045 it->second->sessions.remove_if ( 1046 [](std::shared_ptr<TransportSession> session)->bool 1047 { 1048 return !session || !session->IsEstablished (); 1049 }); 1050 if (!it->second->IsConnected () && ts > it->second->creationTime + SESSION_CREATION_TIMEOUT) 1051 { 1052 LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); 1053 /* if (!it->second.router) 1054 { 1055 // if router for ident not found mark it unreachable 1056 auto profile = i2p::data::GetRouterProfile (it->first); 1057 if (profile) profile->Unreachable (); 1058 } */ 1059 std::lock_guard<std::mutex> l(m_PeersMutex); 1060 it = m_Peers.erase (it); 1061 } 1062 else 1063 { 1064 if (ts > it->second->nextRouterInfoUpdateTime) 1065 { 1066 auto session = it->second->sessions.front (); 1067 if (session) 1068 session->SendLocalRouterInfo (true); 1069 it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL + 1070 m_Rng() % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE; 1071 } 1072 ++it; 1073 } 1074 } 1075 bool ipv4Testing = i2p::context.GetTesting (); 1076 if (!ipv4Testing) 1077 ipv4Testing = i2p::context.GetRouterInfo ().IsSSU2V4 () && (i2p::context.GetStatus() == eRouterStatusUnknown); 1078 bool ipv6Testing = i2p::context.GetTestingV6 (); 1079 if (!ipv6Testing) 1080 ipv6Testing = i2p::context.GetRouterInfo ().IsSSU2V6 () && (i2p::context.GetStatusV6() == eRouterStatusUnknown); 1081 // if still testing or unknown, repeat peer test 1082 if (ipv4Testing || ipv6Testing) 1083 PeerTest (ipv4Testing, ipv6Testing); 1084 m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(2 * SESSION_CREATION_TIMEOUT + m_Rng() % SESSION_CREATION_TIMEOUT)); 1085 m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); 1086 } 1087 } 1088 1089 void Transports::HandlePeerTestTimer (const boost::system::error_code& ecode) 1090 { 1091 if (ecode != boost::asio::error::operation_aborted) 1092 { 1093 PeerTest (); 1094 m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE)); 1095 m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); 1096 } 1097 } 1098 1099 void Transports::HandleBanListCleanupTimer (const boost::system::error_code& ecode) 1100 { 1101 if (ecode != boost::asio::error::operation_aborted) 1102 { 1103 if (!m_BanList.empty ()) 1104 { 1105 auto ts = i2p::util::GetMonotonicSeconds (); 1106 { 1107 std::lock_guard<std::mutex> l(m_BanListMutex); 1108 for (auto it = m_BanList.begin (); it != m_BanList.end (); ) 1109 { 1110 if (ts < it->second) 1111 it++; 1112 else 1113 it = m_BanList.erase (it); 1114 } 1115 } 1116 } 1117 m_BanListCleanupTimer->expires_after (std::chrono::seconds(BAN_LIST_CLEANUP_INTERVAL + m_Rng () % BAN_LIST_CLEANUP_INTERVAL_VARIANCE)); 1118 m_BanListCleanupTimer->async_wait (std::bind (&Transports::HandleBanListCleanupTimer, this, std::placeholders::_1)); 1119 } 1120 } 1121 1122 template<typename Filter> 1123 std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer (Filter filter) const 1124 { 1125 if (m_Peers.empty()) return nullptr; 1126 auto ts = i2p::util::GetSecondsSinceEpoch (); 1127 bool found = false; 1128 i2p::data::IdentHash ident; 1129 { 1130 uint16_t inds[3]; 1131 RAND_bytes ((uint8_t *)inds, sizeof (inds)); 1132 std::lock_guard<std::mutex> l(m_PeersMutex); 1133 auto count = m_Peers.size (); 1134 if(count == 0) return nullptr; 1135 inds[0] %= count; 1136 auto it = m_Peers.begin (); 1137 std::advance (it, inds[0]); 1138 // try random peer 1139 if (it != m_Peers.end () && filter (it->second)) 1140 { 1141 ident = it->first; 1142 found = true; 1143 } 1144 else 1145 { 1146 // try some peers around 1147 auto it1 = m_Peers.begin (); 1148 if (inds[0]) 1149 { 1150 // before 1151 inds[1] %= inds[0]; 1152 std::advance (it1, (inds[1] + inds[0])/2); 1153 } 1154 else 1155 it1 = it; 1156 auto it2 = it; 1157 if (inds[0] < m_Peers.size () - 1) 1158 { 1159 // after 1160 inds[2] %= (m_Peers.size () - 1 - inds[0]); inds[2] /= 2; 1161 std::advance (it2, inds[2]); 1162 } 1163 // it1 - from, it2 - to 1164 it = it1; 1165 while (it != it2 && it != m_Peers.end ()) 1166 { 1167 if (ts > it->second->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL && 1168 filter (it->second)) 1169 { 1170 ident = it->first; 1171 it->second->lastSelectionTime = ts; 1172 found = true; 1173 break; 1174 } 1175 it++; 1176 } 1177 if (!found) 1178 { 1179 // still not found, try from the beginning 1180 it = m_Peers.begin (); 1181 while (it != it1 && it != m_Peers.end ()) 1182 { 1183 if (ts > it->second->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL && 1184 filter (it->second)) 1185 { 1186 ident = it->first; 1187 it->second->lastSelectionTime = ts; 1188 found = true; 1189 break; 1190 } 1191 it++; 1192 } 1193 if (!found) 1194 { 1195 // still not found, try to the beginning 1196 it = it2; 1197 while (it != m_Peers.end ()) 1198 { 1199 if (ts > it->second->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL && 1200 filter (it->second)) 1201 { 1202 ident = it->first; 1203 it->second->lastSelectionTime = ts; 1204 found = true; 1205 break; 1206 } 1207 it++; 1208 } 1209 } 1210 } 1211 } 1212 } 1213 return found ? i2p::data::netdb.FindRouter (ident) : nullptr; 1214 } 1215 1216 std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer (bool isHighBandwidth) const 1217 { 1218 return GetRandomPeer ( 1219 [isHighBandwidth](std::shared_ptr<const Peer> peer)->bool 1220 { 1221 // connected, not overloaded and not slow 1222 return !peer->router && peer->IsConnected () && peer->isEligible && 1223 peer->sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && 1224 !peer->sessions.front ()->IsSlow () && !peer->sessions.front ()->IsBandwidthExceeded (peer->isHighBandwidth) && 1225 (!isHighBandwidth || peer->isHighBandwidth); 1226 }); 1227 } 1228 1229 void Transports::RestrictRoutesToFamilies(const std::vector<std::string_view>& families) 1230 { 1231 std::lock_guard<std::mutex> lock(m_FamilyMutex); 1232 m_TrustedFamilies.clear(); 1233 for (auto f: families) 1234 { 1235 std::string fam(f); boost::to_lower (fam); 1236 auto id = i2p::data::netdb.GetFamilies ().GetFamilyID (fam); 1237 if (id) 1238 m_TrustedFamilies.push_back (id); 1239 } 1240 } 1241 1242 void Transports::RestrictRoutesToRouters(const std::vector<i2p::data::IdentHash>& routers) 1243 { 1244 std::lock_guard<std::mutex> lock(m_TrustedRoutersMutex); 1245 m_TrustedRouters.clear(); 1246 for (const auto & ri : routers ) 1247 m_TrustedRouters.insert(ri); 1248 } 1249 1250 bool Transports::RoutesRestricted() const 1251 { 1252 { 1253 std::lock_guard<std::mutex> routerslock(m_TrustedRoutersMutex); 1254 if (!m_TrustedRouters.empty ()) return true; 1255 } 1256 { 1257 std::lock_guard<std::mutex> famlock(m_FamilyMutex); 1258 if (!m_TrustedFamilies.empty ()) return true; 1259 } 1260 return false; 1261 } 1262 1263 /** XXX: if routes are not restricted this dies */ 1264 std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer() 1265 { 1266 { 1267 std::lock_guard<std::mutex> l(m_FamilyMutex); 1268 i2p::data::FamilyID fam = 0; 1269 auto sz = m_TrustedFamilies.size(); 1270 if(sz > 1) 1271 { 1272 auto it = m_TrustedFamilies.begin (); 1273 std::advance(it, m_Rng() % sz); 1274 fam = *it; 1275 } 1276 else if (sz == 1) 1277 { 1278 fam = m_TrustedFamilies[0]; 1279 } 1280 if (fam) 1281 return i2p::data::netdb.GetRandomRouterInFamily(fam); 1282 } 1283 { 1284 std::lock_guard<std::mutex> l(m_TrustedRoutersMutex); 1285 auto sz = m_TrustedRouters.size(); 1286 if (sz) 1287 { 1288 auto it = m_TrustedRouters.begin(); 1289 if(sz > 1) 1290 std::advance(it, m_Rng() % sz); 1291 return i2p::data::netdb.FindRouter(*it); 1292 } 1293 } 1294 return nullptr; 1295 } 1296 1297 bool Transports::IsTrustedRouter (const i2p::data::IdentHash& ih) const 1298 { 1299 if (m_TrustedRouters.empty ()) return false; 1300 std::lock_guard<std::mutex> l(m_TrustedRoutersMutex); 1301 #if __cplusplus >= 202002L // C++20 1302 if (m_TrustedRouters.contains (ih)) 1303 #else 1304 if (m_TrustedRouters.count (ih) > 0) 1305 #endif 1306 return true; 1307 return false; 1308 } 1309 1310 bool Transports::IsRestrictedPeer(const i2p::data::IdentHash& ih) const 1311 { 1312 if (IsTrustedRouter (ih)) return true; 1313 1314 { 1315 std::lock_guard<std::mutex> l(m_FamilyMutex); 1316 auto ri = i2p::data::netdb.FindRouter(ih); 1317 for (const auto & fam : m_TrustedFamilies) 1318 if(ri->IsFamily(fam)) return true; 1319 } 1320 return false; 1321 } 1322 1323 void Transports::SetOnline (bool online) 1324 { 1325 if (m_IsOnline != online) 1326 { 1327 m_IsOnline = online; 1328 if (online) 1329 PeerTest (); 1330 else 1331 i2p::context.SetError (eRouterErrorOffline); 1332 } 1333 } 1334 1335 int Transports::GetLocalDelay () const 1336 { 1337 return (i2p::context.GetStatus () == eRouterStatusProxy) ? 1000 : 0; // 1 sec for proxy. TODO: implement param 1338 } 1339 1340 bool Transports::IsInReservedRange (const boost::asio::ip::address& host) const 1341 { 1342 return IsCheckReserved () && i2p::util::net::IsInReservedRange (host); 1343 } 1344 1345 bool Transports::IsBanned (const boost::asio::ip::address& addr) 1346 { 1347 std::lock_guard<std::mutex> l(m_BanListMutex); 1348 auto it = m_BanList.find (addr); 1349 if (it != m_BanList.end ()) 1350 { 1351 if (it->second > i2p::util::GetMonotonicSeconds ()) 1352 return true; 1353 else 1354 m_BanList.erase (it); 1355 } 1356 return false; 1357 } 1358 1359 bool Transports::AddBan (const boost::asio::ip::address& addr) 1360 { 1361 auto ts = i2p::util::GetMonotonicSeconds () + IP_BAN_TIME + m_Rng () % IP_BAN_TIME_VARIANCE; 1362 std::lock_guard<std::mutex> l(m_BanListMutex); 1363 return m_BanList.emplace (addr, ts).second; 1364 } 1365 1366 void InitAddressFromIface () 1367 { 1368 bool ipv6; i2p::config::GetOption("ipv6", ipv6); 1369 bool ipv4; i2p::config::GetOption("ipv4", ipv4); 1370 1371 // ifname -> address 1372 std::string ifname; i2p::config::GetOption("ifname", ifname); 1373 if (ipv4 && i2p::config::IsDefault ("address4")) 1374 { 1375 std::string ifname4; i2p::config::GetOption("ifname4", ifname4); 1376 if (!ifname4.empty ()) 1377 i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4 1378 else if (!ifname.empty ()) 1379 i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4 1380 } 1381 if (ipv6 && i2p::config::IsDefault ("address6")) 1382 { 1383 std::string ifname6; i2p::config::GetOption("ifname6", ifname6); 1384 if (!ifname6.empty ()) 1385 i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6 1386 else if (!ifname.empty ()) 1387 i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6 1388 } 1389 } 1390 1391 void InitTransports () 1392 { 1393 bool ipv6; i2p::config::GetOption("ipv6", ipv6); 1394 bool ipv4; i2p::config::GetOption("ipv4", ipv4); 1395 bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); 1396 uint16_t port; i2p::config::GetOption("port", port); 1397 bool stan; i2p::config::GetOption("stan", stan); 1398 1399 boost::asio::ip::address_v6 yggaddr; 1400 if (ygg) 1401 { 1402 std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress); 1403 if (!yggaddress.empty ()) 1404 { 1405 yggaddr = boost::asio::ip::make_address (yggaddress).to_v6 (); 1406 if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) || 1407 !i2p::util::net::IsLocalAddress (yggaddr)) 1408 { 1409 LogPrint(eLogWarning, "Transports: Can't find Yggdrasil address ", yggaddress); 1410 ygg = false; 1411 } 1412 } 1413 else 1414 { 1415 yggaddr = i2p::util::net::GetYggdrasilAddress (); 1416 if (yggaddr.is_unspecified ()) 1417 { 1418 LogPrint(eLogWarning, "Transports: Yggdrasil is not running. Disabled"); 1419 ygg = false; 1420 } 1421 } 1422 } 1423 1424 if (ipv6 && i2p::util::net::GetClearnetIPV6Address ().is_unspecified ()) 1425 { 1426 std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); 1427 std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy); 1428 if (ntcp2proxy.empty () && ssu2proxy.empty ()) 1429 { 1430 LogPrint(eLogWarning, "Transports: Clearnet ipv6 not found. Disabled"); 1431 ipv6 = false; 1432 } 1433 } 1434 1435 if (!i2p::config::IsDefault("port")) 1436 { 1437 LogPrint(eLogInfo, "Transports: Accepting incoming connections at port ", port); 1438 i2p::context.UpdatePort (port); 1439 } 1440 i2p::context.SetSupportsV6 (ipv6); 1441 i2p::context.SetSupportsV4 (ipv4); 1442 i2p::context.SetSupportsMesh (ygg, yggaddr); 1443 1444 bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); 1445 if (ntcp2) 1446 { 1447 bool published = false; 1448 if (!stan) i2p::config::GetOption("ntcp2.published", published); 1449 if (published) 1450 { 1451 std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); 1452 if (!ntcp2proxy.empty ()) published = false; 1453 } 1454 int ntcp2version = 2; 1455 #if OPENSSL_PQ 1456 i2p::config::GetOption("ntcp2.version", ntcp2version); 1457 #endif 1458 if (published) 1459 { 1460 uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port); 1461 if (!ntcp2port) ntcp2port = port; // use standard port 1462 i2p::context.PublishNTCP2Address (ntcp2port, true, ipv4, ipv6, false, ntcp2version); // publish 1463 if (ipv6) 1464 { 1465 std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr); 1466 auto addr = boost::asio::ip::make_address (ipv6Addr).to_v6 (); 1467 if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ()) 1468 i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured 1469 } 1470 } 1471 else 1472 i2p::context.PublishNTCP2Address (port, false, ipv4, ipv6, false, ntcp2version); // unpublish 1473 } 1474 if (ygg) 1475 { 1476 i2p::context.PublishNTCP2Address (port, true, false, false, true, 2); 1477 i2p::context.UpdateNTCP2V6Address (yggaddr); 1478 if (!ipv4 && !ipv6) 1479 i2p::context.SetStatus (eRouterStatusMesh); 1480 } 1481 bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); 1482 if (ssu2 && i2p::config::IsDefault ("ssu2.enabled") && !ipv4 && !ipv6) 1483 ssu2 = false; // don't enable ssu2 for yggdrasil only router 1484 if (ssu2) 1485 { 1486 uint16_t ssu2port; i2p::config::GetOption("ssu2.port", ssu2port); 1487 if (!ssu2port && port) ssu2port = port; 1488 bool published = false; 1489 if (!stan) i2p::config::GetOption("ssu2.published", published); 1490 if (published) 1491 i2p::context.PublishSSU2Address (ssu2port, true, ipv4, ipv6); // publish 1492 else 1493 i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish 1494 } 1495 if (stan) 1496 i2p::context.SetStatus (eRouterStatusStan); 1497 } 1498 } 1499 }