mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 00:20:46 +00:00 
			
		
		
		
	add option for client tunnels to build tunnels such that OBEP==IBGW
This commit is contained in:
		
							parent
							
								
									987688f196
								
							
						
					
					
						commit
						9b62f238ed
					
				
					 12 changed files with 502 additions and 333 deletions
				
			
		| 
						 | 
				
			
			@ -10,20 +10,21 @@
 | 
			
		|||
#include "ClientContext.h"
 | 
			
		||||
#include "SOCKS.h"
 | 
			
		||||
#include "WebSocks.h"
 | 
			
		||||
#include "MatchedDestination.h"
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
namespace client
 | 
			
		||||
{
 | 
			
		||||
	ClientContext context;	
 | 
			
		||||
	ClientContext context;
 | 
			
		||||
 | 
			
		||||
	ClientContext::ClientContext (): m_SharedLocalDestination (nullptr),
 | 
			
		||||
		m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), 
 | 
			
		||||
		m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr),
 | 
			
		||||
		m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	ClientContext::~ClientContext () 
 | 
			
		||||
 | 
			
		||||
	ClientContext::~ClientContext ()
 | 
			
		||||
	{
 | 
			
		||||
		delete m_HttpProxy;
 | 
			
		||||
		delete m_SocksProxy;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,20 +32,20 @@ namespace client
 | 
			
		|||
		delete m_BOBCommandChannel;
 | 
			
		||||
		delete m_I2CPServer;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	void ClientContext::Start ()
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_SharedLocalDestination)
 | 
			
		||||
		{	
 | 
			
		||||
		{
 | 
			
		||||
			m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA
 | 
			
		||||
			m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination;
 | 
			
		||||
			m_SharedLocalDestination->Start ();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
		m_AddressBook.Start ();	
 | 
			
		||||
    
 | 
			
		||||
		std::shared_ptr<ClientDestination> localDestination;	
 | 
			
		||||
 | 
			
		||||
		m_AddressBook.Start ();
 | 
			
		||||
 | 
			
		||||
		std::shared_ptr<ClientDestination> localDestination;
 | 
			
		||||
		bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy);
 | 
			
		||||
		if (httproxy) {
 | 
			
		||||
			std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys",    httpProxyKeys);
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +61,7 @@ namespace client
 | 
			
		|||
					std::map<std::string, std::string> params;
 | 
			
		||||
					ReadI2CPOptionsFromConfig ("httpproxy.", params);
 | 
			
		||||
					localDestination = CreateNewLocalDestination (keys, false, ¶ms);
 | 
			
		||||
				}	
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					LogPrint(eLogError, "Clients: failed to load HTTP Proxy key");
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -71,10 +72,10 @@ namespace client
 | 
			
		|||
			  LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
		localDestination = nullptr;
 | 
			
		||||
		bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy);
 | 
			
		||||
		if (socksproxy) 
 | 
			
		||||
		if (socksproxy)
 | 
			
		||||
		{
 | 
			
		||||
			std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys",    socksProxyKeys);
 | 
			
		||||
			std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr);
 | 
			
		||||
| 
						 | 
				
			
			@ -104,8 +105,8 @@ namespace client
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		// I2P tunnels
 | 
			
		||||
		ReadTunnels ();		
 | 
			
		||||
    
 | 
			
		||||
		ReadTunnels ();
 | 
			
		||||
 | 
			
		||||
		// SAM
 | 
			
		||||
		bool sam; i2p::config::GetOption("sam.enabled", sam);
 | 
			
		||||
		if (sam) {
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +119,7 @@ namespace client
 | 
			
		|||
			} catch (std::exception& e) {
 | 
			
		||||
			  LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what());
 | 
			
		||||
			}
 | 
			
		||||
		} 
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// BOB
 | 
			
		||||
		bool bob; i2p::config::GetOption("bob.enabled", bob);
 | 
			
		||||
| 
						 | 
				
			
			@ -132,27 +133,27 @@ namespace client
 | 
			
		|||
			} catch (std::exception& e) {
 | 
			
		||||
			  LogPrint(eLogError, "Clients: Exception in BOB bridge: ", e.what());
 | 
			
		||||
			}
 | 
			
		||||
		} 
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// I2CP
 | 
			
		||||
		bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp);
 | 
			
		||||
		if (i2cp) 
 | 
			
		||||
		if (i2cp)
 | 
			
		||||
		{
 | 
			
		||||
			std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
 | 
			
		||||
			uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
 | 
			
		||||
			try 
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
 | 
			
		||||
			  	m_I2CPServer->Start ();
 | 
			
		||||
			} 
 | 
			
		||||
			catch (std::exception& e) 
 | 
			
		||||
			}
 | 
			
		||||
			catch (std::exception& e)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what());
 | 
			
		||||
			}
 | 
			
		||||
		} 
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_AddressBook.StartResolvers ();	
 | 
			
		||||
		m_AddressBook.StartResolvers ();
 | 
			
		||||
 | 
			
		||||
		// start UDP cleanup
 | 
			
		||||
		if (!m_ServerForwards.empty ())
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +162,7 @@ namespace client
 | 
			
		|||
			ScheduleCleanupUDP();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	void ClientContext::Stop ()
 | 
			
		||||
	{
 | 
			
		||||
		if (m_HttpProxy)
 | 
			
		||||
| 
						 | 
				
			
			@ -185,28 +186,28 @@ namespace client
 | 
			
		|||
			LogPrint(eLogInfo, "Clients: stopping I2P client tunnel on port ", it.first);
 | 
			
		||||
			it.second->Stop ();
 | 
			
		||||
		}
 | 
			
		||||
		m_ClientTunnels.clear ();	
 | 
			
		||||
		m_ClientTunnels.clear ();
 | 
			
		||||
 | 
			
		||||
		for (auto& it: m_ServerTunnels)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: stopping I2P server tunnel");
 | 
			
		||||
			it.second->Stop ();
 | 
			
		||||
		}
 | 
			
		||||
		m_ServerTunnels.clear ();	
 | 
			
		||||
		m_ServerTunnels.clear ();
 | 
			
		||||
 | 
			
		||||
		if (m_SamBridge)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: stopping SAM bridge");
 | 
			
		||||
			m_SamBridge->Stop ();
 | 
			
		||||
			delete m_SamBridge; 
 | 
			
		||||
			delete m_SamBridge;
 | 
			
		||||
			m_SamBridge = nullptr;
 | 
			
		||||
		}		
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_BOBCommandChannel)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: stopping BOB command channel");
 | 
			
		||||
			m_BOBCommandChannel->Stop ();
 | 
			
		||||
			delete m_BOBCommandChannel; 
 | 
			
		||||
			delete m_BOBCommandChannel;
 | 
			
		||||
			m_BOBCommandChannel = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +215,7 @@ namespace client
 | 
			
		|||
		{
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: stopping I2CP");
 | 
			
		||||
			m_I2CPServer->Stop ();
 | 
			
		||||
			delete m_I2CPServer; 
 | 
			
		||||
			delete m_I2CPServer;
 | 
			
		||||
			m_I2CPServer = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -226,18 +227,18 @@ namespace client
 | 
			
		|||
			m_ServerForwards.clear();
 | 
			
		||||
			m_ClientForwards.clear();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		if (m_CleanupUDPTimer)
 | 
			
		||||
		{
 | 
			
		||||
			m_CleanupUDPTimer->cancel ();	
 | 
			
		||||
			m_CleanupUDPTimer = nullptr;	
 | 
			
		||||
			m_CleanupUDPTimer->cancel ();
 | 
			
		||||
			m_CleanupUDPTimer = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto& it: m_Destinations)
 | 
			
		||||
			it.second->Stop ();
 | 
			
		||||
		m_Destinations.clear ();
 | 
			
		||||
		m_SharedLocalDestination = nullptr;
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ClientContext::ReloadConfig ()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -246,14 +247,14 @@ namespace client
 | 
			
		|||
		Stop();
 | 
			
		||||
		Start();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType)
 | 
			
		||||
	{
 | 
			
		||||
		bool success = true;
 | 
			
		||||
		std::string fullPath = i2p::fs::DataDirPath (filename);
 | 
			
		||||
		std::ifstream s(fullPath, std::ifstream::binary);
 | 
			
		||||
		if (s.is_open ())	
 | 
			
		||||
		{	
 | 
			
		||||
		if (s.is_open ())
 | 
			
		||||
		{
 | 
			
		||||
			s.seekg (0, std::ios::end);
 | 
			
		||||
			size_t len = s.tellg();
 | 
			
		||||
			s.seekg (0, std::ios::beg);
 | 
			
		||||
| 
						 | 
				
			
			@ -267,18 +268,18 @@ namespace client
 | 
			
		|||
			else
 | 
			
		||||
				LogPrint (eLogInfo, "Clients: Local address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " loaded");
 | 
			
		||||
			delete[] buf;
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Clients: can't open file ", fullPath, " Creating new one with signature type ", sigType);
 | 
			
		||||
			keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); 
 | 
			
		||||
			keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
 | 
			
		||||
			std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out);
 | 
			
		||||
			size_t len = keys.GetFullLen ();
 | 
			
		||||
			uint8_t * buf = new uint8_t[len];
 | 
			
		||||
			len = keys.ToBuffer (buf, len);
 | 
			
		||||
			f.write ((char *)buf, len);
 | 
			
		||||
			delete[] buf;
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			LogPrint (eLogInfo, "Clients: New private keys file ", fullPath, " for ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created");
 | 
			
		||||
		}
 | 
			
		||||
		return success;
 | 
			
		||||
| 
						 | 
				
			
			@ -306,9 +307,9 @@ namespace client
 | 
			
		|||
		}
 | 
			
		||||
		return infos;
 | 
			
		||||
	}
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType,
 | 
			
		||||
		const std::map<std::string, std::string> * params)
 | 
			
		||||
     const std::map<std::string, std::string> * params)
 | 
			
		||||
	{
 | 
			
		||||
		i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
 | 
			
		||||
		auto localDestination = std::make_shared<ClientDestination> (keys, isPublic, params);
 | 
			
		||||
| 
						 | 
				
			
			@ -318,6 +319,16 @@ namespace client
 | 
			
		|||
		return localDestination;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<ClientDestination> ClientContext::CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map<std::string, std::string> * params)
 | 
			
		||||
	{
 | 
			
		||||
		MatchedTunnelDestination * cl = new MatchedTunnelDestination(keys, name, params);
 | 
			
		||||
		auto localDestination = std::shared_ptr<ClientDestination>(cl);
 | 
			
		||||
		std::unique_lock<std::mutex> l(m_DestinationsMutex);
 | 
			
		||||
		m_Destinations[localDestination->GetIdentHash ()] = localDestination;
 | 
			
		||||
		localDestination->Start ();
 | 
			
		||||
		return localDestination;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ClientContext::DeleteLocalDestination (std::shared_ptr<ClientDestination> destination)
 | 
			
		||||
	{
 | 
			
		||||
		if (!destination) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -328,7 +339,7 @@ namespace client
 | 
			
		|||
			{
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_DestinationsMutex);
 | 
			
		||||
				m_Destinations.erase (it);
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
			d->Stop ();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -341,32 +352,32 @@ namespace client
 | 
			
		|||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Clients: Local destination ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " exists");
 | 
			
		||||
			if (!it->second->IsRunning ())
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				it->second->Start ();
 | 
			
		||||
				return it->second;
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
			return nullptr;
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
		auto localDestination = std::make_shared<ClientDestination> (keys, isPublic, params);
 | 
			
		||||
		std::unique_lock<std::mutex> l(m_DestinationsMutex);
 | 
			
		||||
		m_Destinations[keys.GetPublic ()->GetIdentHash ()] = localDestination;
 | 
			
		||||
		localDestination->Start ();
 | 
			
		||||
		return localDestination;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<ClientDestination> ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const
 | 
			
		||||
	{
 | 
			
		||||
		auto it = m_Destinations.find (destination);
 | 
			
		||||
		if (it != m_Destinations.end ())
 | 
			
		||||
			return it->second;
 | 
			
		||||
		return nullptr;
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Section, typename Type>
 | 
			
		||||
	std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
 | 
			
		||||
	{
 | 
			
		||||
        return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Section>
 | 
			
		||||
	void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
 | 
			
		||||
| 
						 | 
				
			
			@ -378,24 +389,24 @@ namespace client
 | 
			
		|||
		options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND);
 | 
			
		||||
		options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);
 | 
			
		||||
		options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const
 | 
			
		||||
	{
 | 
			
		||||
		std::string value; 
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNEL_LENGTH, value)) 
 | 
			
		||||
		std::string value;
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNEL_LENGTH, value))
 | 
			
		||||
			options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = value;
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value)) 
 | 
			
		||||
			options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = value;	
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value)) 
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value))
 | 
			
		||||
			options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = value;
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value))
 | 
			
		||||
			options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = value;
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value)) 
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value))
 | 
			
		||||
			options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = value;
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value))
 | 
			
		||||
			options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value;
 | 
			
		||||
		if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value))
 | 
			
		||||
			options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value;
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ClientContext::ReadTunnels ()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -411,20 +422,20 @@ namespace client
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		LogPrint(eLogDebug, "FS: tunnels config file: ", tunConf);
 | 
			
		||||
		try 
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			boost::property_tree::read_ini (tunConf, pt);
 | 
			
		||||
		} 
 | 
			
		||||
		catch (std::exception& ex) 
 | 
			
		||||
		}
 | 
			
		||||
		catch (std::exception& ex)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Clients: Can't read ", tunConf, ": ", ex.what ());
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		int numClientTunnels = 0, numServerTunnels = 0;
 | 
			
		||||
		for (auto& section: pt)
 | 
			
		||||
		{
 | 
			
		||||
			std::string name = section.first;			
 | 
			
		||||
			std::string name = section.first;
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				std::string type = section.second.get<std::string> (I2P_TUNNELS_SECTION_TYPE);
 | 
			
		||||
| 
						 | 
				
			
			@ -440,13 +451,14 @@ namespace client
 | 
			
		|||
						dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
 | 
			
		||||
					int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
 | 
			
		||||
					// optional params
 | 
			
		||||
					bool matchTunnels = section.second.get(I2P_CLIENT_TUNNEL_MATCH_TUNNELS, false);
 | 
			
		||||
					std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "");
 | 
			
		||||
					std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
 | 
			
		||||
					int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
 | 
			
		||||
					i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
 | 
			
		||||
					// I2CP
 | 
			
		||||
					std::map<std::string, std::string> options;			
 | 
			
		||||
					ReadI2CPOptions (section, options);	
 | 
			
		||||
					std::map<std::string, std::string> options;
 | 
			
		||||
					ReadI2CPOptions (section, options);
 | 
			
		||||
 | 
			
		||||
					std::shared_ptr<ClientDestination> localDestination = nullptr;
 | 
			
		||||
					if (keys.length () > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -456,9 +468,15 @@ namespace client
 | 
			
		|||
						{
 | 
			
		||||
							localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
 | 
			
		||||
							if (!localDestination)
 | 
			
		||||
								localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options);
 | 
			
		||||
							{
 | 
			
		||||
								if(matchTunnels)
 | 
			
		||||
									localDestination = CreateNewMatchedTunnelDestination(k, dest, &options);
 | 
			
		||||
								else
 | 
			
		||||
									localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
 | 
			
		||||
						// udp client
 | 
			
		||||
						// TODO: hostnames
 | 
			
		||||
| 
						 | 
				
			
			@ -515,7 +533,7 @@ namespace client
 | 
			
		|||
								 || type == I2P_TUNNELS_SECTION_TYPE_HTTP
 | 
			
		||||
								 || type == I2P_TUNNELS_SECTION_TYPE_IRC
 | 
			
		||||
								 || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
 | 
			
		||||
				{	
 | 
			
		||||
				{
 | 
			
		||||
					// mandatory params
 | 
			
		||||
					std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
 | 
			
		||||
					int port = section.second.get<int> (I2P_SERVER_TUNNEL_PORT);
 | 
			
		||||
| 
						 | 
				
			
			@ -532,15 +550,15 @@ namespace client
 | 
			
		|||
					bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true);
 | 
			
		||||
 | 
			
		||||
					// I2CP
 | 
			
		||||
					std::map<std::string, std::string> options;							 
 | 
			
		||||
					ReadI2CPOptions (section, options);				
 | 
			
		||||
					std::map<std::string, std::string> options;
 | 
			
		||||
					ReadI2CPOptions (section, options);
 | 
			
		||||
 | 
			
		||||
					std::shared_ptr<ClientDestination> localDestination = nullptr;
 | 
			
		||||
					i2p::data::PrivateKeys k;
 | 
			
		||||
					if(!LoadPrivateKeys (k, keys, sigType))
 | 
			
		||||
						continue;
 | 
			
		||||
					localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
 | 
			
		||||
					if (!localDestination)		
 | 
			
		||||
					if (!localDestination)
 | 
			
		||||
						localDestination = CreateNewLocalDestination (k, true, &options);
 | 
			
		||||
					if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
 | 
			
		||||
					{
 | 
			
		||||
| 
						 | 
				
			
			@ -549,7 +567,7 @@ namespace client
 | 
			
		|||
						auto localAddress = boost::asio::ip::address::from_string(address);
 | 
			
		||||
						boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::address::from_string(host), port);
 | 
			
		||||
						I2PUDPServerTunnel * serverTunnel = new I2PUDPServerTunnel(name, localDestination, localAddress, endpoint, port);
 | 
			
		||||
						if(!isUniqueLocal) 
 | 
			
		||||
						if(!isUniqueLocal)
 | 
			
		||||
						{
 | 
			
		||||
							LogPrint(eLogInfo, "Clients: disabling loopback address mapping");
 | 
			
		||||
							serverTunnel->SetUniqueLocal(isUniqueLocal);
 | 
			
		||||
| 
						 | 
				
			
			@ -566,10 +584,10 @@ namespace client
 | 
			
		|||
						}
 | 
			
		||||
						else
 | 
			
		||||
							LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists");
 | 
			
		||||
						
 | 
			
		||||
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
          
 | 
			
		||||
 | 
			
		||||
					I2PServerTunnel * serverTunnel;
 | 
			
		||||
					if (type == I2P_TUNNELS_SECTION_TYPE_HTTP)
 | 
			
		||||
                    	serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort, gzip);
 | 
			
		||||
| 
						 | 
				
			
			@ -594,7 +612,7 @@ namespace client
 | 
			
		|||
						{
 | 
			
		||||
							comma = accessList.find (',', pos);
 | 
			
		||||
							i2p::data::IdentHash ident;
 | 
			
		||||
							ident.FromBase32 (accessList.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos));	
 | 
			
		||||
							ident.FromBase32 (accessList.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos));
 | 
			
		||||
							idents.insert (ident);
 | 
			
		||||
							pos = comma + 1;
 | 
			
		||||
						}
 | 
			
		||||
| 
						 | 
				
			
			@ -602,7 +620,7 @@ namespace client
 | 
			
		|||
						serverTunnel->SetAccessList (idents);
 | 
			
		||||
					}
 | 
			
		||||
					if (m_ServerTunnels.insert (std::make_pair (
 | 
			
		||||
							std::make_pair (localDestination->GetIdentHash (), inPort), 
 | 
			
		||||
							std::make_pair (localDestination->GetIdentHash (), inPort),
 | 
			
		||||
					        std::unique_ptr<I2PServerTunnel>(serverTunnel))).second)
 | 
			
		||||
					{
 | 
			
		||||
						serverTunnel->Start ();
 | 
			
		||||
| 
						 | 
				
			
			@ -610,21 +628,21 @@ namespace client
 | 
			
		|||
					}
 | 
			
		||||
					else
 | 
			
		||||
						LogPrint (eLogError, "Clients: I2P server tunnel for destination/port ",   m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
 | 
			
		||||
						
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					LogPrint (eLogWarning, "Clients: Unknown section type=", type, " of ", name, " in ", tunConf);
 | 
			
		||||
				
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			catch (std::exception& ex)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogError, "Clients: Can't read tunnel ", name, " params: ", ex.what ());
 | 
			
		||||
			}
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
		LogPrint (eLogInfo, "Clients: ", numClientTunnels, " I2P client tunnels created");
 | 
			
		||||
		LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created");
 | 
			
		||||
	}
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	void ClientContext::ScheduleCleanupUDP()
 | 
			
		||||
	{
 | 
			
		||||
		if (m_CleanupUDPTimer)
 | 
			
		||||
| 
						 | 
				
			
			@ -644,5 +662,5 @@ namespace client
 | 
			
		|||
			ScheduleCleanupUDP();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}		
 | 
			
		||||
}	
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,19 +34,21 @@ namespace client
 | 
			
		|||
	const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination";
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";	
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_HOST[] = "host";	
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";	
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
 | 
			
		||||
  const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_HOST[] = "host";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_PORT[] = "port";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_KEYS[] = "keys";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_INPORT[] = "inport";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist";		
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_GZIP[] = "gzip";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_WEBIRC_PASSWORD[] = "webircpassword";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_ADDRESS[] = "address";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	class ClientContext
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
| 
						 | 
				
			
			@ -62,10 +64,11 @@ namespace client
 | 
			
		|||
			std::shared_ptr<ClientDestination> GetSharedLocalDestination () const { return m_SharedLocalDestination; };
 | 
			
		||||
			std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1,
 | 
			
		||||
			    const std::map<std::string, std::string> * params = nullptr); // transient
 | 
			
		||||
			std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, 
 | 
			
		||||
				const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
			std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
 | 
			
		||||
                                                                    const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
    std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
			void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
 | 
			
		||||
			std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;		
 | 
			
		||||
			std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
 | 
			
		||||
			bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
 | 
			
		||||
 | 
			
		||||
			AddressBook& GetAddressBook () { return m_AddressBook; };
 | 
			
		||||
| 
						 | 
				
			
			@ -81,16 +84,16 @@ namespace client
 | 
			
		|||
			std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const;
 | 
			
		||||
			template<typename Section>
 | 
			
		||||
			void ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const;
 | 
			
		||||
			void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const;	
 | 
			
		||||
			void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const;
 | 
			
		||||
 | 
			
		||||
			void CleanupUDP(const boost::system::error_code & ecode);
 | 
			
		||||
			void ScheduleCleanupUDP();
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::mutex m_DestinationsMutex;
 | 
			
		||||
			std::map<i2p::data::IdentHash, std::shared_ptr<ClientDestination> > m_Destinations;
 | 
			
		||||
			std::shared_ptr<ClientDestination>  m_SharedLocalDestination;	
 | 
			
		||||
			std::shared_ptr<ClientDestination>  m_SharedLocalDestination;
 | 
			
		||||
 | 
			
		||||
			AddressBook m_AddressBook;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -99,16 +102,16 @@ namespace client
 | 
			
		|||
			std::map<boost::asio::ip::tcp::endpoint, std::unique_ptr<I2PService> > m_ClientTunnels; // local endpoint->tunnel
 | 
			
		||||
			std::map<std::pair<i2p::data::IdentHash, int>, std::unique_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port>->tunnel
 | 
			
		||||
 | 
			
		||||
			std::mutex m_ForwardsMutex;			 
 | 
			
		||||
			std::mutex m_ForwardsMutex;
 | 
			
		||||
			std::map<boost::asio::ip::udp::endpoint, std::unique_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel
 | 
			
		||||
			std::map<std::pair<i2p::data::IdentHash, int>, std::unique_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			SAMBridge * m_SamBridge;
 | 
			
		||||
			BOBCommandChannel * m_BOBCommandChannel;
 | 
			
		||||
			I2CPServer * m_I2CPServer;
 | 
			
		||||
 | 
			
		||||
			std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
			// for HTTP
 | 
			
		||||
			const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
 | 
			
		||||
| 
						 | 
				
			
			@ -119,9 +122,9 @@ namespace client
 | 
			
		|||
			const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; }
 | 
			
		||||
			const i2p::proxy::SOCKSProxy * GetSocksProxy () const { return m_SocksProxy; }
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	extern ClientContext context;	
 | 
			
		||||
}		
 | 
			
		||||
}	
 | 
			
		||||
 | 
			
		||||
	extern ClientContext context;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								Datagram.h
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								Datagram.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -19,7 +19,7 @@ namespace client
 | 
			
		|||
}
 | 
			
		||||
namespace datagram
 | 
			
		||||
{
 | 
			
		||||
	// milliseconds for max session idle time 
 | 
			
		||||
	// milliseconds for max session idle time
 | 
			
		||||
	const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000;
 | 
			
		||||
	// milliseconds for how long we try sticking to a dead routing path before trying to switch
 | 
			
		||||
	const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 10 * 1000;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,14 +33,14 @@ namespace datagram
 | 
			
		|||
	const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
 | 
			
		||||
  // max 64 messages buffered in send queue for each datagram session
 | 
			
		||||
  const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	class DatagramSession : public std::enable_shared_from_this<DatagramSession>
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent);
 | 
			
		||||
 | 
			
		||||
		void Start ();
 | 
			
		||||
		void Stop ();	
 | 
			
		||||
		void Stop ();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** @brief ack the garlic routing path */
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ namespace datagram
 | 
			
		|||
			std::shared_ptr<const i2p::data::IdentHash> IBGW;
 | 
			
		||||
			std::shared_ptr<const i2p::data::IdentHash> OBEP;
 | 
			
		||||
			const uint64_t activity;
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
			Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
 | 
			
		||||
			Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
 | 
			
		||||
				activity(a) {
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ namespace datagram
 | 
			
		|||
    void HandleSend(std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
| 
						 | 
				
			
			@ -95,16 +95,16 @@ namespace datagram
 | 
			
		|||
 | 
			
		||||
	typedef std::shared_ptr<DatagramSession> DatagramSession_ptr;
 | 
			
		||||
 | 
			
		||||
	const size_t MAX_DATAGRAM_SIZE = 32768;	 
 | 
			
		||||
	const size_t MAX_DATAGRAM_SIZE = 32768;
 | 
			
		||||
	class DatagramDestination
 | 
			
		||||
	{
 | 
			
		||||
		typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
			DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
 | 
			
		||||
			~DatagramDestination ();	
 | 
			
		||||
 | 
			
		||||
    DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
 | 
			
		||||
			~DatagramDestination ();
 | 
			
		||||
 | 
			
		||||
    	void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
 | 
			
		||||
			void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
 | 
			
		||||
| 
						 | 
				
			
			@ -116,21 +116,21 @@ namespace datagram
 | 
			
		|||
			void ResetReceiver (uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); };
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
			// clean up stale sessions
 | 
			
		||||
			void CleanUp ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
						
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort);
 | 
			
		||||
 | 
			
		||||
			void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
 | 
			
		||||
 | 
			
		||||
			/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
 | 
			
		||||
			Receiver FindReceiver(uint16_t port);
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
			i2p::client::ClientDestination * m_Owner;
 | 
			
		||||
			i2p::data::IdentityEx m_Identity;
 | 
			
		||||
| 
						 | 
				
			
			@ -142,9 +142,8 @@ namespace datagram
 | 
			
		|||
 | 
			
		||||
			i2p::data::GzipInflator m_Inflator;
 | 
			
		||||
			i2p::data::GzipDeflator m_Deflator;
 | 
			
		||||
	};		
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,16 +27,16 @@ namespace client
 | 
			
		|||
{
 | 
			
		||||
	const uint8_t PROTOCOL_TYPE_STREAMING = 6;
 | 
			
		||||
	const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
 | 
			
		||||
	const uint8_t PROTOCOL_TYPE_RAW = 18;	
 | 
			
		||||
	const uint8_t PROTOCOL_TYPE_RAW = 18;
 | 
			
		||||
	const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
 | 
			
		||||
	const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successfull publish
 | 
			
		||||
	const int PUBLISH_MIN_INTERVAL = 20; // in seconds 
 | 
			
		||||
	const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically	
 | 
			
		||||
	const int PUBLISH_MIN_INTERVAL = 20; // in seconds
 | 
			
		||||
	const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically
 | 
			
		||||
	const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds
 | 
			
		||||
	const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds
 | 
			
		||||
	const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes 
 | 
			
		||||
	const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes
 | 
			
		||||
	const unsigned int MAX_NUM_FLOODFILLS_PER_REQUEST = 7;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	// I2CP
 | 
			
		||||
	const char I2CP_PARAM_INBOUND_TUNNEL_LENGTH[] = "inbound.length";
 | 
			
		||||
	const int DEFAULT_INBOUND_TUNNEL_LENGTH = 3;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ namespace client
 | 
			
		|||
	const int DEFAULT_MIN_TUNNEL_LATENCY = 0;
 | 
			
		||||
	const char I2CP_PARAM_MAX_TUNNEL_LATENCY[] = "latency.max";
 | 
			
		||||
	const int DEFAULT_MAX_TUNNEL_LATENCY = 0;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
 | 
			
		||||
 | 
			
		||||
	class LeaseSetDestination: public i2p::garlic::GarlicDestination,
 | 
			
		||||
| 
						 | 
				
			
			@ -78,24 +78,24 @@ namespace client
 | 
			
		|||
			{
 | 
			
		||||
				for (auto& it: requestComplete) it (ls);
 | 
			
		||||
				requestComplete.clear ();
 | 
			
		||||
			}	
 | 
			
		||||
		};	
 | 
			
		||||
		
 | 
			
		||||
		
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
			~LeaseSetDestination ();	
 | 
			
		||||
			~LeaseSetDestination ();
 | 
			
		||||
 | 
			
		||||
			virtual bool Start ();
 | 
			
		||||
			virtual bool Stop ();
 | 
			
		||||
			bool IsRunning () const { return m_IsRunning; };
 | 
			
		||||
			boost::asio::io_service& GetService () { return m_Service; };
 | 
			
		||||
			std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; }; 
 | 
			
		||||
			std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
 | 
			
		||||
			bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
 | 
			
		||||
			std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
 | 
			
		||||
			bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
 | 
			
		||||
			void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);	
 | 
			
		||||
			void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
 | 
			
		||||
 | 
			
		||||
			// implements GarlicDestination
 | 
			
		||||
			std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ namespace client
 | 
			
		|||
			// override GarlicDestination
 | 
			
		||||
			bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
 | 
			
		||||
			void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
			void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);	
 | 
			
		||||
			void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
			void SetLeaseSetUpdated ();
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
| 
						 | 
				
			
			@ -115,10 +115,10 @@ namespace client
 | 
			
		|||
			// I2CP
 | 
			
		||||
			virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
 | 
			
		||||
			virtual void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels) = 0;
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
				
 | 
			
		||||
			void Run ();			
 | 
			
		||||
 | 
			
		||||
			void Run ();
 | 
			
		||||
			void UpdateLeaseSet ();
 | 
			
		||||
			void Publish ();
 | 
			
		||||
			void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
 | 
			
		||||
| 
						 | 
				
			
			@ -126,18 +126,18 @@ namespace client
 | 
			
		|||
			void HandlePublishDelayTimer (const boost::system::error_code& ecode);
 | 
			
		||||
			void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
 | 
			
		||||
			void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
 | 
			
		||||
			void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);		
 | 
			
		||||
			void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
 | 
			
		||||
			void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete);
 | 
			
		||||
			bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo>  nextFloodfill, std::shared_ptr<LeaseSetRequest> request);	
 | 
			
		||||
			bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo>  nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
 | 
			
		||||
			void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
 | 
			
		||||
			void HandleCleanupTimer (const boost::system::error_code& ecode);
 | 
			
		||||
			void CleanupRemoteLeaseSets ();			
 | 
			
		||||
			
 | 
			
		||||
			void CleanupRemoteLeaseSets ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			volatile bool m_IsRunning;
 | 
			
		||||
			std::thread * m_Thread;	
 | 
			
		||||
			std::thread * m_Thread;
 | 
			
		||||
			boost::asio::io_service m_Service;
 | 
			
		||||
			mutable std::mutex m_RemoteLeaseSetsMutex;
 | 
			
		||||
			std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
 | 
			
		||||
| 
						 | 
				
			
			@ -150,16 +150,16 @@ namespace client
 | 
			
		|||
			uint32_t m_PublishReplyToken;
 | 
			
		||||
			uint64_t m_LastSubmissionTime; // in seconds
 | 
			
		||||
			std::set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
 | 
			
		||||
	
 | 
			
		||||
			boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, 
 | 
			
		||||
 | 
			
		||||
			boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
 | 
			
		||||
				m_PublishDelayTimer, m_CleanupTimer;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			// for HTTP only
 | 
			
		||||
			int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
 | 
			
		||||
			const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; };
 | 
			
		||||
	};	
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class ClientDestination: public LeaseSetDestination
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -171,16 +171,16 @@ namespace client
 | 
			
		|||
			// if cancelled before ready, informs promise with nullptr
 | 
			
		||||
			void Ready(ReadyPromise & p);
 | 
			
		||||
#endif
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
			ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
			~ClientDestination ();
 | 
			
		||||
			
 | 
			
		||||
			bool Start ();
 | 
			
		||||
			bool Stop ();
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			virtual bool Start ();
 | 
			
		||||
			virtual bool Stop ();
 | 
			
		||||
 | 
			
		||||
			const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
 | 
			
		||||
			void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };	
 | 
			
		||||
			
 | 
			
		||||
			void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
 | 
			
		||||
 | 
			
		||||
			// streaming
 | 
			
		||||
			std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
 | 
			
		||||
			std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
 | 
			
		||||
| 
						 | 
				
			
			@ -191,31 +191,31 @@ namespace client
 | 
			
		|||
			void StopAcceptingStreams ();
 | 
			
		||||
			bool IsAcceptingStreams () const;
 | 
			
		||||
			void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			// datagram
 | 
			
		||||
      i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
 | 
			
		||||
      i2p::datagram::DatagramDestination * CreateDatagramDestination ();
 | 
			
		||||
			
 | 
			
		||||
			// implements LocalDestination		
 | 
			
		||||
 | 
			
		||||
			// implements LocalDestination
 | 
			
		||||
			const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
 | 
			
		||||
			std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };			
 | 
			
		||||
			std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			void CleanupDestination ();
 | 
			
		||||
			// I2CP
 | 
			
		||||
			void HandleDataMessage (const uint8_t * buf, size_t len);
 | 
			
		||||
			void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<ClientDestination> GetSharedFromThis ()
 | 
			
		||||
			{ return std::static_pointer_cast<ClientDestination>(shared_from_this ()); }   
 | 
			
		||||
			{ return std::static_pointer_cast<ClientDestination>(shared_from_this ()); }
 | 
			
		||||
			void PersistTemporaryKeys ();
 | 
			
		||||
#ifdef I2LUA
 | 
			
		||||
			void ScheduleCheckForReady(ReadyPromise * p);
 | 
			
		||||
			void HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p);
 | 
			
		||||
#endif      
 | 
			
		||||
#endif
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			i2p::data::PrivateKeys m_Keys;
 | 
			
		||||
| 
						 | 
				
			
			@ -226,13 +226,13 @@ namespace client
 | 
			
		|||
      i2p::datagram::DatagramDestination * m_DatagramDestination;
 | 
			
		||||
 | 
			
		||||
			boost::asio::deadline_timer m_ReadyChecker;
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			// for HTTP only
 | 
			
		||||
			std::vector<std::shared_ptr<const i2p::stream::Stream> > GetAllStreams () const;
 | 
			
		||||
	};	
 | 
			
		||||
}	
 | 
			
		||||
}	
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										94
									
								
								I2PTunnel.h
									
										
									
									
									
								
							
							
						
						
									
										94
									
								
								I2PTunnel.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -19,9 +19,9 @@ namespace i2p
 | 
			
		|||
namespace client
 | 
			
		||||
{
 | 
			
		||||
	const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 65536;
 | 
			
		||||
	const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds	
 | 
			
		||||
	const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
 | 
			
		||||
	const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
 | 
			
		||||
	// for HTTP tunnels		
 | 
			
		||||
	// for HTTP tunnels
 | 
			
		||||
	const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash  in base64
 | 
			
		||||
	const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
 | 
			
		||||
	const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
 | 
			
		||||
| 
						 | 
				
			
			@ -33,21 +33,21 @@ namespace client
 | 
			
		|||
			I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
 | 
			
		||||
			I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API 
 | 
			
		||||
			I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,  std::shared_ptr<boost::asio::ip::tcp::socket> socket, 
 | 
			
		||||
				std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API
 | 
			
		||||
			I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,  std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				const boost::asio::ip::tcp::endpoint& target, bool quiet = true); // from I2P
 | 
			
		||||
			~I2PTunnelConnection ();
 | 
			
		||||
			void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0);
 | 
			
		||||
			void Connect (bool isUniqueLocal = true);
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Terminate ();	
 | 
			
		||||
			void Terminate ();
 | 
			
		||||
 | 
			
		||||
			void Receive ();
 | 
			
		||||
			void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);	
 | 
			
		||||
			void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
 | 
			
		||||
			virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
 | 
			
		||||
			void HandleWrite (const boost::system::error_code& ecode);	
 | 
			
		||||
			void HandleWrite (const boost::system::error_code& ecode);
 | 
			
		||||
 | 
			
		||||
			void StreamReceive ();
 | 
			
		||||
			void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,28 +75,28 @@ namespace client
 | 
			
		|||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Write (const uint8_t * buf, size_t len);	
 | 
			
		||||
			
 | 
			
		||||
		private:	
 | 
			
		||||
			void Write (const uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::stringstream m_InHeader, m_OutHeader;
 | 
			
		||||
			bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
 | 
			
		||||
	};	
 | 
			
		||||
	
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::socket> socket, 
 | 
			
		||||
				const boost::asio::ip::tcp::endpoint& target, const std::string& host); 
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				const boost::asio::ip::tcp::endpoint& target, const std::string& host);
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Write (const uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
			std::string m_Host;
 | 
			
		||||
			std::stringstream m_InHeader, m_OutHeader;
 | 
			
		||||
			bool m_HeaderSent;
 | 
			
		||||
| 
						 | 
				
			
			@ -106,21 +106,21 @@ namespace client
 | 
			
		|||
	class I2PTunnelConnectionIRC: public I2PTunnelConnection
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
            I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
 | 
			
		||||
                std::shared_ptr<boost::asio::ip::tcp::socket> socket, 
 | 
			
		||||
                const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); 
 | 
			
		||||
                std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
                const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
 | 
			
		||||
 | 
			
		||||
        protected:
 | 
			
		||||
 | 
			
		||||
            void Write (const uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
            std::shared_ptr<const i2p::data::IdentityEx> m_From;
 | 
			
		||||
            std::stringstream m_OutPacket, m_InPacket;
 | 
			
		||||
			bool m_NeedsWebIrc;
 | 
			
		||||
            std::string m_WebircPass; 
 | 
			
		||||
            std::string m_WebircPass;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -133,24 +133,24 @@ namespace client
 | 
			
		|||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PClientTunnel (const std::string& name, const std::string& destination, 
 | 
			
		||||
			I2PClientTunnel (const std::string& name, const std::string& destination,
 | 
			
		||||
				const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
 | 
			
		||||
			~I2PClientTunnel () {}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
			void Start ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
 | 
			
		||||
			const char* GetName() { return m_Name.c_str (); }	
 | 
			
		||||
			
 | 
			
		||||
			const char* GetName() { return m_Name.c_str (); }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			const i2p::data::IdentHash * GetIdentHash ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			std::string m_Name, m_Destination;
 | 
			
		||||
			const i2p::data::IdentHash * m_DestinationIdentHash;
 | 
			
		||||
			int m_DestinationPort;	
 | 
			
		||||
			int m_DestinationPort;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +173,7 @@ namespace client
 | 
			
		|||
		uint16_t RemotePort;
 | 
			
		||||
 | 
			
		||||
		uint8_t m_Buffer[I2P_UDP_MAX_MTU];
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
		UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
 | 
			
		||||
							 const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
 | 
			
		||||
							 boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +182,7 @@ namespace client
 | 
			
		|||
		void Receive();
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	/** read only info about a datagram session */
 | 
			
		||||
	struct DatagramSessionInfo
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ namespace client
 | 
			
		|||
	};
 | 
			
		||||
 | 
			
		||||
	typedef std::shared_ptr<UDPSession> UDPSessionPtr;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	/** server side udp tunnel, many i2p inbound to 1 ip outbound */
 | 
			
		||||
	class I2PUDPServerTunnel
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +239,7 @@ namespace client
 | 
			
		|||
			std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class I2PUDPClientTunnel 
 | 
			
		||||
	class I2PUDPClientTunnel
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
			I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +249,7 @@ namespace client
 | 
			
		|||
			void Start();
 | 
			
		||||
			const char * GetName() const { return m_Name.c_str(); }
 | 
			
		||||
			std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions();
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			bool IsLocalDestination(const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); }
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
 | 
			
		||||
| 
						 | 
				
			
			@ -275,18 +275,18 @@ namespace client
 | 
			
		|||
			uint16_t RemotePort;
 | 
			
		||||
			bool m_cancel_resolve;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	class I2PServerTunnel: public I2PService
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnel (const std::string& name, const std::string& address, int port, 
 | 
			
		||||
				std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);	
 | 
			
		||||
			I2PServerTunnel (const std::string& name, const std::string& address, int port,
 | 
			
		||||
				std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
 | 
			
		||||
 | 
			
		||||
			void Start ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
 | 
			
		||||
			void SetAccessList (const std::set<i2p::data::IdentHash>& accessList); 
 | 
			
		||||
			void SetAccessList (const std::set<i2p::data::IdentHash>& accessList);
 | 
			
		||||
 | 
			
		||||
			void SetUniqueLocal (bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; }
 | 
			
		||||
			bool IsUniqueLocal () const { return m_IsUniqueLocal; }
 | 
			
		||||
| 
						 | 
				
			
			@ -296,13 +296,13 @@ namespace client
 | 
			
		|||
			uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); };
 | 
			
		||||
			const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; }
 | 
			
		||||
 | 
			
		||||
			const char* GetName() { return m_Name.c_str (); }	
 | 
			
		||||
			const char* GetName() { return m_Name.c_str (); }
 | 
			
		||||
 | 
			
		||||
      void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
			void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, 
 | 
			
		||||
			void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
 | 
			
		||||
 | 
			
		||||
			void Accept ();
 | 
			
		||||
| 
						 | 
				
			
			@ -310,11 +310,11 @@ namespace client
 | 
			
		|||
			virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			bool m_IsUniqueLocal;
 | 
			
		||||
			std::string m_Name, m_Address;
 | 
			
		||||
			int m_Port;
 | 
			
		||||
			boost::asio::ip::tcp::endpoint m_Endpoint;	
 | 
			
		||||
			boost::asio::ip::tcp::endpoint m_Endpoint;
 | 
			
		||||
			std::shared_ptr<i2p::stream::StreamingDestination> m_PortDestination;
 | 
			
		||||
			std::set<i2p::data::IdentHash> m_AccessList;
 | 
			
		||||
			bool m_IsAccessList;
 | 
			
		||||
| 
						 | 
				
			
			@ -324,9 +324,9 @@ namespace client
 | 
			
		|||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, 
 | 
			
		||||
			I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
 | 
			
		||||
				std::shared_ptr<ClientDestination> localDestination, const std::string& host,
 | 
			
		||||
			    int inport = 0, bool gzip = true);	
 | 
			
		||||
			    int inport = 0, bool gzip = true);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -336,14 +336,14 @@ namespace client
 | 
			
		|||
 | 
			
		||||
			std::string m_Host;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
    class I2PServerTunnelIRC: public I2PServerTunnel
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, 
 | 
			
		||||
            I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
 | 
			
		||||
                std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
 | 
			
		||||
                int inport = 0, bool gzip = true);   
 | 
			
		||||
                int inport = 0, bool gzip = true);
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -355,6 +355,6 @@ namespace client
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ INCFLAGS ?=
 | 
			
		|||
# detect proper flag for c++11 support by compilers
 | 
			
		||||
CXXVER := $(shell $(CXX) -dumpversion)
 | 
			
		||||
ifeq ($(shell expr match $(CXX) 'clang'),5)
 | 
			
		||||
	NEEDED_CXXFLAGS += -std=c++11
 | 
			
		||||
	NEEDED_CXXFLAGS += -std=c++11 
 | 
			
		||||
else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10
 | 
			
		||||
	NEEDED_CXXFLAGS += -std=c++11
 | 
			
		||||
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										105
									
								
								MatchedDestination.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								MatchedDestination.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
#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)
 | 
			
		||||
		: ClientDestination(keys, false, params),
 | 
			
		||||
			m_RemoteName(remoteName) {}
 | 
			
		||||
 | 
			
		||||
	void MatchedTunnelDestination::ResolveCurrentLeaseSet()
 | 
			
		||||
	{
 | 
			
		||||
		if(i2p::client::context.GetAddressBook().GetIdentHash(m_RemoteName, m_RemoteIdent))
 | 
			
		||||
		{
 | 
			
		||||
			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
 | 
			
		||||
			ResolveCurrentLeaseSet();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	bool MatchedTunnelDestination::Start()
 | 
			
		||||
	{
 | 
			
		||||
		if(ClientDestination::Start())
 | 
			
		||||
		{
 | 
			
		||||
			GetTunnelPool()->SetCustomPeerSelector(this);
 | 
			
		||||
			ResolveCurrentLeaseSet();
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool MatchedTunnelDestination::Stop()
 | 
			
		||||
	{
 | 
			
		||||
		if(ClientDestination::Stop())
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound)
 | 
			
		||||
	{
 | 
			
		||||
		auto pool = GetTunnelPool();
 | 
			
		||||
		if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1)))
 | 
			
		||||
			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.push_back(obep->GetRouterIdentity());
 | 
			
		||||
					LogPrint(eLogDebug, "Destination: found OBEP matching IBGW");
 | 
			
		||||
				} else
 | 
			
		||||
					LogPrint(eLogWarning, "Destination: could not find proper IBGW for matched outbound tunnel");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool MatchedTunnelDestination::OnBuildResult(const i2p::tunnel::Path & path, bool inbound, i2p::tunnel::TunnelBuildResult result)
 | 
			
		||||
	{
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								MatchedDestination.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								MatchedDestination.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
#ifndef MATCHED_DESTINATION_H_
 | 
			
		||||
#define MATCHED_DESTINATION_H_
 | 
			
		||||
#include "Destination.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
namespace client
 | 
			
		||||
{
 | 
			
		||||
  /**
 | 
			
		||||
     client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination
 | 
			
		||||
   */
 | 
			
		||||
  class MatchedTunnelDestination : public ClientDestination, public i2p::tunnel::ITunnelPeerSelector
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
    bool Start();
 | 
			
		||||
    bool Stop();
 | 
			
		||||
 | 
			
		||||
    bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound);
 | 
			
		||||
    bool OnBuildResult(const i2p::tunnel::Path & peers, bool inbound, i2p::tunnel::TunnelBuildResult result);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void ResolveCurrentLeaseSet();
 | 
			
		||||
    void HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    std::string m_RemoteName;
 | 
			
		||||
    i2p::data::IdentHash m_RemoteIdent;
 | 
			
		||||
    std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										202
									
								
								TunnelPool.cpp
									
										
									
									
									
								
							
							
						
						
									
										202
									
								
								TunnelPool.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -18,7 +18,7 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace tunnel
 | 
			
		||||
{
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
 | 
			
		||||
		m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
 | 
			
		||||
		m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true),
 | 
			
		||||
| 
						 | 
				
			
			@ -37,25 +37,25 @@ namespace tunnel
 | 
			
		|||
		if (m_ExplicitPeers)
 | 
			
		||||
		{
 | 
			
		||||
			int size = m_ExplicitPeers->size ();
 | 
			
		||||
			if (m_NumInboundHops > size) 
 | 
			
		||||
			if (m_NumInboundHops > size)
 | 
			
		||||
			{
 | 
			
		||||
				m_NumInboundHops = size;
 | 
			
		||||
				LogPrint (eLogInfo, "Tunnels: Inbound tunnel length has beed adjusted to ", size, " for explicit peers");
 | 
			
		||||
			} 
 | 
			
		||||
			if (m_NumOutboundHops > size) 
 | 
			
		||||
			}
 | 
			
		||||
			if (m_NumOutboundHops > size)
 | 
			
		||||
			{
 | 
			
		||||
				m_NumOutboundHops = size;
 | 
			
		||||
				LogPrint (eLogInfo, "Tunnels: Outbound tunnel length has beed adjusted to ", size, " for explicit peers");
 | 
			
		||||
			} 
 | 
			
		||||
			}
 | 
			
		||||
			m_NumInboundTunnels = 1;
 | 
			
		||||
			m_NumOutboundTunnels = 1;
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::DetachTunnels ()
 | 
			
		||||
	{
 | 
			
		||||
		{
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);	
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
 | 
			
		||||
			for (auto& it: m_InboundTunnels)
 | 
			
		||||
				it->SetTunnelPool (nullptr);
 | 
			
		||||
			m_InboundTunnels.clear ();
 | 
			
		||||
| 
						 | 
				
			
			@ -67,21 +67,21 @@ namespace tunnel
 | 
			
		|||
			m_OutboundTunnels.clear ();
 | 
			
		||||
		}
 | 
			
		||||
		m_Tests.clear ();
 | 
			
		||||
	}	
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel)
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_IsActive) return;
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS			
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.created", createdTunnel);
 | 
			
		||||
#endif			
 | 
			
		||||
#endif
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
 | 
			
		||||
			m_InboundTunnels.insert (createdTunnel);
 | 
			
		||||
		}
 | 
			
		||||
		if (m_LocalDestination)
 | 
			
		||||
			m_LocalDestination->SetLeaseSetUpdated ();
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		OnTunnelBuildResult(createdTunnel, eBuildResultOkay);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -89,25 +89,25 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		if (expiredTunnel)
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS			
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.expired", expiredTunnel);
 | 
			
		||||
#endif			
 | 
			
		||||
#endif
 | 
			
		||||
			expiredTunnel->SetTunnelPool (nullptr);
 | 
			
		||||
			for (auto& it: m_Tests)
 | 
			
		||||
				if (it.second.second == expiredTunnel) it.second.second = nullptr;
 | 
			
		||||
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
 | 
			
		||||
			m_InboundTunnels.erase (expiredTunnel);
 | 
			
		||||
		}	
 | 
			
		||||
	}	
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::TunnelCreated (std::shared_ptr<OutboundTunnel> createdTunnel)
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_IsActive) return;
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS			
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.created", createdTunnel);
 | 
			
		||||
#endif			
 | 
			
		||||
#endif
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
 | 
			
		||||
			m_OutboundTunnels.insert (createdTunnel);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -120,9 +120,9 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		if (expiredTunnel)
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS			
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.expired", expiredTunnel);
 | 
			
		||||
#endif			
 | 
			
		||||
#endif
 | 
			
		||||
			expiredTunnel->SetTunnelPool (nullptr);
 | 
			
		||||
			for (auto& it: m_Tests)
 | 
			
		||||
				if (it.second.first == expiredTunnel) it.second.first = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +131,7 @@ namespace tunnel
 | 
			
		|||
			m_OutboundTunnels.erase (expiredTunnel);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	std::vector<std::shared_ptr<InboundTunnel> > TunnelPool::GetInboundTunnels (int num) const
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<InboundTunnel> > v;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,8 +144,8 @@ namespace tunnel
 | 
			
		|||
			{
 | 
			
		||||
				v.push_back (it);
 | 
			
		||||
				i++;
 | 
			
		||||
			}	
 | 
			
		||||
		}	
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return v;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
 | 
			
		||||
		return GetNextTunnel (m_OutboundTunnels, excluded);
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<InboundTunnel> TunnelPool::GetNextInboundTunnel (std::shared_ptr<InboundTunnel> excluded) const
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -164,11 +164,11 @@ namespace tunnel
 | 
			
		|||
	template<class TTunnels>
 | 
			
		||||
	typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const
 | 
			
		||||
	{
 | 
			
		||||
		if (tunnels.empty ()) return nullptr;		
 | 
			
		||||
		if (tunnels.empty ()) return nullptr;
 | 
			
		||||
		uint32_t ind = rand () % (tunnels.size ()/2 + 1), i = 0;
 | 
			
		||||
		typename TTunnels::value_type tunnel = nullptr;
 | 
			
		||||
		for (const auto& it: tunnels)
 | 
			
		||||
		{	
 | 
			
		||||
		{
 | 
			
		||||
			if (it->IsEstablished () && it != excluded)
 | 
			
		||||
			{
 | 
			
		||||
				if(HasLatencyRequirement() && it->LatencyIsKnown() && !it->LatencyFitsRange(m_MinLatency, m_MaxLatency)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ namespace tunnel
 | 
			
		|||
		if(HasLatencyRequirement() && !tunnel) {
 | 
			
		||||
			ind = rand () % (tunnels.size ()/2 + 1), i = 0;
 | 
			
		||||
			for (const auto& it: tunnels)
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				if (it->IsEstablished () && it != excluded)
 | 
			
		||||
				{
 | 
			
		||||
						tunnel = it;
 | 
			
		||||
| 
						 | 
				
			
			@ -199,10 +199,10 @@ namespace tunnel
 | 
			
		|||
	std::shared_ptr<OutboundTunnel> TunnelPool::GetNewOutboundTunnel (std::shared_ptr<OutboundTunnel> old) const
 | 
			
		||||
	{
 | 
			
		||||
		if (old && old->IsEstablished ()) return old;
 | 
			
		||||
		std::shared_ptr<OutboundTunnel> tunnel;	
 | 
			
		||||
		std::shared_ptr<OutboundTunnel> tunnel;
 | 
			
		||||
		if (old)
 | 
			
		||||
		{
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);	
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
 | 
			
		||||
			for (const auto& it: m_OutboundTunnels)
 | 
			
		||||
				if (it->IsEstablished () && old->GetEndpointIdentHash () == it->GetEndpointIdentHash ())
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -210,9 +210,9 @@ namespace tunnel
 | 
			
		|||
					break;
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
		if (!tunnel)
 | 
			
		||||
			tunnel = GetNextOutboundTunnel ();		
 | 
			
		||||
			tunnel = GetNextOutboundTunnel ();
 | 
			
		||||
		return tunnel;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -220,12 +220,12 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		int num = 0;
 | 
			
		||||
		{
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);	
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
 | 
			
		||||
			for (const auto& it : m_OutboundTunnels)
 | 
			
		||||
				if (it->IsEstablished ()) num++;
 | 
			
		||||
		}
 | 
			
		||||
		for (int i = num; i < m_NumOutboundTunnels; i++)
 | 
			
		||||
			CreateOutboundTunnel ();	
 | 
			
		||||
			CreateOutboundTunnel ();
 | 
			
		||||
 | 
			
		||||
		num = 0;
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -253,20 +253,20 @@ namespace tunnel
 | 
			
		|||
			LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed");
 | 
			
		||||
			// if test failed again with another tunnel we consider it failed
 | 
			
		||||
			if (it.second.first)
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				if (it.second.first->GetState () == eTunnelStateTestFailed)
 | 
			
		||||
				{	
 | 
			
		||||
				{
 | 
			
		||||
					it.second.first->SetState (eTunnelStateFailed);
 | 
			
		||||
					std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
 | 
			
		||||
					m_OutboundTunnels.erase (it.second.first);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					it.second.first->SetState (eTunnelStateTestFailed);
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
			if (it.second.second)
 | 
			
		||||
			{
 | 
			
		||||
				if (it.second.second->GetState () == eTunnelStateTestFailed)
 | 
			
		||||
				{	
 | 
			
		||||
				{
 | 
			
		||||
					it.second.second->SetState (eTunnelStateFailed);
 | 
			
		||||
					{
 | 
			
		||||
						std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
 | 
			
		||||
| 
						 | 
				
			
			@ -274,25 +274,25 @@ namespace tunnel
 | 
			
		|||
					}
 | 
			
		||||
					if (m_LocalDestination)
 | 
			
		||||
						m_LocalDestination->SetLeaseSetUpdated ();
 | 
			
		||||
				}	
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					it.second.second->SetState (eTunnelStateTestFailed);
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	
 | 
			
		||||
		// new tests	
 | 
			
		||||
 | 
			
		||||
		// new tests
 | 
			
		||||
		auto it1 = m_OutboundTunnels.begin ();
 | 
			
		||||
		auto it2 = m_InboundTunnels.begin ();
 | 
			
		||||
		while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ())
 | 
			
		||||
		{
 | 
			
		||||
			bool failed = false;
 | 
			
		||||
			if ((*it1)->IsFailed ())
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				failed = true;
 | 
			
		||||
				++it1;
 | 
			
		||||
			}
 | 
			
		||||
			if ((*it2)->IsFailed ())
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				failed = true;
 | 
			
		||||
				++it2;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -307,7 +307,7 @@ namespace tunnel
 | 
			
		|||
 				(*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
 | 
			
		||||
					CreateDeliveryStatusMsg (msgID));
 | 
			
		||||
				++it1; ++it2;
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -317,24 +317,24 @@ namespace tunnel
 | 
			
		|||
			m_LocalDestination->ProcessGarlicMessage (msg);
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogWarning, "Tunnels: local destination doesn't exist, dropped");
 | 
			
		||||
	}	
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg)
 | 
			
		||||
	{
 | 
			
		||||
		const uint8_t * buf = msg->GetPayload ();
 | 
			
		||||
		uint32_t msgID = bufbe32toh (buf);
 | 
			
		||||
		buf += 4;	
 | 
			
		||||
		buf += 4;
 | 
			
		||||
		uint64_t timestamp = bufbe64toh (buf);
 | 
			
		||||
 | 
			
		||||
		decltype(m_Tests)::mapped_type test;
 | 
			
		||||
		bool found = false;	
 | 
			
		||||
		bool found = false;
 | 
			
		||||
		{
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_TestsMutex);
 | 
			
		||||
			auto it = m_Tests.find (msgID);
 | 
			
		||||
			if (it != m_Tests.end ())
 | 
			
		||||
			{
 | 
			
		||||
				found = true;
 | 
			
		||||
				test = it->second; 
 | 
			
		||||
				test = it->second;
 | 
			
		||||
				m_Tests.erase (it);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -358,35 +358,23 @@ namespace tunnel
 | 
			
		|||
				m_LocalDestination->ProcessDeliveryStatusMessage (msg);
 | 
			
		||||
			else
 | 
			
		||||
				LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped");
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const
 | 
			
		||||
	{
 | 
			
		||||
		bool isExploratory = (i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ());
 | 
			
		||||
		auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop): 
 | 
			
		||||
		auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop):
 | 
			
		||||
			i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop);
 | 
			
		||||
 | 
			
		||||
		if (!hop || hop->GetProfile ()->IsBad ())
 | 
			
		||||
			hop = i2p::data::netdb.GetRandomRouter (prevHop);
 | 
			
		||||
		return hop;	
 | 
			
		||||
	}	
 | 
			
		||||
		return hop;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool TunnelPool::SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
 | 
			
		||||
	bool StandardSelectPeers(Path & peers, int numHops, bool inbound, SelectHopFunc nextHop)
 | 
			
		||||
	{
 | 
			
		||||
		int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
 | 
			
		||||
		// peers is empty
 | 
			
		||||
		if (numHops <= 0) return true; 
 | 
			
		||||
		// custom peer selector in use ?
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
 | 
			
		||||
			if (m_CustomPeerSelector)
 | 
			
		||||
					return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
 | 
			
		||||
		}
 | 
			
		||||
		// explicit peers in use
 | 
			
		||||
		if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
 | 
			
		||||
 | 
			
		||||
		auto prevHop = i2p::context.GetSharedRouterInfo ();			
 | 
			
		||||
		auto prevHop = i2p::context.GetSharedRouterInfo ();
 | 
			
		||||
		if(i2p::transport::transports.RoutesRestricted())
 | 
			
		||||
		{
 | 
			
		||||
			/** if routes are restricted prepend trusted first hop */
 | 
			
		||||
| 
						 | 
				
			
			@ -399,36 +387,52 @@ namespace tunnel
 | 
			
		|||
		{
 | 
			
		||||
			auto r = i2p::transport::transports.GetRandomPeer ();
 | 
			
		||||
			if (r && !r->GetProfile ()->IsBad ())
 | 
			
		||||
			{
 | 
			
		||||
				prevHop = r;
 | 
			
		||||
				peers.push_back (r->GetRouterIdentity ());
 | 
			
		||||
				numHops--;
 | 
			
		||||
			}
 | 
			
		||||
				{
 | 
			
		||||
					prevHop = r;
 | 
			
		||||
					peers.push_back (r->GetRouterIdentity ());
 | 
			
		||||
					numHops--;
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		for(int i = 0; i < numHops; i++ )
 | 
			
		||||
		{
 | 
			
		||||
			auto hop = SelectNextHop (prevHop);
 | 
			
		||||
			auto hop = nextHop (prevHop);
 | 
			
		||||
			if (!hop)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
 | 
			
		||||
				return false;
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
			prevHop = hop;
 | 
			
		||||
			peers.push_back (hop->GetRouterIdentity ());
 | 
			
		||||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	}	
 | 
			
		||||
	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool TunnelPool::SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
 | 
			
		||||
	{
 | 
			
		||||
		int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
 | 
			
		||||
		// peers is empty
 | 
			
		||||
		if (numHops <= 0) return true;
 | 
			
		||||
		// custom peer selector in use ?
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
 | 
			
		||||
			if (m_CustomPeerSelector)
 | 
			
		||||
					return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
 | 
			
		||||
		}
 | 
			
		||||
		// explicit peers in use
 | 
			
		||||
		if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
 | 
			
		||||
		return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool TunnelPool::SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
 | 
			
		||||
	{
 | 
			
		||||
		int size = m_ExplicitPeers->size ();
 | 
			
		||||
		std::vector<int> peerIndicies;
 | 
			
		||||
		for (int i = 0; i < size; i++) peerIndicies.push_back(i);
 | 
			
		||||
		std::random_shuffle (peerIndicies.begin(), peerIndicies.end());
 | 
			
		||||
	
 | 
			
		||||
		int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;		
 | 
			
		||||
		for (int i = 0; i < numHops; i++) 
 | 
			
		||||
 | 
			
		||||
		int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
 | 
			
		||||
		for (int i = 0; i < numHops; i++)
 | 
			
		||||
		{
 | 
			
		||||
			auto& ident = (*m_ExplicitPeers)[peerIndicies[i]];
 | 
			
		||||
			auto r = i2p::data::netdb.FindRouter (ident);
 | 
			
		||||
| 
						 | 
				
			
			@ -443,7 +447,7 @@ namespace tunnel
 | 
			
		|||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::CreateInboundTunnel ()
 | 
			
		||||
	{
 | 
			
		||||
		auto outboundTunnel = GetNextOutboundTunnel ();
 | 
			
		||||
| 
						 | 
				
			
			@ -455,15 +459,15 @@ namespace tunnel
 | 
			
		|||
		{
 | 
			
		||||
			std::shared_ptr<TunnelConfig> config;
 | 
			
		||||
			if (m_NumInboundHops > 0)
 | 
			
		||||
			{	
 | 
			
		||||
				std::reverse (peers.begin (), peers.end ());	
 | 
			
		||||
			{
 | 
			
		||||
				std::reverse (peers.begin (), peers.end ());
 | 
			
		||||
				config = std::make_shared<TunnelConfig> (peers);
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
			auto tunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
 | 
			
		||||
			tunnel->SetTunnelPool (shared_from_this ());
 | 
			
		||||
			if (tunnel->IsEstablished ()) // zero hops
 | 
			
		||||
				TunnelCreated (tunnel);
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogError, "Tunnels: Can't create inbound tunnel, no peers available");
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -480,41 +484,41 @@ namespace tunnel
 | 
			
		|||
		newTunnel->SetTunnelPool (shared_from_this());
 | 
			
		||||
		if (newTunnel->IsEstablished ()) // zero hops
 | 
			
		||||
			TunnelCreated (newTunnel);
 | 
			
		||||
	}	
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::CreateOutboundTunnel ()
 | 
			
		||||
	{
 | 
			
		||||
		auto inboundTunnel = GetNextInboundTunnel ();
 | 
			
		||||
		if (!inboundTunnel)
 | 
			
		||||
			inboundTunnel = tunnels.GetNextInboundTunnel ();
 | 
			
		||||
		if (inboundTunnel)
 | 
			
		||||
		{	
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogDebug, "Tunnels: Creating destination outbound tunnel...");
 | 
			
		||||
			std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
 | 
			
		||||
			if (SelectPeers (peers, false))
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				std::shared_ptr<TunnelConfig> config;
 | 
			
		||||
				if (m_NumOutboundHops > 0) 
 | 
			
		||||
				if (m_NumOutboundHops > 0)
 | 
			
		||||
					config = std::make_shared<TunnelConfig>(peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
 | 
			
		||||
				auto tunnel = tunnels.CreateOutboundTunnel (config);
 | 
			
		||||
				tunnel->SetTunnelPool (shared_from_this ());
 | 
			
		||||
				if (tunnel->IsEstablished ()) // zero hops
 | 
			
		||||
					TunnelCreated (tunnel);
 | 
			
		||||
			}	
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no peers available");
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no inbound tunnels found");
 | 
			
		||||
	}	
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::RecreateOutboundTunnel (std::shared_ptr<OutboundTunnel> tunnel)
 | 
			
		||||
	{
 | 
			
		||||
		auto inboundTunnel = GetNextInboundTunnel ();
 | 
			
		||||
		if (!inboundTunnel)
 | 
			
		||||
			inboundTunnel = tunnels.GetNextInboundTunnel ();
 | 
			
		||||
		if (inboundTunnel)
 | 
			
		||||
		{	
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel...");
 | 
			
		||||
			std::shared_ptr<TunnelConfig> config;
 | 
			
		||||
			if (m_NumOutboundHops > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -523,10 +527,10 @@ namespace tunnel
 | 
			
		|||
			newTunnel->SetTunnelPool (shared_from_this ());
 | 
			
		||||
			if (newTunnel->IsEstablished ()) // zero hops
 | 
			
		||||
				TunnelCreated (newTunnel);
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found");
 | 
			
		||||
	}		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -535,7 +539,7 @@ namespace tunnel
 | 
			
		|||
		tunnel->SetTunnelPool (shared_from_this ());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TunnelPool::SetCustomPeerSelector(TunnelPeerSelector selector)
 | 
			
		||||
	void TunnelPool::SetCustomPeerSelector(ITunnelPeerSelector * selector)
 | 
			
		||||
	{
 | 
			
		||||
		std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
 | 
			
		||||
		m_CustomPeerSelector = selector;
 | 
			
		||||
| 
						 | 
				
			
			@ -567,7 +571,7 @@ namespace tunnel
 | 
			
		|||
		}
 | 
			
		||||
		return tun;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<OutboundTunnel> TunnelPool::GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude) const
 | 
			
		||||
	{
 | 
			
		||||
		std::shared_ptr<OutboundTunnel> tun = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										45
									
								
								TunnelPool.h
									
										
									
									
									
								
							
							
						
						
									
										45
									
								
								TunnelPool.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -30,25 +30,29 @@ namespace tunnel
 | 
			
		|||
		eBuildResultTimeout // tunnel build timed out
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
  typedef std::shared_ptr<const i2p::data::IdentityEx> Peer;
 | 
			
		||||
  typedef std::vector<Peer> Path;
 | 
			
		||||
 | 
			
		||||
	/** interface for custom tunnel peer selection algorithm */
 | 
			
		||||
	struct ITunnelPeerSelector
 | 
			
		||||
	{
 | 
			
		||||
		typedef std::shared_ptr<const i2p::data::IdentityEx> Peer;
 | 
			
		||||
		typedef std::vector<Peer> TunnelPath;
 | 
			
		||||
		
 | 
			
		||||
		virtual bool SelectPeers(TunnelPath & peers, int hops, bool isInbound) = 0;
 | 
			
		||||
		virtual bool OnBuildResult(TunnelPath & peers, bool isInbound, TunnelBuildResult result) = 0;
 | 
			
		||||
    virtual ~ITunnelPeerSelector() {};
 | 
			
		||||
		virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0;
 | 
			
		||||
		virtual bool OnBuildResult(const Path & peers, bool isInbound, TunnelBuildResult result) = 0;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	typedef std::shared_ptr<ITunnelPeerSelector> TunnelPeerSelector;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>)> SelectHopFunc;
 | 
			
		||||
  // standard peer selection algorithm
 | 
			
		||||
  bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop);
 | 
			
		||||
 | 
			
		||||
	class TunnelPool: public std::enable_shared_from_this<TunnelPool> // per local destination
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels);
 | 
			
		||||
			~TunnelPool ();
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<i2p::garlic::GarlicDestination> GetLocalDestination () const { return m_LocalDestination; };
 | 
			
		||||
			void SetLocalDestination (std::shared_ptr<i2p::garlic::GarlicDestination> destination) { m_LocalDestination = destination; };
 | 
			
		||||
			void SetExplicitPeers (std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers);
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +66,7 @@ namespace tunnel
 | 
			
		|||
			void RecreateOutboundTunnel (std::shared_ptr<OutboundTunnel> tunnel);
 | 
			
		||||
			std::vector<std::shared_ptr<InboundTunnel> > GetInboundTunnels (int num) const;
 | 
			
		||||
			std::shared_ptr<OutboundTunnel> GetNextOutboundTunnel (std::shared_ptr<OutboundTunnel> excluded = nullptr) const;
 | 
			
		||||
			std::shared_ptr<InboundTunnel> GetNextInboundTunnel (std::shared_ptr<InboundTunnel> excluded = nullptr) const;		
 | 
			
		||||
			std::shared_ptr<InboundTunnel> GetNextInboundTunnel (std::shared_ptr<InboundTunnel> excluded = nullptr) const;
 | 
			
		||||
			std::shared_ptr<OutboundTunnel> GetNewOutboundTunnel (std::shared_ptr<OutboundTunnel> old) const;
 | 
			
		||||
			void TestTunnels ();
 | 
			
		||||
			void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +79,7 @@ namespace tunnel
 | 
			
		|||
			int GetNumInboundTunnels () const { return m_NumInboundTunnels; };
 | 
			
		||||
			int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; };
 | 
			
		||||
 | 
			
		||||
			void SetCustomPeerSelector(TunnelPeerSelector selector);
 | 
			
		||||
			void SetCustomPeerSelector(ITunnelPeerSelector * selector);
 | 
			
		||||
			void UnsetCustomPeerSelector();
 | 
			
		||||
			bool HasCustomPeerSelector();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -90,23 +94,25 @@ namespace tunnel
 | 
			
		|||
		std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude=nullptr) const;
 | 
			
		||||
 | 
			
		||||
		void OnTunnelBuildResult(std::shared_ptr<Tunnel> tunnel, TunnelBuildResult result);
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
    // for overriding tunnel peer selection
 | 
			
		||||
    std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
			
 | 
			
		||||
			void CreateInboundTunnel ();	
 | 
			
		||||
 | 
			
		||||
			void CreateInboundTunnel ();
 | 
			
		||||
			void CreateOutboundTunnel ();
 | 
			
		||||
			void CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel);
 | 
			
		||||
			template<class TTunnels>
 | 
			
		||||
			typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const;
 | 
			
		||||
			std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
 | 
			
		||||
			bool SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& hops, bool isInbound);
 | 
			
		||||
			bool SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& hops, bool isInbound);			
 | 
			
		||||
			bool SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& hops, bool isInbound);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<i2p::garlic::GarlicDestination> m_LocalDestination;
 | 
			
		||||
			int m_NumInboundHops, m_NumOutboundHops, m_NumInboundTunnels, m_NumOutboundTunnels;
 | 
			
		||||
			std::shared_ptr<std::vector<i2p::data::IdentHash> > m_ExplicitPeers;	
 | 
			
		||||
			std::shared_ptr<std::vector<i2p::data::IdentHash> > m_ExplicitPeers;
 | 
			
		||||
			mutable std::mutex m_InboundTunnelsMutex;
 | 
			
		||||
			std::set<std::shared_ptr<InboundTunnel>, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
 | 
			
		||||
			mutable std::mutex m_OutboundTunnelsMutex;
 | 
			
		||||
| 
						 | 
				
			
			@ -115,20 +121,19 @@ namespace tunnel
 | 
			
		|||
			std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
 | 
			
		||||
			bool m_IsActive;
 | 
			
		||||
			std::mutex m_CustomPeerSelectorMutex;
 | 
			
		||||
			TunnelPeerSelector m_CustomPeerSelector;
 | 
			
		||||
			ITunnelPeerSelector * m_CustomPeerSelector;
 | 
			
		||||
 | 
			
		||||
		uint64_t m_MinLatency=0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
 | 
			
		||||
		uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			// for HTTP only
 | 
			
		||||
			const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; };
 | 
			
		||||
			const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; };
 | 
			
		||||
 | 
			
		||||
	};	
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ set (LIBI2PD_SRC
 | 
			
		|||
  "${CMAKE_SOURCE_DIR}/FS.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Log.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/NTCPSession.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/NetDbRequests.cpp"	
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/NetDbRequests.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/NetDb.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Profiling.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Reseed.cpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ set (LIBI2PD_SRC
 | 
			
		|||
  "${CMAKE_SOURCE_DIR}/SSUData.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/SSUSession.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Streaming.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Destination.cpp"	
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Destination.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/TransitTunnel.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Tunnel.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/TunnelGateway.cpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -59,16 +59,16 @@ set (LIBI2PD_SRC
 | 
			
		|||
  "${CMAKE_SOURCE_DIR}/Datagram.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Family.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Signature.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Timestamp.cpp"	
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Timestamp.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/api.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Event.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Gost.cpp"	
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/Gost.cpp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if (WITH_WEBSOCKETS)
 | 
			
		||||
  add_definitions(-DWITH_EVENTS)
 | 
			
		||||
  find_package(websocketpp REQUIRED)
 | 
			
		||||
endif ()  
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS)
 | 
			
		||||
  list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
 | 
			
		||||
| 
						 | 
				
			
			@ -90,8 +90,9 @@ install(TARGETS libi2pd
 | 
			
		|||
 | 
			
		||||
set (CLIENT_SRC
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/AddressBook.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/BOB.cpp"	
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/BOB.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/ClientContext.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/MatchedDestination.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/I2PTunnel.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/I2PService.cpp"
 | 
			
		||||
  "${CMAKE_SOURCE_DIR}/SAM.cpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -357,7 +358,7 @@ include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_
 | 
			
		|||
# warn if for meshnet
 | 
			
		||||
if (WITH_MESHNET)
 | 
			
		||||
  message(STATUS "Building for testnet")
 | 
			
		||||
  message(WARNING "This build will NOT work on mainline i2p")  
 | 
			
		||||
  message(WARNING "This build will NOT work on mainline i2p")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,9 @@ LIB_SRC = \
 | 
			
		|||
  Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Event.cpp Gost.cpp
 | 
			
		||||
 | 
			
		||||
LIB_CLIENT_SRC = \
 | 
			
		||||
	AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \
 | 
			
		||||
	AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp MatchedDestination.cpp \
 | 
			
		||||
	SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp WebSocks.cpp
 | 
			
		||||
 | 
			
		||||
# also: Daemon{Linux,Win32}.cpp will be added later
 | 
			
		||||
DAEMON_SRC = \
 | 
			
		||||
	HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue