/ 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  }