public abstract class TunnelPeerSelector extends ConnectChecker
| Modifier and Type | Class and Description |
|---|---|
protected class | TunnelPeerSelector.ExcluderExcluder that automatically adds peers to the set when they should be excluded. |
| Modifier and Type | Field and Description |
|---|---|
protected static Map<Hash,Long> | _firstHopFailsTracks when a peer last failed as first hop |
protected static Map<Hash,Long> | _peerCooldownsShared cooldown map across all peer selectors |
protected static Map<Hash,Long> | _provenRespondersPeers whose most recent tunnel participation succeeded, mapped to the
time of that success. |
protected static double | ATTACK_THRESHOLDThreshold for detecting tunnel build attacks |
protected static double | DEGRADED_BUILD_THRESHOLDBuild success at or below this widens the activity window to counter the
purgatory band (40-79% success) where the recency gate prunes good peers
faster than they can be re-tested, tightening the eligible pool in a
self-reinforcing loop. |
protected static int | FAILURE_MAP_MAX_SIZESize bound for the cooldown maps ( _peerCooldowns,
_firstHopFails, ExploratoryPeerSelector._exploratoryCooldowns). |
protected static long | FIRST_HOP_FAIL_COOLDOWN_MSPeers that failed as first hop (first hop unreachable) excluded for this long |
protected static long | PEER_SELECTION_COOLDOWN_MSPeers selected within this window are excluded from further selection to ensure diversity |
protected static long | PROVEN_RESPONDER_WINDOW_MSRecency window for proven-responder proof |
protected static long | STARTUP_WARNING_SUPPRESS_MSDuration in ms to suppress startup warnings |
ANY_V4, ctx, log| Modifier | Constructor and Description |
|---|---|
protected | TunnelPeerSelector(RouterContext context)TunnelPeerSelector. |
| Modifier and Type | Method and Description |
|---|---|
protected static int | addFreshCooldownExclusions(Map<Hash,Long> cooldowns,
long cutoff,
Set<Hash> exclude)Add cooldown entries still inside their window (value > cutoff) to the
exclusion set without mutating the map; returns the count added. |
protected boolean | allowAsIBGW(Hash h)Should we allow as IBGW?
This just checks for the "R" capability and IPv4 support. |
protected boolean | allowAsOBEP(Hash h)Should we allow as OBEP?
This just checks for IPv4 support. |
(package private) static boolean | allowFirewalledUnderAttack(String capabilities,
double buildSuccess)Should we allow a firewalled (U-cap) peer?
During attacks (build success below ATTACK_THRESHOLD), allow
U-cap peers that also publish M, N, O, P, or X capability. |
protected boolean | checkTunnel(boolean isInbound,
boolean isExploratory,
List<Hash> tunnel)Connectivity check. |
(package private) static int | compareProven(long t1,
long t2,
long now)Proven-responder comparison for the quality cascade: a peer whose last
tunnel participation succeeded within the recency window sorts before
one without; two peers on the same side compare equal so later cascade
stages decide. |
(package private) static int | countKnownCaps(String cap)Count the meaningful capabilities a peer publishes, used to reject
peers with no useful caps when there are plenty of fast peers. |
protected boolean | filterSlow(boolean isInbound,
boolean isExploratory)Whether to skip peers that are slow. |
protected static String | formatExcludedPeers(Set<Hash> peers)Format a set of excluded peers for logging, with exclusion reasons when
the set is an TunnelPeerSelector.Excluder or ExcluderBase. |
static long | getActivityWindow(RouterContext ctx)Compute the activity window for peer selection based on current network
visibility. |
static long | getActivityWindow(RouterContext ctx,
double buildSuccess)Compute the activity window for peer selection based on current network
visibility. |
(package private) static double | getBuildSuccess(RouterContext ctx)Current tunnel build success ratio, 1.0 when no data is available. |
protected Set<Hash> | getClosestHopExclude(boolean isInbound,
Set<Hash> toAdd)Pick peers that we want to avoid for the first OB hop or last IB hop. |
protected Set<Hash> | getExclude(boolean isInbound,
boolean isExploratory)As of 0.9.58, this returns a set populated only by TunnelManager.selectPeersInTooManyTunnels(),
for passing to ProfileOrganizer. |
protected int | getLength(TunnelPoolSettings settings)Determine the tunnel length (number of hops). |
protected static Set<Hash> | getPeersInPool(RouterContext ctx,
TunnelPool pool)All non-self peers in active tunnels of the given pool. |
static int | getWindowMultiplier()Current Tuner-controlled activity-window multiplier. |
(package private) static boolean | hasConnectivitySignal(PeerProfile profile,
long now,
long activityWindow)Pre-qualification signal check: does the peer profile show recent
connectivity evidence? Heard from or successfully sent to within the
last 30 minutes, a successful tunnel test within the activity window,
or any test history at all with a >50% acceptance ratio. |
protected static boolean | hasRecoveredFromFailure(RouterContext ctx,
Hash peer)Check if a peer has recovered from failure and can be reconsidered. |
protected static boolean | hasTunnelLongerThanOne(TunnelPool pool)True if the pool has at least one active tunnel longer than one hop. |
protected static boolean | hasValidTransportAddress(RouterContext ctx,
Hash peer)Check if a peer's RouterInfo has at least one reachable SSU or NTCP address. |
protected boolean | isDuplicateSequence(TunnelPoolSettings settings,
List<Hash> newPeers)Check if the selected peer sequence matches an existing tunnel in the pool. |
static boolean | isFirstHopFailing(RouterContext ctx,
Hash peer)Check if a peer recently failed as first hop and should be excluded. |
protected boolean | isInStartupGracePeriod()Convenience instance method wrapping the static helper. |
protected static boolean | isInStartupGracePeriod(RouterContext ctx)Is the router in the startup grace period?
During startup, peers haven't accumulated test history yet, so
quality filters (pre-qualification, tier capping) should be relaxed
to allow tunnels to build. |
protected boolean | isIPv6Only()Are we IPv6 only? |
protected static boolean | isLowAcceptanceRatio(RouterContext ctx,
Hash peer)Check if a peer has a history of rejecting tunnel build requests. |
(package private) static boolean | isOutdatedVersion(String version)True if the peer runs a version too old to interoperate: not the
published version and older than MIN_VERSION. |
(package private) static boolean | isProvenResponder(long lastJoin,
long now)Whether a proven-join timestamp falls inside the recency window. |
(package private) static boolean | isStalePeer(RouterContext ctx,
Hash peer)Check whether a peer is stale — no contact (heard from or heard about)
within the dynamic activity window. |
(package private) static boolean | isStalePeer(RouterContext ctx,
Hash peer,
double buildSuccess)Check whether a peer is stale — no contact (heard from or heard about)
within the dynamic activity window. |
(package private) static boolean | isUsableRouterAddress(RouterAddress ra)Is the RouterAddress usable for tunnel building? SSU requires
protocol v2 plus a valid IP/port or an introduction; SSU2 requires a
valid IP/port or an introduction; NTCP/NTCP2 require a valid IP/port. |
protected static boolean | isZeroHopSettings(TunnelPoolSettings settings)True if the settings describe a zero-hop pair: length <= 0, length
override == 0, or length + variance <= 0. |
static void | keepAlive(RouterContext ctx,
boolean aggressive)Periodically called to keep transport sessions alive for top-tier peers and
proactively establish connections to Fast/HighCap peers before builds need them. |
(package private) static boolean | matchesExistingTunnel(TunnelInfo existing,
List<Hash> newPeers,
boolean isInbound)Compare a newly selected peer sequence (excluding self) against one
existing tunnel. |
protected void | orderPeers(List<Hash> rv,
SessionKey key)Order peers using the given key. |
protected static void | preConnectTo(RouterContext ctx,
Hash peer)Trigger an outbound connection establishment to a peer. |
protected static void | prunePeerMaps(RouterContext ctx)Prune expired entries from static peer maps. |
protected static void | recordFirstHopFail(RouterContext ctx,
Hash peer)Record that a peer failed as first hop (first hop unreachable). |
protected static void | recordPeerFailure(RouterContext ctx,
Hash peer)Record that a peer failed during peer selection (first-hop or adjacent). |
protected List<Hash> | regeneratePeers(TunnelPoolSettings settings,
List<Hash> peers,
int attempt)Regenerate tunnel peers to avoid duplicate sequence. |
(package private) static String | relaxedExcludeCaps(String configured,
double buildSuccess,
long uptimeMs)Strip the M, N, O, D, P capability exclusions from the configured caps
when the build success ratio is below ATTACK_THRESHOLD or the
router is within its first STARTUP_WARNING_SUPPRESS_MS of
uptime (when the ratio is not yet meaningful). |
protected List<Hash> | selectExplicit(TunnelPoolSettings settings,
int length)For debugging, also possibly for restricted routes. |
abstract List<Hash> | selectPeers(TunnelPoolSettings settings)Which peers should go into the next tunnel for the given settings? |
static void | setWindowMultiplier(int mult)Tuner-controlled activity-window multiplier, clamped to [1, 8]. |
static boolean | shouldExclude(RouterContext ctx,
RouterInfo peer)Should the peer be excluded based on its published caps, crypto, and version? |
static boolean | shouldExclude(RouterContext ctx,
RouterInfo peer,
double buildSuccess)Should the peer be excluded based on its published caps, crypto, and version? |
protected boolean | shouldSelectExplicit(TunnelPoolSettings settings)For debugging, also possibly for restricted routes?
Needs analysis and testing |
protected static boolean | supportsNTCP2(RouterContext ctx,
Hash peer)Check if a peer supports NTCP2 transport. |
canConnect, canConnect, canConnect, getInboundMask, getOutboundMask, isNTCPDisabled, isSSUDisabledprotected static final Map<Hash,Long> _firstHopFails
protected static final Map<Hash,Long> _peerCooldowns
protected static final Map<Hash,Long> _provenResponders
ClientPeerSelector.compareQuality; entries older than
PROVEN_RESPONDER_WINDOW_MS carry no weight and are pruned.protected static final double ATTACK_THRESHOLD
protected static final double DEGRADED_BUILD_THRESHOLD
ATTACK_THRESHOLD because
relaxing recency is far safer than relaxing capability exclusions.protected static final int FAILURE_MAP_MAX_SIZE
_peerCooldowns,
_firstHopFails, ExploratoryPeerSelector._exploratoryCooldowns).
Entries are recorded on selection failures, tunnel rejects, and tunnel
reuse. They expire lazily (read-time filtering during selection) and
are bulk-pruned only when a map exceeds this bound, so these maps stay
small — 128 entries is already generous. This bound only limits
growth between selections; it does not evict live entries.protected static final long FIRST_HOP_FAIL_COOLDOWN_MS
protected static final long PEER_SELECTION_COOLDOWN_MS
protected static final long PROVEN_RESPONDER_WINDOW_MS
protected static final long STARTUP_WARNING_SUPPRESS_MS
protected TunnelPeerSelector(RouterContext context)
protected static int addFreshCooldownExclusions(Map<Hash,Long> cooldowns, long cutoff, Set<Hash> exclude)
_peerCooldowns for client pools, the exploratory map for
exploratory selections).cooldowns - the cooldown map to scan (never mutated)cutoff - entries with value <= cutoff are expired and skippedexclude - the exclusion set to add fresh entries toprotected boolean allowAsIBGW(Hash h)
h - the peer hashprotected boolean allowAsOBEP(Hash h)
h - the peer hashstatic boolean allowFirewalledUnderAttack(String capabilities, double buildSuccess)
ATTACK_THRESHOLD), allow
U-cap peers that also publish M, N, O, P, or X capability. Peers
without the U cap are always allowed. Pure decision — no context
access, safe for unit tests.capabilities - the peer's capability string, possibly nullbuildSuccess - the build success ratio, fetched once per selectionprotected boolean checkTunnel(boolean isInbound,
boolean isExploratory,
List<Hash> tunnel)isInbound - true for inbound tunnelsisExploratory - true for exploratory tunnelstunnel - ENDPOINT FIRST, GATEWAY LAST!!!!, length 2 or greaterstatic int compareProven(long t1,
long t2,
long now)t1 - last proven-join time of the first peer, 0 if nonet2 - last proven-join time of the second peer, 0 if nonenow - current time from the router clockstatic int countKnownCaps(String cap)
cap - the peer's capability stringprotected boolean filterSlow(boolean isInbound,
boolean isExploratory)isInbound - true for inbound tunnelsisExploratory - true for exploratory tunnelsprotected static String formatExcludedPeers(Set<Hash> peers)
TunnelPeerSelector.Excluder or ExcluderBase.public static long getActivityWindow(RouterContext ctx)
setWindowMultiplier(int)) and floored to at least 4 hours
when build success is in the degraded/purgatory band, so good peers whose
last successful test has aged out are re-admitted instead of pruned in a
self-reinforcing loop.ctx - the router contextpublic static long getActivityWindow(RouterContext ctx, double buildSuccess)
setWindowMultiplier(int)) and floored to at least 6 hours
when build success is in the degraded/purgatory band, so good peers whose
last successful test has aged out are re-admitted instead of pruned in a
self-reinforcing loop.ctx - the router contextbuildSuccess - the build success ratio, fetched once by the callerstatic double getBuildSuccess(RouterContext ctx)
Expensive: each call performs 6 RateStat lookups and 6 rate fetches
(ProfileOrganizer.getTunnelBuildSuccess()). Fetch once per
selection or scan and pass the value down; never call per candidate
peer. A value of 1.0 (no data) keeps the attack-threshold gates
closed at boot instead of treating missing stats as an attack.
ctx - the router contextprotected Set<Hash> getClosestHopExclude(boolean isInbound, Set<Hash> toAdd)
isInbound - true for inbound tunnelstoAdd - set of peers to initially populate the exclusion setprotected Set<Hash> getExclude(boolean isInbound, boolean isExploratory)
isInbound - true for inbound tunnelsisExploratory - true for exploratory tunnelsprotected int getLength(TunnelPoolSettings settings)
settings - the tunnel pool settingsprotected static Set<Hash> getPeersInPool(RouterContext ctx, TunnelPool pool)
ctx - the router contextpool - the tunnel pool to scanpublic static int getWindowMultiplier()
static boolean hasConnectivitySignal(PeerProfile profile, long now, long activityWindow)
profile - the peer profile (non-null)now - current time in millisecondsactivityWindow - the dynamic activity window in millisecondsprotected static boolean hasRecoveredFromFailure(RouterContext ctx, Hash peer)
ctx - the router contextpeer - the peerprotected static boolean hasTunnelLongerThanOne(TunnelPool pool)
pool - the tunnel pool to scan (non-null)protected static boolean hasValidTransportAddress(RouterContext ctx, Hash peer)
ctx - the router contextpeer - hash of the peer to checkprotected boolean isDuplicateSequence(TunnelPoolSettings settings, List<Hash> newPeers)
settings - the tunnel pool settingsnewPeers - the newly selected peers (excluding self)public static boolean isFirstHopFailing(RouterContext ctx, Hash peer)
ctx - the router contextpeer - the peerprotected boolean isInStartupGracePeriod()
protected static boolean isInStartupGracePeriod(RouterContext ctx)
ctx - the router contextprotected boolean isIPv6Only()
protected static boolean isLowAcceptanceRatio(RouterContext ctx, Hash peer)
ctx - the router contextpeer - hash of the peer to checkstatic boolean isOutdatedVersion(String version)
MIN_VERSION.
Pure — safe for unit tests.version - the peer's version stringstatic boolean isProvenResponder(long lastJoin,
long now)lastJoin - the last successful-participation time, 0 if nonenow - current time from the router clockstatic boolean isStalePeer(RouterContext ctx, Hash peer)
ctx - the router contextpeer - hash of the peer to checkstatic boolean isStalePeer(RouterContext ctx, Hash peer, double buildSuccess)
ctx - the router contextpeer - hash of the peer to checkbuildSuccess - the build success ratio, fetched once by the callerstatic boolean isUsableRouterAddress(RouterAddress ra)
ra - the router address to check (non-null)protected static boolean isZeroHopSettings(TunnelPoolSettings settings)
settings - the paired pool's settingspublic static void keepAlive(RouterContext ctx, boolean aggressive)
ctx - the router contextaggressive - if true, also pre-connect to non-established eligible peers
(used when any pool has 0 tunnels)static boolean matchesExistingTunnel(TunnelInfo existing, List<Hash> newPeers, boolean isInbound)
existing - the existing tunnel to compare againstnewPeers - the newly selected peers (excluding self)isInbound - true for inbound tunnelsprotected void orderPeers(List<Hash> rv, SessionKey key)
rv - the list to orderkey - the session key for orderingprotected static void preConnectTo(RouterContext ctx, Hash peer)
ctx - the router contextpeer - hash of the peer to connect toprotected static void prunePeerMaps(RouterContext ctx)
ctx - the router contextprotected static void recordFirstHopFail(RouterContext ctx, Hash peer)
ctx - the router contextpeer - the peerprotected static void recordPeerFailure(RouterContext ctx, Hash peer)
ctx - the router contextpeer - the peerprotected List<Hash> regeneratePeers(TunnelPoolSettings settings, List<Hash> peers, int attempt)
The canonical order is the key-distance sort from
orderPeers(java.util.List<net.i2p.data.Hash>, net.i2p.data.SessionKey). Because that sort is deterministic, regenerating
always reproduced the identical sequence and could not avoid
duplicates. Each regeneration attempt now rotates the canonical order
by a step derived from the pool key, so successive attempts yield
different sequences while staying key-derived (attacker-unpredictable).
settings - the tunnel pool settingspeers - the peers to regenerate (not modified)attempt - 1-based regeneration attempt numberstatic String relaxedExcludeCaps(String configured, double buildSuccess, long uptimeMs)
ATTACK_THRESHOLD or the
router is within its first STARTUP_WARNING_SUPPRESS_MS of
uptime (when the ratio is not yet meaningful). A ratio of 0.0 (no
data) relaxes as well, matching the conservative startup behavior.
Pure decision — no context access, safe for unit tests.configured - the configured exclude caps, possibly null or emptybuildSuccess - the build success ratio in [0.0, 1.0]uptimeMs - router uptime in millisecondsprotected List<Hash> selectExplicit(TunnelPoolSettings settings, int length)
settings - the tunnel pool settingslength - the desired length of the tunnelpublic abstract List<Hash> selectPeers(TunnelPoolSettings settings)
settings - the tunnel pool settingspublic static void setWindowMultiplier(int mult)
mult - the multiplier applied to the base activity windowpublic static boolean shouldExclude(RouterContext ctx, RouterInfo peer)
ctx - Router context for peer count checkspeer - The peer to evaluatepublic static boolean shouldExclude(RouterContext ctx, RouterInfo peer, double buildSuccess)
Variant for per-peer selection loops that already fetched the build success ratio once; avoids re-reading router statistics per peer.
ctx - Router context for peer count checkspeer - The peer to evaluatebuildSuccess - the build success ratio in [0.0, 1.0]protected boolean shouldSelectExplicit(TunnelPoolSettings settings)
settings - the tunnel pool settingsprotected static boolean supportsNTCP2(RouterContext ctx, Hash peer)
ctx - the router contextpeer - hash of the peer to check