Extracted from CommSystemFacadeImpl (2026-09-06) so the country cluster - a per-peer country cache with periodic cleanup, over-capacity eviction, strict-country gating, and startup GeoIP queueing - lives apart from the facade core. The facade retains thin delegation stubs so the public static and commSystem() APIs are unchanged.
All pure decision logic (cache eviction decisions, memory-independent helpers) is exposed as package-visible static methods so it can be tested without a running router; see CountryLookupDecisionTest.
Constructor Summary
ConstructorsConstructorDescriptionCountryLookup(RouterContext ctx, GeoIP geoIP) Create a lookup over the netDb's router IPs, backed by the GeoIP database.Method Summary
Modifier and TypeMethodDescription(package private) static intRemove stale and unresolved ("xx") entries from the country cache.static byte[]IP address compatible with our capabilities (IPv4/IPv6).Provides country code mappings.getCountry(String ip) The two-letter country code for an IP address string.getCountry(Hash peer) Uses the transport IP first because that lookup is fast, then the IP from the netDb.Full name for a country code, or the code if we don't know the name.static StringDomain name from a reverse DNS hostname.(package private) static byte[]getFirstValidIPOfType(RouterInfo ri, boolean wantIPv6) First valid IP of the specified type (IPv4 or IPv6).(package private) static byte[]getIP(RouterInfo ri) Return first IP (v4 or v6) we find, any transport.Country code for this router, from the GeoIP lookup.static byte[]getValidIP(RouterInfo ri) Return first valid IP (v4 or v6) we find, any transport.booleanAre we in a strict country.booleanisInStrictCountry(Hash peer) Are they in a strict country.booleanAre they in a strict country.(package private) static booleanisUnknownCountryCode(String code) True when the cache stores an unresolved-country marker ("xx").voidqueueLookup(byte[] ip) Queues a GeoIP lookup for the given IP.voidstart()Collect the IPs for all routers in the DB and queue them for lookup.(package private) static booleanCheck if we support outbound IPv4 connections.(package private) static booleanCheck if we support outbound IPv6 connections.(package private) static voidtrimToCapacity(Map<Hash, String> cache, Map<Hash, Long> timestamps, long now, long expiryMs, int maxSize) Bring an over-capacity country cache back under its size bound.
Constructor Details
CountryLookup
Create a lookup over the netDb's router IPs, backed by the GeoIP database.- Parameters:
ctx- non-nullgeoIP- non-null
Method Details
start
public void start()Collect the IPs for all routers in the DB and queue them for lookup. The recurring lookup pipeline starts on the first pass only.queueLookup
public void queueLookup(byte[] ip) Queues a GeoIP lookup for the given IP.- Parameters:
ip- ipv4 or ipv6
getOurCountry
Country code for this router, from the GeoIP lookup.- Returns:
- two-letter lower-case country code or null
isInStrictCountry
public boolean isInStrictCountry()Are we in a strict country.- Returns:
- whether in strict country
isInStrictCountry
Are they in a strict country. Not recommended for our local router hash, as we may not be either in the cache or netdb, or may not be publishing an IP.- Parameters:
peer- non-null- Returns:
- whether in strict country
isInStrictCountry
Are they in a strict country.- Parameters:
ri- non-null- Returns:
- whether in strict country
getCountry
Uses the transport IP first because that lookup is fast, then the IP from the netDb. Not recommended for our local router hash, as we may not be either in the cache or netdb, or may not be publishing an IP.As of 0.9.32, works only for literal IPs, returns null for hostnames.
- Parameters:
peer- not ourselves - use getOurCountry() for that- Returns:
- two-letter lower-case country code or xx for non-banned peers, or null otherwise
getCountry
getCountryName
getCountries
getDomain
Domain name from a reverse DNS hostname.Multi-part TLDs (co.uk, com.au, ...) are recognized so the registrable domain is returned rather than a bare second-level label.
- Parameters:
hostname- the reverse DNS host name to reduce to its registrable domain- Returns:
- domain name only from reverse dns hostname lookups
getIP
Return first IP (v4 or v6) we find, any transport. Not validated, may be local, etc.As of 0.9.32, works only for literal IPs, returns null for host names.
- Parameters:
ri- the RouterInfo whose addresses are scanned for a literal IP- Returns:
- IP or null
getValidIP
Return first valid IP (v4 or v6) we find, any transport. Local and other invalid IPs will not be returned.As of 0.9.32, works only for literal IPs, returns null for host names.
- Parameters:
ri- the RouterInfo whose addresses are scanned for a publicly routable IP- Returns:
- IP or null
getCompatibleIP
IP address compatible with our capabilities (IPv4/IPv6). Prefers IPv4 if we support it.- Parameters:
ri- RouterInfo to get IP from- Returns:
- IP or null
getFirstValidIPOfType
First valid IP of the specified type (IPv4 or IPv6).- Parameters:
ri- the RouterInfo whose addresses are scannedwantIPv6- true to accept a 16 byte address, false to accept a 4 byte one- Returns:
- the first valid IP of type
supportsIPv4
Check if we support outbound IPv4 connections.- Parameters:
ctx- the router context supplying the transport enablement properties- Returns:
- true when NTCP or UDP is enabled, so an outbound IPv4 connection is possible
supportsIPv6
Check if we support outbound IPv6 connections.- Parameters:
ctx- the router context supplying the transport enablement properties- Returns:
- true when neither NTCP nor UDP has IPv6 explicitly disabled
evictExpired
Remove stale and unresolved ("xx") entries from the country cache.An entry is expired when its timestamp is strictly older than
expiryMs; "xx" (unresolved) entries are always dropped. Called both periodically fromgetCountry(Hash)and as the first stage oftrimToCapacity(Map, Map, long, long, int)so the hot path never recomputes the loop.- Parameters:
cache- country cache to drain (entries removed in place)timestamps- parallel timestamp map for the same keysnow- cache age reference in millisexpiryMs- age threshold in millis (strict>)- Returns:
- number of entries removed
trimToCapacity
static void trimToCapacity(Map<Hash, String> cache, Map<Hash, Long> timestamps, long now, long expiryMs, int maxSize) Bring an over-capacity country cache back under its size bound.First advances the expired-entry pass via
evictExpired(Map, Map, long, long); if still at or abovemaxSize, drops the oldest quarter by timestamp. The redundant removeIf()/stream cascade in the original facade is preserved, so hot-path behavior (evict expired first, then oldest) is unchanged.- Parameters:
cache- country cache to shrink (entries removed in place)timestamps- parallel timestamp map for the same keysnow- cache age reference in millisexpiryMs- age threshold in millis for the expired-entry passmaxSize- size bound that triggers trimming
isUnknownCountryCode
True when the cache stores an unresolved-country marker ("xx").- Parameters:
code- the cached country name to test- Returns:
- true for the unresolved "xx" marker, and for a null code