/ libi2pd_client / MatchedDestination.cpp
MatchedDestination.cpp
1 /* 2 * Copyright (c) 2013-2025, 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 "MatchedDestination.h" 10 #include "Log.h" 11 #include "ClientContext.h" 12 13 14 namespace i2p 15 { 16 namespace client 17 { 18 MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys, 19 const std::string & remoteName, const i2p::util::Mapping * params) 20 : RunnableClientDestination(keys, false, params), 21 m_RemoteName(remoteName) {} 22 23 24 void MatchedTunnelDestination::ResolveCurrentLeaseSet() 25 { 26 auto addr = i2p::client::context.GetAddressBook().GetAddress (m_RemoteName); 27 if(addr && addr->IsIdentHash ()) 28 { 29 m_RemoteIdent = addr->identHash; 30 auto ls = FindLeaseSet(m_RemoteIdent); 31 if(ls) 32 HandleFoundCurrentLeaseSet(ls); 33 else 34 RequestDestination(m_RemoteIdent, std::bind(&MatchedTunnelDestination::HandleFoundCurrentLeaseSet, this, std::placeholders::_1)); 35 } 36 else 37 LogPrint(eLogWarning, "Destination: Failed to resolve ", m_RemoteName); 38 } 39 40 void MatchedTunnelDestination::HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls) 41 { 42 if(ls) 43 { 44 LogPrint(eLogDebug, "Destination: Resolved remote lease set for ", m_RemoteName); 45 m_RemoteLeaseSet = ls; 46 } 47 else 48 { 49 m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1)); 50 m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) { 51 if(!ec) ResolveCurrentLeaseSet(); 52 }); 53 } 54 } 55 56 57 void MatchedTunnelDestination::Start() 58 { 59 ClientDestination::Start(); 60 m_ResolveTimer = std::make_shared<boost::asio::deadline_timer>(GetService()); 61 GetTunnelPool()->SetCustomPeerSelector(this); 62 ResolveCurrentLeaseSet(); 63 } 64 65 void MatchedTunnelDestination::Stop() 66 { 67 ClientDestination::Stop(); 68 if(m_ResolveTimer) 69 m_ResolveTimer->cancel(); 70 } 71 72 73 bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound) 74 { 75 auto pool = GetTunnelPool(); 76 if(!pool || !pool->StandardSelectPeers(path, hops, inbound, 77 std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, 78 std::placeholders::_2, std::placeholders::_3))) 79 return false; 80 // more here for outbound tunnels 81 if(!inbound && m_RemoteLeaseSet) 82 { 83 if(m_RemoteLeaseSet->IsExpired()) 84 ResolveCurrentLeaseSet(); 85 if(m_RemoteLeaseSet && !m_RemoteLeaseSet->IsExpired()) 86 { 87 // remote lease set is good 88 auto leases = m_RemoteLeaseSet->GetNonExpiredLeases(); 89 // pick lease 90 std::shared_ptr<i2p::data::RouterInfo> obep; 91 while(!obep && leases.size() > 0) 92 { 93 auto idx = rand() % leases.size(); 94 auto lease = leases[idx]; 95 obep = i2p::data::netdb.FindRouter(lease->tunnelGateway); 96 leases.erase(leases.begin()+idx); 97 } 98 if(obep) 99 { 100 path.Add (obep); 101 LogPrint(eLogDebug, "Destination: Found OBEP matching IBGW"); 102 } else 103 LogPrint(eLogWarning, "Destination: Could not find proper IBGW for matched outbound tunnel"); 104 } 105 } 106 return true; 107 } 108 } 109 }