mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-08-28 00:44:42 +00:00
select first hop from connected peers based on peer ordering key
This commit is contained in:
+19
-1
@@ -16,6 +16,7 @@
|
||||
#include "I2PEndian.h"
|
||||
#include "Base.h"
|
||||
#include "Crypto.h"
|
||||
#include "Siphash.h"
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "I2NPProtocol.h"
|
||||
@@ -26,8 +27,8 @@
|
||||
#include "Garlic.h"
|
||||
#include "ECIESX25519AEADRatchetSession.h"
|
||||
#include "Config.h"
|
||||
#include "NetDb.hpp"
|
||||
#include "util.h"
|
||||
#include "NetDb.hpp"
|
||||
|
||||
using namespace i2p::transport;
|
||||
|
||||
@@ -1406,5 +1407,22 @@ namespace data
|
||||
if (r->GetBuffer ()) return true;
|
||||
return r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ()));
|
||||
}
|
||||
|
||||
int CalculatePeerOrderingGroup (i2p::data::Tag<16> key, const i2p::data::IdentHash& routerIdent)
|
||||
{
|
||||
uint8_t hash[16];
|
||||
#if OPENSSL_SIPHASH
|
||||
EVP_PKEY * sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, key, 16);
|
||||
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
|
||||
EVP_DigestSignInit (ctx, nullptr, nullptr, nullptr, sipKey);
|
||||
size_t l = 16;
|
||||
EVP_DigestSign (ctx, hash, &l, routerIdent, 32);
|
||||
EVP_MD_CTX_destroy (ctx);
|
||||
EVP_PKEY_free (sipKey);
|
||||
#else
|
||||
i2p::crypto::Siphash<16> (hash, routerIdent, 32, key);
|
||||
#endif
|
||||
return hash[0] & 0x03;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,6 +205,8 @@ namespace data
|
||||
};
|
||||
|
||||
extern NetDb netdb;
|
||||
|
||||
int CalculatePeerOrderingGroup (i2p::data::Tag<16> key, const i2p::data::IdentHash& routerIdent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+40
-26
@@ -1183,7 +1183,7 @@ namespace transport
|
||||
}
|
||||
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer (Filter filter) const
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer (Filter filter, i2p::data::Tag<16> * peerOrderingKey) const
|
||||
{
|
||||
std::vector<std::pair<i2p::data::IdentHash, std::shared_ptr<Peer>>> peers;
|
||||
{
|
||||
@@ -1203,13 +1203,17 @@ namespace transport
|
||||
inds[0] %= count;
|
||||
auto& [ident, peer] = peers[inds[0]];
|
||||
// try random peer
|
||||
if (filter (peer))
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL)
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
int peerOrderingGroup = peerOrderingKey ? i2p::data::CalculatePeerOrderingGroup (*peerOrderingKey, ident) : 0;
|
||||
if (!peerOrderingGroup && filter (peer))
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!found)
|
||||
{
|
||||
// try some peers around
|
||||
if (inds[0])
|
||||
@@ -1233,13 +1237,16 @@ namespace transport
|
||||
for (auto i = inds[1]; i < inds[2]; i++)
|
||||
{
|
||||
auto& [ident, peer] = peers[i];
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL &&
|
||||
filter (peer))
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL)
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
break;
|
||||
int peerOrderingGroup = peerOrderingKey ? i2p::data::CalculatePeerOrderingGroup (*peerOrderingKey, ident) : 0;
|
||||
if (!peerOrderingGroup && filter (peer))
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1249,13 +1256,16 @@ namespace transport
|
||||
for (auto i = 0; i < inds[1]; i++)
|
||||
{
|
||||
auto& [ident, peer] = peers[i];
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL &&
|
||||
filter (peer))
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL)
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
break;
|
||||
int peerOrderingGroup = peerOrderingKey ? i2p::data::CalculatePeerOrderingGroup (*peerOrderingKey, ident) : 0;
|
||||
if (!peerOrderingGroup && filter (peer))
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,13 +1275,16 @@ namespace transport
|
||||
for (auto i = inds[2]; i < peers.size (); i++)
|
||||
{
|
||||
auto& [ident, peer] = peers[i];
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL &&
|
||||
filter (peer))
|
||||
if (ts > peer->lastSelectionTime + PEER_SELECTION_MIN_INTERVAL)
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
break;
|
||||
int peerOrderingGroup = peerOrderingKey ? i2p::data::CalculatePeerOrderingGroup (*peerOrderingKey, ident) : 0;
|
||||
if (!peerOrderingGroup && filter (peer))
|
||||
{
|
||||
foundIdent = ident;
|
||||
peer->lastSelectionTime = ts;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1280,7 +1293,7 @@ namespace transport
|
||||
return found ? i2p::data::netdb.FindRouter (foundIdent) : nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer (bool isHighBandwidth) const
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer (bool isHighBandwidth, i2p::data::Tag<16> * peerOrderingKey) const
|
||||
{
|
||||
return GetRandomPeer (
|
||||
[isHighBandwidth, this](std::shared_ptr<const Peer> peer)->bool
|
||||
@@ -1304,7 +1317,8 @@ namespace transport
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
i2p::context.IsLimitedConnectivity () ? nullptr : peerOrderingKey);
|
||||
}
|
||||
|
||||
void Transports::RestrictRoutesToFamilies(const std::vector<std::string_view>& families)
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace transport
|
||||
uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; };
|
||||
int GetCongestionLevel (bool longTerm) const;
|
||||
size_t GetNumPeers () const { return m_Peers.size (); };
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth, i2p::data::Tag<16> * peerOrderingKey = nullptr) const;
|
||||
|
||||
/** get a trusted first hop for restricted routes */
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer();
|
||||
@@ -215,7 +215,7 @@ namespace transport
|
||||
void DetectExternalIP ();
|
||||
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (Filter filter) const;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (Filter filter, i2p::data::Tag<16> * peerOrderingKey) const;
|
||||
boost::asio::ip::address GetNetworkAddress (std::shared_ptr<TransportSession> session) const;
|
||||
boost::asio::ip::address GetNetworkAddress (const boost::asio::ip::address& addr) const;
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace tunnel
|
||||
if (m_OutboundVariance > 0 && m_NumOutboundHops + m_OutboundVariance > STANDARD_NUM_RECORDS)
|
||||
m_OutboundVariance = (m_NumOutboundHops < STANDARD_NUM_RECORDS) ? STANDARD_NUM_RECORDS - m_NumOutboundHops : 0;
|
||||
m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + m_Rng () % TUNNEL_POOL_MANAGE_INTERVAL;
|
||||
RAND_bytes (m_PeerOrderingKey, 16);
|
||||
}
|
||||
|
||||
TunnelPool::~TunnelPool ()
|
||||
@@ -611,7 +612,8 @@ namespace tunnel
|
||||
(inbound && (i2p::transport::transports.GetNumPeers () > 25 ||
|
||||
(i2p::context.IsLimitedConnectivity () && i2p::transport::transports.GetNumPeers () > 0))))
|
||||
{
|
||||
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ());
|
||||
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity (),
|
||||
&m_PeerOrderingKey);
|
||||
if (r && r->IsECIES () && (!r->HasProfile () || !r->GetProfile ()->IsBad ()) &&
|
||||
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
|
||||
{
|
||||
@@ -627,7 +629,7 @@ namespace tunnel
|
||||
if (!hop && !i) // if no suitable peer found for first hop, try already connected
|
||||
{
|
||||
LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected");
|
||||
hop = i2p::transport::transports.GetRandomPeer (false);
|
||||
hop = i2p::transport::transports.GetRandomPeer (false, &m_PeerOrderingKey);
|
||||
if (hop && !hop->IsECIES ()) hop = nullptr;
|
||||
}
|
||||
if (!hop)
|
||||
|
||||
@@ -153,6 +153,7 @@ namespace tunnel
|
||||
std::mutex m_CustomPeerSelectorMutex;
|
||||
ITunnelPeerSelector * m_CustomPeerSelector;
|
||||
std::mt19937 m_Rng; // for tunnel selection
|
||||
i2p::data::Tag<16> m_PeerOrderingKey;
|
||||
|
||||
int m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
|
||||
int m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
|
||||
|
||||
Reference in New Issue
Block a user