Warning - most methods taking a key as an argument require the routing key, not the original key.
Nested Class Summary
Modifier and TypeClassDescriptionprivate classCollector picking the closest floodfills.static enumClassification result for floodfill peer selection.Field Summary
FieldsModifier and TypeFieldDescriptionprivate BanLoggerRecords why floodfills were banned.private static booleanCached ban setting for unresponsive floodfills.private static RouterContextContext the cached config values were read from.private static longWhen the config values were last refreshed.private final KademliaNetworkDatabaseFacadeThe floodfill's own database facade.private final RateStat[]Rate stat slots for the failed lookups.private final RateStat[]Rate stat slots for the test success times.private static final longInterval between config refreshes.private static final longAge after which a floodfill counts as recently heard about.private static final intResponse time still counted as good, in ms.private static final longFloodfills withRouterInfopublished longer ago than this are skipped.private static final intAge a lookup counts as good with no failures.private static final intThis must be longer than the max streaming timeout (60s).private static final intAge a no-fail floodfill counts as good.private static final intAge a no-fail floodfill counts as OK.private static final intByte count matched when fingerprinting a peer for same-subnet exclusion: /16 for IPv4, /32 for IPv6, mirroring the historicMaskedIPSet(_context, entry, info, 2)call.private static final longGrace period after router startup before enforcing HEARD_AGE.Fields inherited from class PeerSelector
_context, _logConstructor Summary
ConstructorsConstructorDescriptionBinds the facade and prepares the ban logger.Method Summary
Modifier and TypeMethodDescription(package private) static booleanaddSameIPFingerprint(Set<Long> maskedIPs, Set<Integer> ports, Set<String> families, RouterContext ctx, Hash peer, RouterInfo pinfo, int mask) Fingerprint a candidate peer into the exclusion accumulators, adding compact masked-IP keys, ports, and the claimed family option.private voidbanAndDisconnect(Hash entry, RouterInfo info, String banReason, String logReason, String disconnectReason, long banDuration, long logDuration, long now) Ban, log, and disconnect from a floodfill peer, with separate texts for the banlist, the ban log, and the disconnect reason.buildFloodfillCandidates(Set<Hash> toIgnore) Build the floodfill candidate list with only the cheap per-peer checks: the exclusion set, the two banlist tiers, and the unreachable capability flag.private FloodfillPeerSelector.PeerClassclassifyFloodfillPeer(Hash entry, RouterInfo info, boolean sameIP, long now, boolean enforceHeard, double maxFailRate) Classify a single floodfill peer as GOOD, OK, or BAD for selection.classifyFloodfillPeerForDisplay(Hash entry, RouterInfo info, long now) Classify a floodfill peer for display purposes.private doublecomputeMaxFailRate(long uptime) Compute the maximum acceptable failure rate for a floodfill peer, based on the network average over the last 10 minutes.private static booleanReads the unresponsive floodfill ban setting.private StringExtract IP:port from RouterInfo.private RateStatgetRateStat(RateStat[] slot, String name) Get the RateStat handle, caching it in the slot for subsequent calls.private voidLog the classification results at debug level.(package private) static longmaskedIPKey(byte[] ip, int mask) Compact long fingerprint of a masked IP, replacing the per-candidate String construction (one StringBuilder plus up to 2*mask heap chars) that the historicMaskedIPSet.maskedIP()did per address on the selection hot path.private static voidRefresh the cached configuration from properties at most once per CONFIG_REFRESH_MS, or immediately when the context changes.selectFloodfillParticipants(Set<Hash> toIgnore, KBucketSet<Hash> _kbuckets) List MAY INCLUDE our own hash.selectFloodfillParticipants(Hash key, int howMany, Set<Hash> toIgnore, KBucketSet<Hash> kbuckets) See above for description List will not include our own hash Returns new list, may be modified.selectFloodfillParticipants(Hash key, int maxNumRouters, KBucketSet<Hash> kbuckets) Sort the floodfills.selectFloodfillParticipants(KBucketSet<Hash> kbuckets) List will not include our own hash.selectFloodfillParticipantsIncludingUs(Hash key, int howMany, Set<Hash> toIgnore, KBucketSet<Hash> kbuckets) See above for description List MAY CONTAIN our own hash unless included in toIgnore Returns new list, may be modified.selectNearest(Hash key, int maxNumRouters, Set<Hash> peersToIgnore, KBucketSet<Hash> kbuckets) Floodfill peers only.selectNearestExplicit(Hash key, int maxNumRouters, Set<Hash> peersToIgnore, KBucketSet<Hash> kbuckets) Pick out peers with the floodfill capacity set, returning them first, but then after they're complete, sort via kademlia.
Field Details
_banLogger
Records why floodfills were banned._facade
The floodfill's own database facade._cfgCtx
Context the cached config values were read from._cfgRefreshed
private static volatile long _cfgRefreshedWhen the config values were last refreshed._cachedEnableUnresponsiveFloodfillBan
private static volatile boolean _cachedEnableUnresponsiveFloodfillBanCached ban setting for unresponsive floodfills.CONFIG_REFRESH_MS
private static final long CONFIG_REFRESH_MSInterval between config refreshes.- See Also:
_failedLookupRateStatSlot
Rate stat slots for the failed lookups._testSuccessTimeStatSlot
Rate stat slots for the test success times.NO_FAIL_STORE_OK
private static final int NO_FAIL_STORE_OKAge a no-fail floodfill counts as OK.- See Also:
NO_FAIL_STORE_GOOD
private static final int NO_FAIL_STORE_GOODAge a no-fail floodfill counts as good.- See Also:
NO_FAIL_LOOKUP_OK
private static final int NO_FAIL_LOOKUP_OKThis must be longer than the max streaming timeout (60s).- See Also:
NO_FAIL_LOOKUP_GOOD
private static final int NO_FAIL_LOOKUP_GOODAge a lookup counts as good with no failures.- See Also:
MAX_GOOD_RESP_TIME
private static final int MAX_GOOD_RESP_TIMEResponse time still counted as good, in ms.- See Also:
HEARD_AGE
private static final long HEARD_AGEAge after which a floodfill counts as recently heard about.- See Also:
STARTUP_GRACE_PERIOD
private static final long STARTUP_GRACE_PERIODGrace period after router startup before enforcing HEARD_AGE. After a restart, profiles may not be fully loaded yet and floodfills we re-discover get temporary firstHeardAbout=now() — locking them out for 45 minutes would hurt the most vulnerable moment.- See Also:
MAX_RI_AGE
private static final long MAX_RI_AGEFloodfills withRouterInfopublished longer ago than this are skipped.- See Also:
SAME_IP_MASK
private static final int SAME_IP_MASKByte count matched when fingerprinting a peer for same-subnet exclusion: /16 for IPv4, /32 for IPv6, mirroring the historicMaskedIPSet(_context, entry, info, 2)call.- See Also:
Constructor Details
FloodfillPeerSelector
Binds the facade and prepares the ban logger.- Parameters:
ctx- the router contextfacade- the network database to select peers from
Method Details
refreshConfig
Refresh the cached configuration from properties at most once per CONFIG_REFRESH_MS, or immediately when the context changes. Benign race: duplicate refreshes are idempotent writes.- Parameters:
ctx- the router context supplying the clock and properties
getEnableUnresponsiveFloodfillBan
Reads the unresponsive floodfill ban setting.- Parameters:
ctx- the context to read the config from- Returns:
- true to ban unresponsive floodfills
getRateStat
Get the RateStat handle, caching it in the slot for subsequent calls. Null is not cached, the stat may register later.- Parameters:
slot- one-element array holding the cached stat between callsname- full stat name, e.g. "peer.failedLookupRate"- Returns:
- the registered stat, or null while it does not exist yet
selectNearestExplicit
List<Hash> selectNearestExplicit(Hash key, int maxNumRouters, Set<Hash> peersToIgnore, KBucketSet<Hash> kbuckets) Pick out peers with the floodfill capacity set, returning them first, but then after they're complete, sort via kademlia.Walks the kbuckets with a FloodfillSelectionCollector, which gathers floodfill peers in groups (good floodfills first, then bad, then non-floodfills sorted by Kademlia distance to the key).
Does not prefer the floodfill peers that are directly connected. List will not include our own hash. Returns new list, may be modified.
- Specified by:
selectNearestExplicitin classPeerSelector- Parameters:
key- the ROUTING key (NOT the original key)maxNumRouters- the most hashes to return, zero or less meaning no limitpeersToIgnore- can be nullkbuckets- the routing table to select from- Returns:
- List of Hash for the peers selected
selectFloodfillParticipants
List will not include our own hash. List is not sorted and not shuffled. Returns new list, may be modified.- Parameters:
kbuckets- unused, retained for signature compatibility; null is accepted- Returns:
- all floodfills not banlisted forever.
selectFloodfillParticipants
List MAY INCLUDE our own hash. List is not sorted and not shuffled. Returns new list, may be modified.- Parameters:
toIgnore- can be null_kbuckets- unused, retained for signature compatibility; null is accepted- Returns:
- all floodfills not banlisted forever and not flagged unreachable.
buildFloodfillCandidates
Build the floodfill candidate list with only the cheap per-peer checks: the exclusion set, the two banlist tiers, and the unreachable capability flag. No profile is touched.ProfileOrganizer.peerSendsBadReplies(Hash)is deliberately not applied here — it takes ProfileOrganizer's read lock and then four synchronized Rate reads per peer, which on a healthy router is ~1000 lock acquisitions and ~4000 Rate reads for a single exploratory lookup, nearly all of them thrown away becauseselectFloodfillParticipantsIncludingUs(Hash, int, Set, KBucketSet)only ever walks a bounded prefix of the XOR order. That path applies the predicate lazily instead, which yields the identical selection.- Parameters:
toIgnore- can be null- Returns:
- the candidates, neither sorted nor shuffled; may be modified
selectFloodfillParticipants
Sort the floodfills. The challenge here is to keep the good ones at the front and the bad ones at the back. If they are all good or bad, searches and stores won't work well.List will not include our own hash. Returns new list, may be modified. Sorted by closest to the key if > maxNumRouters, otherwise not. The list is in 3 groups - sorted by routing key within each group. Group 1: No store or lookup failure in a long time, and lookup fail rate no more than 1.5 * average Group 2: No store or lookup failure in a little while or success newer than failure Group 3: All others.
- Parameters:
key- the ROUTING key (NOT the original key)maxNumRouters- max to returnkbuckets- unused, retained for signature compatibility; null is accepted- Returns:
- floodfills closest to the key that are not banlisted forever
selectFloodfillParticipants
List<Hash> selectFloodfillParticipants(Hash key, int howMany, Set<Hash> toIgnore, KBucketSet<Hash> kbuckets) See above for description List will not include our own hash Returns new list, may be modified.- Parameters:
key- the ROUTING key (NOT the original key)howMany- the maximum number of peers to returntoIgnore- can be nullkbuckets- unused, retained for signature compatibility; null is accepted- Returns:
- the selected peers, ordered best first, never null
selectFloodfillParticipantsIncludingUs
private List<Hash> selectFloodfillParticipantsIncludingUs(Hash key, int howMany, Set<Hash> toIgnore, KBucketSet<Hash> kbuckets) See above for description List MAY CONTAIN our own hash unless included in toIgnore Returns new list, may be modified.- Parameters:
key- the ROUTING key (NOT the original key)howMany- maximum number of floodfill peers to returntoIgnore- can be nullkbuckets- unused, retained for signature compatibility; null is accepted- Returns:
- a new shuffled-by-tier list of up to howMany floodfill hashes, GOOD peers first, then OK, then BAD; shorter if too few qualify
maskedIPKey
static long maskedIPKey(byte[] ip, int mask) Compact long fingerprint of a masked IP, replacing the per-candidate String construction (one StringBuilder plus up to 2*mask heap chars) that the historicMaskedIPSet.maskedIP()did per address on the selection hot path. Semantics match MaskedIPSet: the firstmaskbytes are matched, and an IPv6 address doubles the match width (8 bytes for mask=2, i.e. /64).Bit layout: bit 63 is an IPv6 marker (the analog of MaskedIPSet's ':' vs '.' delimiter, so the two families can never collide); the masked bytes' nibbles then occupy bits 59 downward. The largest supported packed key is 15 nibbles (60 bits) below the marker, i.e. IPv4 mask 4 or IPv6 mask 3.
- Parameters:
ip- an IPv4 (4-byte) or IPv6 (16-byte) addressmask- 1-4, the number of leading bytes to match- Returns:
- the packed fingerprint; equal keys mean "same masked subnet"
- Throws:
IllegalArgumentException- if the packed key would exceed 60 bits (IPv6 with mask 4), which no caller uses
addSameIPFingerprint
static boolean addSameIPFingerprint(Set<Long> maskedIPs, Set<Integer> ports, Set<String> families, RouterContext ctx, Hash peer, RouterInfo pinfo, int mask) Fingerprint a candidate peer into the exclusion accumulators, adding compact masked-IP keys, ports, and the claimed family option. One call replaces the per-candidateMaskedIPSetconstruction (and its per-address toString churn) of the historic selection loop.Returns whether any added key collided with a previously seen peer; this is the definition of "same IP" used to push a peer to the BAD tier. The three spaces (masked IP, port, family) are kept separate so, just like MaskedIPSet's '.' / 'p' / 'x' prefixes, a cross-space collision can never occur.
- Parameters:
maskedIPs- accumulator of packed masked-IP keys, mutated on addports- accumulator of router ports, mutated on addfamilies- accumulator of family option values, mutated on addctx- used to resolve the peer's communicate-addresspeer- the candidate's hashpinfo- the candidate RouterInfo (validated, never null here)mask- byte count formaskedIPKey(byte[], int)- Returns:
- true if at least one key was already present
computeMaxFailRate
private double computeMaxFailRate(long uptime) Compute the maximum acceptable failure rate for a floodfill peer, based on the network average over the last 10 minutes. Returns a value between 0.20 and 0.95.- Parameters:
uptime- router uptime in ms; under 2 hours the network average is not consulted- Returns:
- the failure rate ceiling, 0.95 while uptime or stats are too fresh, otherwise 1.25 times the network average clamped to 0.20 - 0.95
classifyFloodfillPeer
private FloodfillPeerSelector.PeerClass classifyFloodfillPeer(Hash entry, RouterInfo info, boolean sameIP, long now, boolean enforceHeard, double maxFailRate) Classify a single floodfill peer as GOOD, OK, or BAD for selection. GOOD: no recent failures, fast response, good profile. OK: some recent failures but still usable. BAD: unreachable, stale, slow, same IP, strict country, or poor profile.- Parameters:
entry- hash of the floodfill peer being classifiedinfo- the peer's RouterInfo from the local netdb, or null when absentsameIP- true if the peer shares a /16, port, or family with an already-accepted candidatenow- the current time in ms for age comparisonsenforceHeard- true after the startup grace period, to reject peers heard about less than 45 minutes agomaxFailRate- failure rate ceiling fromcomputeMaxFailRate(long)- Returns:
- the peer's class: GOOD, OK, or BAD
classifyFloodfillPeerForDisplay
public FloodfillPeerSelector.PeerClass classifyFloodfillPeerForDisplay(Hash entry, RouterInfo info, long now) Classify a floodfill peer for display purposes. Uses the same logic as the internal selection classifier but without same-IP tracking.- Parameters:
entry- the peer hashinfo- the peer's RouterInfo, may be nullnow- current time in milliseconds- Returns:
- GOOD, OK, or BAD
banAndDisconnect
private void banAndDisconnect(Hash entry, RouterInfo info, String banReason, String logReason, String disconnectReason, long banDuration, long logDuration, long now) Ban, log, and disconnect from a floodfill peer, with separate texts for the banlist, the ban log, and the disconnect reason.- Parameters:
entry- the peer hashinfo- the peer's RouterInfobanReason- the reason recorded in the banlistlogReason- the reason recorded in the ban logdisconnectReason- the reason passed to forceDisconnectbanDuration- the ban length in mslogDuration- the ban log length in msnow- the current time in ms
logSelectionResults
selectNearest
List<Hash> selectNearest(Hash key, int maxNumRouters, Set<Hash> peersToIgnore, KBucketSet<Hash> kbuckets) Floodfill peers only. Used only by HandleDatabaseLookupMessageJob to populate the DSRM. UNLESS peersToIgnore contains Hash.FAKE_HASH (all zeros), in which case this is an exploratory lookup, and the response should not include floodfills. List MAY INCLUDE our own router - add to peersToIgnore if you don't want.- Specified by:
selectNearestin classPeerSelector- Parameters:
key- the original key (NOT the routing key)maxNumRouters- the most hashes to return, zero or less meaning no limitpeersToIgnore- can be nullkbuckets- the routing table to select from- Returns:
- List of Hash for the peers selected, ordered
getIPFromRouterInfo
Extract IP:port from RouterInfo.- Parameters:
ri- the router info to read addresses from, may be null- Returns:
- host:port of the first address with both set, or null if ri is null or no address qualifies