Nested Class Summary
Nested classes/interfaces inherited from class TunnelPeerSelector
TunnelPeerSelector.Excluder, TunnelPeerSelector.KeepAliveTally, TunnelPeerSelector.PreConnectOutcomeModifier and TypeClassDescriptionprotected classExcluder that automatically adds peers to the set when they should be excluded.(package private) static final classPer-cycle tally of why keepalive did not act on the peers it selected.(package private) static enumWhat a pre-connect probe actually achieved.Field Summary
FieldsModifier and TypeFieldDescriptionCooldown entries for exploratory selections, recorded when checkTunnel fails.private final ThreadLocal<Set<Hash>> Peers from the last selection that were all ghosts, handed to the redraw inselectPeers(TunnelPoolSettings).(package private) static final StringCounts selections discarded because every candidate was banlisted.private static final long[]Rate windows kept for the selector's stats.Fields inherited from class TunnelPeerSelector
_firstHopFails, _peerCooldowns, _provenResponders, ATTACK_RELAX_EXIT, ATTACK_THRESHOLD, FAILURE_MAP_MAX_SIZE, FIRST_HOP_FAIL_COOLDOWN_MS, MAX_WINDOW_MS, MIN_PROVEN_RESPONDER_COUNT, PEER_SELECTION_COOLDOWN_MS, PROVEN_RESPONDER_WINDOW_MS, QUALITY_RELAXED, QUALITY_STRICT, SCARCE_FAST_PEERS, STARTUP_WARNING_SUPPRESS_MS, WINDOW_MULTIPLIER_STATModifier and TypeFieldDescriptionTracks when a peer last failed as first hop.Shared cooldown map across all peer selectors.Peers whose most recent tunnel participation succeeded, mapped to the time of that success.(package private) static final doubleWhether the exclude caps are currently relaxed, and by how much build success has to recover before they are enforced again.protected static final doubleThreshold for detecting tunnel build attacks.protected static final intSize bound for the cooldown maps (TunnelPeerSelector._peerCooldowns,TunnelPeerSelector._firstHopFails,_exploratoryCooldowns).protected static final longPeers that failed as first hop (first hop unreachable) excluded for this long.static final longUpper bound on the activity window, applied after the multiplier.(package private) static final intMinimum proven-responder entries before cold-start seeding kicks in.protected static final longPeers selected within this window are excluded from further selection to ensure diversity.protected static final longRecency window for proven-responder proof.(package private) static final intMinimum evidence bar when builds are healthy.(package private) static final intMinimum evidence bar under stress: a live session or a recent successful tunnel test.static final intNumber of fast peers at or above which the peer set is considered well supplied and the activity window is never widened on availability grounds.protected static final longDuration in ms to suppress startup warnings.static final StringStat name for the live window multiplier.Fields inherited from class ConnectChecker
ANY_V4, ctx, logModifier and TypeFieldDescriptionstatic final intAny IPv4 transport.protected final RouterContextThe router context.protected final LogThe logger.Constructor Summary
ConstructorsConstructorDescriptionExploratoryPeerSelector(RouterContext context) Creates the selector over the given router context.Method Summary
Modifier and TypeMethodDescriptionprivate intUse current + last to get more recent and smoother data.private intWe should really use the difference between the exploratory fail rate and the high capacity fail rate - but we don't have a stat for high cap, so use the fast (== client) fail rate, it should be close if the expl.private intFailure rate of one tunnel type.private static intMinimum active peers for a normal selection.private static intMinimum active peers before the startup gate lifts.private static intMinimum share of pools that must be building.private static voidRecord a discarded selection, creating the stat on first use.selectPeers(TunnelPoolSettings settings) Returns ENDPOINT FIRST, GATEWAY LAST!!!! In: us ..selectPeersInternal(TunnelPoolSettings settings, int length, boolean includeCooldowns) The actual peer selection, shared between the normal path and the cooldown-bypass retry inselectPeers(TunnelPoolSettings).selectPeersInternal(TunnelPoolSettings settings, int length, boolean includeCooldowns, Set<Hash> alsoExclude) Select peers, additionally excluding a set the caller has decided on.private booleanShould we pick from the high cap pool instead of the larger not failing pool? This should return false most of the time, but if the not-failing pool's build success rate is much worse, return true so that reliability is maintained.Methods inherited from class TunnelPeerSelector
addFreshCooldownExclusions, allowAsIBGW, allowAsOBEP, allowFirewalledUnderAttack, applyProbeFailure, checkTunnel, compareProven, countKnownCaps, dropUnreliable, filterSlow, formatExcludedPeers, getActivityWindow, getActivityWindow, getBuildSuccess, getClosestHopExclude, getExclude, getLength, getMaxWindowMultiplier, getPeersInAllPools, getPeersInPool, getWindowMultiplier, hasConnectivitySignal, hasConnectivitySignal, hasRecoveredFromFailure, hasTunnelLongerThanOne, hasValidTransportAddress, hasValidTransportAddress, isDuplicateSequence, isFirstHopFailing, isInStartupGracePeriod, isInStartupGracePeriod, isIPv6Only, isLowAcceptanceRatio, isOutdatedVersion, isProvenResponder, isStalePeer, isStalePeer, isUsableRouterAddress, isZeroHopSettings, keepAlive, matchesExistingTunnel, noteFirstHopRtt, orderPeers, preConnectTo, preferProven, prunePeerMaps, publishWindowMultiplier, recordFirstHopFail, regeneratePeers, relaxedExcludeCaps, relaxedExcludeCaps, requiredSignalQuality, seedProvenResponders, selectExplicit, selectPeers, setWindowMultiplier, shouldExclude, shouldExclude, shouldPreQual, shouldSelectExplicit, supportsNTCP2, windowMultiplierFor, windowMultiplierForModifier and TypeMethodDescriptionprotected static intAdd cooldown entries still inside their window (value > cutoff) to the exclusion set without mutating the map.protected booleanallowAsIBGW(Hash h) Should we allow as IBGW? This just checks for the "R" capability and IPv4 support.protected booleanallowAsOBEP(Hash h) Should we allow as OBEP? This just checks for IPv4 support.(package private) static booleanallowFirewalledUnderAttack(String capabilities, double buildSuccess) Should we allow a firewalled (U-cap) peer? During attacks (build success belowTunnelPeerSelector.ATTACK_THRESHOLD), allow U-cap peers that also publish M, N, O, P, or X capability.(package private) static voidapplyProbeFailure(RouterContext ctx, Hash peer) Act on a pre-connect probe that could not be delivered.protected booleancheckTunnel(boolean isInbound, boolean isExploratory, List<Hash> tunnel) Connectivity check.(package private) static intcompareProven(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 intcountKnownCaps(String cap) Count the meaningful capabilities a peer publishes, used to reject peers with no useful caps when there are plenty of fast peers.(package private) static booleandropUnreliable(List<Hash> hops, Set<Hash> unreliable, int minKeep) Remove unreliable hops while at leastminKeepremain.protected booleanfilterSlow(boolean isInbound, boolean isExploratory) Whether to skip peers that are slow.protected static StringformatExcludedPeers(Set<Hash> peers) Format a set of excluded peers for logging, with exclusion reasons when the set is anTunnelPeerSelector.ExcluderorExcluderBase.static longCompute the activity window for peer selection from the base ladder only, scaled by whatever multiplier the availability gate has granted.static longgetActivityWindow(RouterContext ctx, double buildSuccess) Compute the activity window for peer selection based on current network visibility.(package private) static doubleCurrent tunnel build success ratio, 1.0 when no data is available.getClosestHopExclude(boolean isInbound, Set<Hash> toAdd) Pick peers that we want to avoid for the first OB hop or last IB hop.getExclude(boolean isInbound, boolean isExploratory) Create the exclusion set for this pool, for passing to ProfileOrganizer.protected intgetLength(TunnelPoolSettings settings) Determine the tunnel length (number of hops).static intCeiling forTunnelPeerSelector.getWindowMultiplier().All non-self peers in active tunnels across ALL pools (client IB/OB + exploratory IB/OB).getPeersInPool(RouterContext ctx, TunnelPool pool) All non-self peers in active tunnels of the given pool.static intCurrent Tuner-controlled activity-window multiplier.(package private) static booleanhasConnectivitySignal(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.(package private) static booleanhasConnectivitySignal(PeerProfile profile, long now, long activityWindow, boolean established, int quality) Pre-qualification signal check at the given strictness.protected static booleanhasRecoveredFromFailure(RouterContext ctx, Hash peer) Check if a peer has recovered from failure and can be reconsidered.protected static booleanTrue if the pool has at least one active tunnel longer than one hop.(package private) static booleanAddress half ofTunnelPeerSelector.hasValidTransportAddress(RouterContext, Hash), split out so a caller that already holds the RouterInfo does not have to probe the netdb a second time for the same entry.protected static booleanhasValidTransportAddress(RouterContext ctx, Hash peer) Check if a peer's RouterInfo has at least one reachable SSU or NTCP address.protected booleanisDuplicateSequence(TunnelPoolSettings settings, List<Hash> newPeers) Check if the selected peer sequence matches an existing tunnel in the pool.static booleanisFirstHopFailing(RouterContext ctx, Hash peer) Check if a peer recently failed as first hop and should be excluded.protected booleanConvenience instance method wrapping the static helper.static booleanIs 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 booleanAre we IPv6 only?protected static booleanisLowAcceptanceRatio(RouterContext ctx, Hash peer) Check if a peer has a history of rejecting tunnel build requests.(package private) static booleanisOutdatedVersion(String version) True if the peer runs a version too old to interoperate: not the published version and older thanTunnelPeerSelector.MIN_VERSION.(package private) static booleanisProvenResponder(long lastJoin, long now) Whether a proven-join timestamp falls inside the recency window.(package private) static booleanisStalePeer(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 booleanisStalePeer(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 booleanIs 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 booleanisZeroHopSettings(TunnelPoolSettings settings) True if the settings describe a zero-hop pair: length <= 0, length override == 0, or length + variance <= 0.static voidkeepAlive(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 booleanmatchesExistingTunnel(TunnelInfo existing, List<Hash> newPeers, boolean isInbound) Compare a newly selected peer sequence (excluding self) against one existing tunnel.(package private) static voidnoteFirstHopRtt(RouterContext ctx, Hash peer, Transport transport) Extract the transport's measured direct-link RTT and record it on the peer.protected voidorderPeers(List<Hash> rv, SessionKey key) Order peers using the given key.protected static TunnelPeerSelector.PreConnectOutcomepreConnectTo(RouterContext ctx, Hash peer) Send aDatabaseLookupMessageto a peer so it answers with our RouterInfo, which forces a full session handshake rather than the emptyDataMessagethat would leave the peer with nothing to reply to.(package private) static intpreferProven(List<Hash> hops, int from, int to, Map<Hash, Long> proof, long now, long window, Iterator<Hash> replacements) Replace hops lacking fresh proof with proven replacements, in order.protected static voidPrune expired entries from static peer maps.static voidPublish the current activity-window multiplier.protected static voidrecordFirstHopFail(RouterContext ctx, Hash peer) Record that a peer failed as first hop (first hop unreachable).regeneratePeers(TunnelPoolSettings settings, List<Hash> peers, int attempt) Regenerate tunnel peers to avoid duplicate sequence.(package private) static StringrelaxedExcludeCaps(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 belowTunnelPeerSelector.ATTACK_THRESHOLDor the router is within its firstTunnelPeerSelector.STARTUP_WARNING_SUPPRESS_MSof uptime (when the ratio is not yet meaningful).(package private) static StringrelaxedExcludeCaps(String configured, double buildSuccess, long uptimeMs, boolean alreadyRelaxed) Strip the M, N, O, D, P capability exclusions from the configured caps when the build success ratio is belowTunnelPeerSelector.ATTACK_THRESHOLDor the router is within its firstTunnelPeerSelector.STARTUP_WARNING_SUPPRESS_MSof uptime (when the ratio is not yet meaningful).(package private) static intrequiredSignalQuality(double buildSuccess) Which quality of connectivity evidence a candidate must show to be pre-qualified, as a function of how well tunnel building is going.(package private) static voidseedProvenResponders(RouterContext ctx, long now) Seed the proven-responder map with random peers from the router's peer profiles when the map is belowTunnelPeerSelector.MIN_PROVEN_RESPONDER_COUNT.selectExplicit(TunnelPoolSettings settings, int length) For debugging, also possibly for restricted routes.selectPeers(TunnelPoolSettings settings, Set<Hash> excludeFirstHops) Select peers for a new tunnel, with an optional set of first-hop peers to exclude from selection.static voidsetWindowMultiplier(int mult) Tuner-controlled activity-window multiplier, clamped to [1, 4] (TunnelPeerSelector.MIN_WINDOW_MULTIPLIER..TunnelPeerSelector.MAX_WINDOW_MULTIPLIER).static booleanshouldExclude(RouterContext ctx, RouterInfo peer) Should the peer be excluded based on its published caps, crypto, and version?static booleanshouldExclude(RouterContext ctx, RouterInfo peer, double buildSuccess) Should the peer be excluded based on its published caps, crypto, and version?(package private) static booleanshouldPreQual(boolean isExploratory, boolean inStartupGrace, double buildSuccess) Whether strict client-pool pre-qualification should be applied to a candidate peer.protected booleanshouldSelectExplicit(TunnelPoolSettings settings) For debugging, also possibly for restricted routes? Needs analysis and testing.protected static booleansupportsNTCP2(RouterContext ctx, Hash peer) Check if a peer supports NTCP2 transport.static intwindowMultiplierFor(int fastPeers, boolean startupGrace, int min, int max) Multiplier the peer-supply signal earns, independent of any build-outcome metric.static intTunnelPeerSelector.windowMultiplierFor(int, boolean, int, int)bound to the live router: reads the current fast-peer count and startup state.Methods inherited from class ConnectChecker
canConnect, canConnect, canConnect, getInboundMask, getOutboundMask, isNTCPDisabled, isSSUDisabledModifier and TypeMethodDescriptionbooleancanConnect(int ourMask, RouterInfo to) Can we connect to "to" based on published addresses?booleancanConnect(Hash from, Hash to) Can "from" connect to "to" based on published addresses?booleancanConnect(RouterInfo from, int ourMask) Can "from" connect to us based on published addresses?intOur inbound mask.intOur outbound mask.protected booleanIs NTCP disabled?protected booleanIs SSU disabled?
Field Details
EPS_ALL_BANNED_STAT
Counts selections discarded because every candidate was banlisted.Exists to keep the discard branch above honest. The change that replaced restoring the banned selection with discarding it was originally justified by a build-capacity figure that no measurement supported, and the branch then recorded 0 occurrences over roughly two hours. Rather than re-assert a benefit, this counter makes the frequency observable so the branch can be re-evaluated on evidence.
Must be created before use:
StatManager.addRateDataon an unregistered name silently drops the sample.- See Also:
EPS_STAT_RATES
private static final long[] EPS_STAT_RATESRate windows kept for the selector's stats._exploratoryCooldowns
Cooldown entries for exploratory selections, recorded when checkTunnel fails. Separate from the sharedTunnelPeerSelector._peerCooldownsso exploratory builds cannot pollute the set used by client pools. Only failures are recorded — healthy selections never cooldown peers._lastAllGhostSelection
Peers from the last selection that were all ghosts, handed to the redraw inselectPeers(TunnelPoolSettings).A field rather than a return value because the ghost filter sits deep inside
selectPeersInternal(TunnelPoolSettings, int, boolean)and the retry belongs beside the existing cooldown retry, in the one method that already sequences attempts. Per-thread: two selections in flight must not exchange the set they were told to avoid.
Constructor Details
ExploratoryPeerSelector
Creates the selector over the given router context.- Parameters:
context- the router context supplying peers and network state
Method Details
noteAllBannedDiscard
Record a discarded selection, creating the stat on first use.StatManager.addRateDatasilently drops samples for an unregistered name, so creation is not optional here. No "already created" guard is needed becausecreateRequiredRateStatis itself idempotent.- Parameters:
ctx- router context; null is ignored
selectPeers
Returns ENDPOINT FIRST, GATEWAY LAST!!!! In: us .. closest .. middle .. IBGW Out: OBGW .. middle .. closest .. us.- Specified by:
selectPeersin classTunnelPeerSelector- Parameters:
settings- the tunnel pool settings- Returns:
- ordered list of Hash objects (one per peer) specifying what order they should appear in a tunnel (ENDPOINT FIRST). This includes the local router in the list. Never null; an empty list means no peers could be selected.
selectPeersInternal
private List<Hash> selectPeersInternal(TunnelPoolSettings settings, int length, boolean includeCooldowns) The actual peer selection, shared between the normal path and the cooldown-bypass retry inselectPeers(TunnelPoolSettings).- Parameters:
settings- the tunnel pool settingslength- the desired tunnel lengthincludeCooldowns- whether to exclude peers on selection cooldown- Returns:
- ordered list of Hash objects (ENDPOINT FIRST), or null if no peers are available or checkTunnel fails
selectPeersInternal
private List<Hash> selectPeersInternal(TunnelPoolSettings settings, int length, boolean includeCooldowns, Set<Hash> alsoExclude) Select peers, additionally excluding a set the caller has decided on.Used for the ghost retry: the client pools exclude peers that turned out to be ghosts and redraw, so exploratory has to be able to do the same rather than restore a selection the peer measurements just rejected.
- Parameters:
settings- the tunnel pool settingslength- the desired tunnel lengthincludeCooldowns- whether to exclude peers on selection cooldownalsoExclude- peers to exclude on top of the usual set, or null- Returns:
- ordered list of Hash objects (ENDPOINT FIRST), or null if no peers are available or checkTunnel fails
getMinNonfailingPct
Minimum share of pools that must be building.- Parameters:
ctx- the router's context- Returns:
- the percentage, from the config
getMinActivePeersStartup
Minimum active peers before the startup gate lifts.- Parameters:
ctx- the router's context- Returns:
- the count, from the config
getMinActivePeers
Minimum active peers for a normal selection.- Parameters:
ctx- the router's context- Returns:
- the count, from the config
shouldPickHighCap
private boolean shouldPickHighCap()Should we pick from the high cap pool instead of the larger not failing pool? This should return false most of the time, but if the not-failing pool's build success rate is much worse, return true so that reliability is maintained.- Returns:
- whether pick high cap
getExploratoryFailPercentage
private int getExploratoryFailPercentage()We should really use the difference between the exploratory fail rate and the high capacity fail rate - but we don't have a stat for high cap, so use the fast (== client) fail rate, it should be close if the expl. and client tunnel lengths aren't too different. So calculate the difference between the exploratory fail rate and the client fail rate, normalized to 100: 100 * ((Efail - Cfail) / (100 - Cfail)) Even this isn't the "true" rate for the NonFailingPeers pool, since we are often building exploratory tunnels using the HighCapacity pool.- Returns:
- the exploratory fail percentage
getFailPercentage
Failure rate of one tunnel type.- Parameters:
t- the tunnel type's name- Returns:
- the failure percentage
getEvents
Use current + last to get more recent and smoother data.- Parameters:
stat- the full stat name, e.g.tunnel.buildExpireperiod- the rate period in milliseconds- Returns:
- the event count for that period, 0 if the stat or rate is unknown