mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 08:30: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,6 +10,7 @@
 | 
				
			||||||
#include "ClientContext.h"
 | 
					#include "ClientContext.h"
 | 
				
			||||||
#include "SOCKS.h"
 | 
					#include "SOCKS.h"
 | 
				
			||||||
#include "WebSocks.h"
 | 
					#include "WebSocks.h"
 | 
				
			||||||
 | 
					#include "MatchedDestination.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace i2p
 | 
					namespace i2p
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -308,7 +309,7 @@ namespace client
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType,
 | 
						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);
 | 
							i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
 | 
				
			||||||
		auto localDestination = std::make_shared<ClientDestination> (keys, isPublic, params);
 | 
							auto localDestination = std::make_shared<ClientDestination> (keys, isPublic, params);
 | 
				
			||||||
| 
						 | 
					@ -318,6 +319,16 @@ namespace client
 | 
				
			||||||
		return localDestination;
 | 
							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)
 | 
						void ClientContext::DeleteLocalDestination (std::shared_ptr<ClientDestination> destination)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!destination) return;
 | 
							if (!destination) return;
 | 
				
			||||||
| 
						 | 
					@ -440,6 +451,7 @@ namespace client
 | 
				
			||||||
						dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
 | 
											dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
 | 
				
			||||||
					int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
 | 
										int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
 | 
				
			||||||
					// optional params
 | 
										// 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 keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "");
 | 
				
			||||||
					std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
 | 
										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);
 | 
										int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
 | 
				
			||||||
| 
						 | 
					@ -456,9 +468,15 @@ namespace client
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
 | 
												localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
 | 
				
			||||||
							if (!localDestination)
 | 
												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) {
 | 
										if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
 | 
				
			||||||
						// udp client
 | 
											// udp client
 | 
				
			||||||
						// TODO: hostnames
 | 
											// TODO: hostnames
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,7 @@ namespace client
 | 
				
			||||||
	const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
 | 
						const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
 | 
				
			||||||
	const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
 | 
						const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
 | 
				
			||||||
	const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
 | 
						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[] = "host";
 | 
				
			||||||
	const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
 | 
						const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
 | 
				
			||||||
	const char I2P_SERVER_TUNNEL_PORT[] = "port";
 | 
						const char I2P_SERVER_TUNNEL_PORT[] = "port";
 | 
				
			||||||
| 
						 | 
					@ -47,6 +48,7 @@ namespace client
 | 
				
			||||||
	const char I2P_SERVER_TUNNEL_ADDRESS[] = "address";
 | 
						const char I2P_SERVER_TUNNEL_ADDRESS[] = "address";
 | 
				
			||||||
	const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal";
 | 
						const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class ClientContext
 | 
						class ClientContext
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
| 
						 | 
					@ -63,7 +65,8 @@ namespace client
 | 
				
			||||||
			std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1,
 | 
								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
 | 
								    const std::map<std::string, std::string> * params = nullptr); // transient
 | 
				
			||||||
			std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
 | 
								std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
 | 
				
			||||||
				const std::map<std::string, std::string> * params = nullptr);
 | 
					                                                                    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);
 | 
								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);
 | 
								bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@ namespace datagram
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
 | 
					    DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
 | 
				
			||||||
			~DatagramDestination ();
 | 
								~DatagramDestination ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    	void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
 | 
					    	void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
 | 
				
			||||||
| 
						 | 
					@ -147,4 +147,3 @@ namespace datagram
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,8 +175,8 @@ namespace client
 | 
				
			||||||
			ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
 | 
								ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
 | 
				
			||||||
			~ClientDestination ();
 | 
								~ClientDestination ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool Start ();
 | 
								virtual bool Start ();
 | 
				
			||||||
			bool Stop ();
 | 
								virtual bool Stop ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
 | 
								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); };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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
 | 
				
			||||||
| 
						 | 
					@ -372,20 +372,8 @@ namespace tunnel
 | 
				
			||||||
		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(i2p::transport::transports.RoutesRestricted())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -399,16 +387,16 @@ namespace tunnel
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto r = i2p::transport::transports.GetRandomPeer ();
 | 
								auto r = i2p::transport::transports.GetRandomPeer ();
 | 
				
			||||||
			if (r && !r->GetProfile ()->IsBad ())
 | 
								if (r && !r->GetProfile ()->IsBad ())
 | 
				
			||||||
			{
 | 
									{
 | 
				
			||||||
				prevHop = r;
 | 
										prevHop = r;
 | 
				
			||||||
				peers.push_back (r->GetRouterIdentity ());
 | 
										peers.push_back (r->GetRouterIdentity ());
 | 
				
			||||||
				numHops--;
 | 
										numHops--;
 | 
				
			||||||
			}
 | 
									}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for(int i = 0; i < numHops; i++ )
 | 
							for(int i = 0; i < numHops; i++ )
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto hop = SelectNextHop (prevHop);
 | 
								auto hop = nextHop (prevHop);
 | 
				
			||||||
			if (!hop)
 | 
								if (!hop)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
 | 
									LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
 | 
				
			||||||
| 
						 | 
					@ -420,6 +408,22 @@ namespace tunnel
 | 
				
			||||||
		return true;
 | 
							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)
 | 
						bool TunnelPool::SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int size = m_ExplicitPeers->size ();
 | 
							int size = m_ExplicitPeers->size ();
 | 
				
			||||||
| 
						 | 
					@ -535,7 +539,7 @@ namespace tunnel
 | 
				
			||||||
		tunnel->SetTunnelPool (shared_from_this ());
 | 
							tunnel->SetTunnelPool (shared_from_this ());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void TunnelPool::SetCustomPeerSelector(TunnelPeerSelector selector)
 | 
						void TunnelPool::SetCustomPeerSelector(ITunnelPeerSelector * selector)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
 | 
							std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
 | 
				
			||||||
		m_CustomPeerSelector = selector;
 | 
							m_CustomPeerSelector = selector;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										25
									
								
								TunnelPool.h
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								TunnelPool.h
									
										
									
									
									
								
							| 
						 | 
					@ -30,17 +30,21 @@ namespace tunnel
 | 
				
			||||||
		eBuildResultTimeout // tunnel build timed out
 | 
							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 */
 | 
						/** interface for custom tunnel peer selection algorithm */
 | 
				
			||||||
	struct ITunnelPeerSelector
 | 
						struct ITunnelPeerSelector
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		typedef std::shared_ptr<const i2p::data::IdentityEx> Peer;
 | 
					    virtual ~ITunnelPeerSelector() {};
 | 
				
			||||||
		typedef std::vector<Peer> TunnelPath;
 | 
							virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0;
 | 
				
			||||||
		
 | 
							virtual bool OnBuildResult(const Path & peers, bool isInbound, TunnelBuildResult result) = 0;
 | 
				
			||||||
		virtual bool SelectPeers(TunnelPath & peers, int hops, bool isInbound) = 0;
 | 
					 | 
				
			||||||
		virtual bool OnBuildResult(TunnelPath & 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
 | 
						class TunnelPool: public std::enable_shared_from_this<TunnelPool> // per local destination
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -75,7 +79,7 @@ namespace tunnel
 | 
				
			||||||
			int GetNumInboundTunnels () const { return m_NumInboundTunnels; };
 | 
								int GetNumInboundTunnels () const { return m_NumInboundTunnels; };
 | 
				
			||||||
			int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; };
 | 
								int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void SetCustomPeerSelector(TunnelPeerSelector selector);
 | 
								void SetCustomPeerSelector(ITunnelPeerSelector * selector);
 | 
				
			||||||
			void UnsetCustomPeerSelector();
 | 
								void UnsetCustomPeerSelector();
 | 
				
			||||||
			bool HasCustomPeerSelector();
 | 
								bool HasCustomPeerSelector();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,6 +95,9 @@ namespace tunnel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void OnTunnelBuildResult(std::shared_ptr<Tunnel> tunnel, TunnelBuildResult result);
 | 
							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:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void CreateInboundTunnel ();
 | 
								void CreateInboundTunnel ();
 | 
				
			||||||
| 
						 | 
					@ -98,7 +105,6 @@ namespace tunnel
 | 
				
			||||||
			void CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel);
 | 
								void CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel);
 | 
				
			||||||
			template<class TTunnels>
 | 
								template<class TTunnels>
 | 
				
			||||||
			typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const;
 | 
								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 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,7 +121,7 @@ namespace tunnel
 | 
				
			||||||
			std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
 | 
								std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
 | 
				
			||||||
			bool m_IsActive;
 | 
								bool m_IsActive;
 | 
				
			||||||
			std::mutex m_CustomPeerSelectorMutex;
 | 
								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_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
 | 
							uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
 | 
				
			||||||
| 
						 | 
					@ -131,4 +137,3 @@ namespace tunnel
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,6 +92,7 @@ set (CLIENT_SRC
 | 
				
			||||||
  "${CMAKE_SOURCE_DIR}/AddressBook.cpp"
 | 
					  "${CMAKE_SOURCE_DIR}/AddressBook.cpp"
 | 
				
			||||||
  "${CMAKE_SOURCE_DIR}/BOB.cpp"
 | 
					  "${CMAKE_SOURCE_DIR}/BOB.cpp"
 | 
				
			||||||
  "${CMAKE_SOURCE_DIR}/ClientContext.cpp"
 | 
					  "${CMAKE_SOURCE_DIR}/ClientContext.cpp"
 | 
				
			||||||
 | 
					  "${CMAKE_SOURCE_DIR}/MatchedDestination.cpp"
 | 
				
			||||||
  "${CMAKE_SOURCE_DIR}/I2PTunnel.cpp"
 | 
					  "${CMAKE_SOURCE_DIR}/I2PTunnel.cpp"
 | 
				
			||||||
  "${CMAKE_SOURCE_DIR}/I2PService.cpp"
 | 
					  "${CMAKE_SOURCE_DIR}/I2PService.cpp"
 | 
				
			||||||
  "${CMAKE_SOURCE_DIR}/SAM.cpp"
 | 
					  "${CMAKE_SOURCE_DIR}/SAM.cpp"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,10 +8,9 @@ LIB_SRC = \
 | 
				
			||||||
  Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Event.cpp Gost.cpp
 | 
					  Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Event.cpp Gost.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LIB_CLIENT_SRC = \
 | 
					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
 | 
						SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp WebSocks.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# also: Daemon{Linux,Win32}.cpp will be added later
 | 
					# also: Daemon{Linux,Win32}.cpp will be added later
 | 
				
			||||||
DAEMON_SRC = \
 | 
					DAEMON_SRC = \
 | 
				
			||||||
	HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp
 | 
						HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue