File: MatchedDestination.cpp

package info (click to toggle)
i2pd 2.58.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,612 kB
  • sloc: cpp: 59,663; makefile: 224; sh: 138
file content (108 lines) | stat: -rw-r--r-- 3,075 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/

#include "MatchedDestination.h"
#include "Log.h"
#include "ClientContext.h"


namespace i2p
{
namespace client
{
	MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys, const std::string & remoteName, const std::map<std::string, std::string> * params)
		: RunnableClientDestination(keys, false, params),
			m_RemoteName(remoteName) {}


	void MatchedTunnelDestination::ResolveCurrentLeaseSet()
	{
		auto addr = i2p::client::context.GetAddressBook().GetAddress (m_RemoteName);
		if(addr && addr->IsIdentHash ())
		{
			m_RemoteIdent = addr->identHash;
			auto ls = FindLeaseSet(m_RemoteIdent);
			if(ls)
				HandleFoundCurrentLeaseSet(ls);
			else
				RequestDestination(m_RemoteIdent, std::bind(&MatchedTunnelDestination::HandleFoundCurrentLeaseSet, this, std::placeholders::_1));
		}
		else
			LogPrint(eLogWarning, "Destination: Failed to resolve ", m_RemoteName);
	}

	void MatchedTunnelDestination::HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls)
	{
		if(ls)
		{
			LogPrint(eLogDebug, "Destination: Resolved remote lease set for ", m_RemoteName);
			m_RemoteLeaseSet = ls;
		}
		else
		{
			m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1));
			m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) {
				if(!ec)	ResolveCurrentLeaseSet();
			});
		}
	}


	void MatchedTunnelDestination::Start()
	{
		ClientDestination::Start();
		m_ResolveTimer = std::make_shared<boost::asio::deadline_timer>(GetService());
		GetTunnelPool()->SetCustomPeerSelector(this);
		ResolveCurrentLeaseSet();
	}

	void MatchedTunnelDestination::Stop()
	{
		ClientDestination::Stop();
		if(m_ResolveTimer)
			m_ResolveTimer->cancel();
	}


	bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound)
	{
		auto pool = GetTunnelPool();
		if(!pool || !pool->StandardSelectPeers(path, hops, inbound,
			std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, 
				std::placeholders::_2, std::placeholders::_3)))
			return false;
		// more here for outbound tunnels
		if(!inbound && m_RemoteLeaseSet)
		{
			if(m_RemoteLeaseSet->IsExpired())
				ResolveCurrentLeaseSet();
			if(m_RemoteLeaseSet && !m_RemoteLeaseSet->IsExpired())
			{
				// remote lease set is good
				auto leases = m_RemoteLeaseSet->GetNonExpiredLeases();
				// pick lease
				std::shared_ptr<i2p::data::RouterInfo> obep;
				while(!obep && leases.size() > 0)
				{
					auto idx = rand() % leases.size();
					auto lease = leases[idx];
					obep = i2p::data::netdb.FindRouter(lease->tunnelGateway);
					leases.erase(leases.begin()+idx);
				}
				if(obep)
				{
					path.Add (obep);
					LogPrint(eLogDebug, "Destination: Found OBEP matching IBGW");
				} else
					LogPrint(eLogWarning, "Destination: Could not find proper IBGW for matched outbound tunnel");
			}
		}
		return true;
	}
}
}