java.lang.Object
net.i2p.router.NetworkDatabaseFacade
net.i2p.router.networkdb.kademlia.KademliaNetworkDatabaseFacade
All Implemented Interfaces:
Service
Direct Known Subclasses:
FloodfillNetworkDatabaseFacade

public abstract class KademliaNetworkDatabaseFacadeextends NetworkDatabaseFacade
Kademlia based version of network database.

Provides core network database functionality using Kademlia DHT for peer discovery, routing table management, and data storage/lookup operations. Never instantiated directly; see FloodfillNetworkDatabaseFacade.

  • Field Details

    • COMMA_SPLIT

      private static final Pattern COMMA_SPLIT
      Pattern.compile.
    • _log

      protected final Log _log
      Class logger.
    • _banLogger

      private BanLogger _banLogger
      Ban logger.
    • _kb

      private KBucketSet<Hash> _kb
      Kbucket set.
    • _ds

      private DataStore _ds
      Data store.
    • _dbDir

      private String _dbDir
      Where the data store is pushing the data.
    • _exploreKeys

      private final Set<Hash> _exploreKeys
      Hash objects that we should search on (to fill up a bucket, not to get data).
    • UNVERIFIED_MAX

      static final int UNVERIFIED_MAX
      Max peers held awaiting direct-contact verification. @since 0.9.71+.
      See Also:
    • UNVERIFIED_MAX_AGE

      static final long UNVERIFIED_MAX_AGE
      Drop a pending peer from the verification queue after this long; it is still in the netdb, it just stops being a bucket candidate until it proves itself. @since 0.9.71+.
      See Also:
    • IP_GROUP_BUCKET_LIMIT

      static final int IP_GROUP_BUCKET_LIMIT
      Max bucket entries sharing one IP group — eclipse/Sybil resistance, mirrors kubo's table.go limits. @since 0.9.71+.
      See Also:
    • IP_GROUP_GLOBAL_LIMIT

      static final int IP_GROUP_GLOBAL_LIMIT
      Max entries across all buckets sharing one IP group. @since 0.9.71+.
      See Also:
    • _unverifiedPeers

      private final Map<Hash,Long> _unverifiedPeers
      Peers stored in the netdb but not yet in the routing buckets, awaiting direct-contact evidence before insertion (verify-before-add). Filled by addContact(Hash, RouterInfo), drained by promoteUnverifiedPeers() and the probe cycle. Capped at UNVERIFIED_MAX, entries older than UNVERIFIED_MAX_AGE are dropped. Hash -> time queued.
    • _initialized

      private boolean _initialized
      Initialized flag.
    • _exploreJob

      private StartExplorersJob _exploreJob
      Clock independent time of when we started up.
    • _lastExploreNew

      private long _lastExploreNew
      When was the last time an exploration found something new?
    • _peerSelector

      protected final PeerSelector _peerSelector
      _peerSelector.
    • _context

      protected final RouterContext _context
      _context.
    • _reseedChecker

      private final ReseedChecker _reseedChecker
      Reseed checker.
    • _lastRIPublishTime

      private volatile long _lastRIPublishTime
      Last RI publish time.
    • _negativeCache

      private NegativeLookupCache _negativeCache
      Negative cache.
    • _networkID

      protected final int _networkID
      Network identifier.
    • _blindCache

      private final BlindCache _blindCache
      Blind cache.
    • _dbid

      private final Hash _dbid
      DB ID.
    • _elj

      private final Job _elj
      Expire leases job.
    • _erj

      private final Job _erj
      Expire routers job.
    • PROP_MIN_ROUTER_VERSION

      static final String PROP_MIN_ROUTER_VERSION
      Property: minimum router version for exploration.
      See Also:
    • PROP_BLOCK_MY_COUNTRY

      public static final String PROP_BLOCK_MY_COUNTRY
      Config property for blocking own-country peers.
      See Also:
    • PROP_IP_COUNTRY

      public static final String PROP_IP_COUNTRY
      Config property for IP country override.
      See Also:
    • PROP_BLOCK_COUNTRIES

      private static final String PROP_BLOCK_COUNTRIES
      Config property to block countries by IP.
      See Also:
    • DEFAULT_BLOCK_COUNTRIES

      private static final String DEFAULT_BLOCK_COUNTRIES
      Default comma-separated list of blocked countries.
      See Also:
    • MIN_ROUTER_VERSION

      public static final String MIN_ROUTER_VERSION
      Lowest peer version that may be selected for a KBucket probe.
      See Also:
    • MIN_VERSION

      public static final String MIN_VERSION
      Lowest peer version whose LeaseSets we will store and serve.
      See Also:
    • MAX_INTRO_SLOTS

      static final int MAX_INTRO_SLOTS
      Introducer slots per transport address. Mirrors UDPAddress.MAX_INTRODUCERS, which is package-private in the transport package - the same deliberate duplication IntroducerLookupJob already carries.
      See Also:
    • PROP_INTRO_TAG_PREFIX

      private static final String PROP_INTRO_TAG_PREFIX
      Introducer relay tag option prefix ("itag0".."itag4"); required in every slot.
      See Also:
    • CURRENT_VERSION

      public static String CURRENT_VERSION
      Current minor version identifier for net DB format.
    • kbInitLock

      private final Object kbInitLock
      Lock object for netdb access.
    • knownLeaseSetsCount

      private final AtomicInteger knownLeaseSetsCount
      Counter for lookups.
    • _publishingLeaseSets

      private final ConcurrentMap<Hash, Set<RepublishLeaseSetJob>> _publishingLeaseSets
      Map of Hash to RepublishLeaseSetJob for leases we're already managing. Multiple jobs may be queued per destination; new jobs replace old ones.
    • _batchRepublishQueue

      private final ConcurrentLinkedQueue<Hash> _batchRepublishQueue
      Queue for batching LeaseSet republishes within a 15-second window. This reduces job queue pressure by consolidating multiple republish jobs into one.
    • _batchRepublishPending

      private final Set<Hash> _batchRepublishPending
      Pending set for batch deduplication — a hash is in this set iff it is in the batch queue or being processed. Prevents duplicate entries under rapid publish(LeaseSet) calls.
    • _lastBatchProcessTime

      private volatile long _lastBatchProcessTime
      Track last batch processing time to ensure 15-second window.
    • BATCH_WINDOW_MS

      private static final long BATCH_WINDOW_MS
      Batched LeaseSet republishing constants.
      See Also:
    • BATCH_PROCESS_DELAY

      private static final long BATCH_PROCESS_DELAY
      Delay in ms between processing batches of netdb entries.
      See Also:
    • MAX_BATCH_SIZE

      private static final int MAX_BATCH_SIZE
      Maximum number of entries per batch.
      See Also:
    • LOCAL_LEASESET_REFRESH_INTERVAL

      private static final long LOCAL_LEASESET_REFRESH_INTERVAL
      Interval between local leaseset refreshes.
      See Also:
    • _refreshClientLeaseSetsJob

      private volatile KademliaNetworkDatabaseFacade.RefreshClientLeaseSetsJob _refreshClientLeaseSetsJob
      Singleton job to refresh client LeaseSets - only one instance exists.
    • _clientLeaseSetAccessTime

      private final ConcurrentHashMap<Hash,Long> _clientLeaseSetAccessTime
      Map of remote destination Hash to last access time for LeaseSets we're using as a client. Used to refresh remote LeaseSets we're actively accessing and remove after 150s inactivity.
    • _activeFloodfillQueries

      private final ConcurrentHashMap<Hash, AtomicInteger> _activeFloodfillQueries
      Count of active outbound iterative-search queries per floodfill peer; incremented when a query is dispatched, decremented when it completes or fails.
    • _recentlyQueriedFloodfills

      private final ConcurrentHashMap<Hash,Long> _recentlyQueriedFloodfills
      Tracks recently-queried floodfill peers across all concurrent searches to avoid hammering the same floodfill. Entries expire after 60s.
    • RECENTLY_QUERIED_COOLDOWN

      private static final long RECENTLY_QUERIED_COOLDOWN
      Cooldown before a floodfill can be queried again in ms.
      See Also:
    • _blockedCountries

      private volatile Set<String> _blockedCountries
      Cached set of blocked countries - lazily initialized.
    • DONT_FAIL_PERIOD

      public static long DONT_FAIL_PERIOD
      For 15 minutes after startup, don't fail db entries so that if we were offline for a while, we'll have a chance of finding some live peers with the previous references.
    • QUIET

      private static final boolean QUIET
      Don't probe or broadcast data, just respond and search when explicitly needed.
      See Also:
    • PROP_DB_DIR

      public static final String PROP_DB_DIR
      Config property for database directory.
      See Also:
    • DEFAULT_DB_DIR

      public static final String DEFAULT_DB_DIR
      Default database directory name.
      See Also:
    • MIN_RESEED

      static final int MIN_RESEED
      Reseed if below this.
      See Also:
    • MIN_REMAINING_ROUTERS

      protected static final int MIN_REMAINING_ROUTERS
      If we have less than this many routers left, don't drop any more, even if they're failing or doing bad stuff. As of 0.9.4, this equals the min for reseeding, so dropping stops at the point where a reseed is forced.
      See Also:
    • ROUTER_INFO_EXPIRATION

      private static final long ROUTER_INFO_EXPIRATION
      Limits for accepting a dbStore of a router, unless we don't know anyone or just started up -- see validate(RouterInfo) below.
      See Also:
    • ROUTER_INFO_EXPIRATION_MIN

      private static final long ROUTER_INFO_EXPIRATION_MIN
      Minimum RouterInfo expiration time in ms.
      See Also:
    • ROUTER_INFO_EXPIRATION_SHORT

      private static final long ROUTER_INFO_EXPIRATION_SHORT
      Short RouterInfo expiration time in ms for non-floodfill.
      See Also:
    • ROUTER_INFO_EXPIRATION_FLOODFILL

      private static final long ROUTER_INFO_EXPIRATION_FLOODFILL
      RouterInfo expiration time in ms for floodfill peers.
      See Also:
    • _cfgCtx

      private static volatile RouterContext _cfgCtx
      The context of the cached settings.
    • _cfgRefreshed

      private static volatile long _cfgRefreshed
      When the cached settings were refreshed.
    • _cachedProactiveRepublishThreshold

      private static volatile long _cachedProactiveRepublishThreshold
      The cached republish threshold.
    • _cachedBlockMyCountry

      private static volatile boolean _cachedBlockMyCountry
      The cached block-my-country flag.
    • _cachedMyCountry

      private static volatile String _cachedMyCountry
      The cached own country.
    • _cachedMinVersionAllowed

      private static volatile String _cachedMinVersionAllowed
      The cached minimum allowed version.
    • CONFIG_REFRESH_MS

      private static final long CONFIG_REFRESH_MS
      Interval for refreshing the cached settings.
      See Also:
    • ROUTER_INFO_EXPIRATION_INTRODUCED

      private static final long ROUTER_INFO_EXPIRATION_INTRODUCED
      RouterInfo expiration time in ms for introduced peers.
      See Also:
    • PROP_ROUTER_INFO_EXPIRATION_ADJUSTED

      static final String PROP_ROUTER_INFO_EXPIRATION_ADJUSTED
      Property: adjusted RouterInfo expiration time in ms.
      See Also:
    • PROP_VALIDATE_ROUTERS_AFTER

      static final String PROP_VALIDATE_ROUTERS_AFTER
      Property: delay before validating routers in ms.
      See Also:
    • EXPLORE_JOB_DELAY

      private static final long EXPLORE_JOB_DELAY
      Delay in ms before starting explore jobs.
      See Also:
    • MAX_LEASE_FUTURE

      private static final long MAX_LEASE_FUTURE
      Don't let leaseSets go too far into the future.
      See Also:
    • MAX_META_LEASE_FUTURE

      private static final long MAX_META_LEASE_FUTURE
      Maximum future time in ms for meta leases.
      See Also:
    • PUBLISH_JOB_DELAY

      protected static final long PUBLISH_JOB_DELAY
      Long enough to give us time to start up, but less than 20m, when we start accepting tunnels and could be an IBGW. Actually, we need this soon if we are a new router or other routers have forgotten about us, else we can't build IB exploratory tunnels. Unused.
      See Also:
    • MAX_EXPLORE_QUEUE

      static final int MAX_EXPLORE_QUEUE
      Maximum number of peers to place in the queue to explore.
      See Also:
    • BUCKET_SIZE_DEFAULT

      private static final int BUCKET_SIZE_DEFAULT
      Kad K — routers kept per distance class. With 256 single-bit leaf buckets this caps routing knowledge at 256 x 64 = 16,384 routers. Was 500 in the old implementation, but that was with B ~= -8.
      See Also:
    • PROP_BUCKET_SIZE

      static final String PROP_BUCKET_SIZE
      Property: Kademlia bucket size (K), read once at startup.
      See Also:
    • KAD_B

      private static final int KAD_B
      Kademlia top-level split factor (B).
      See Also:
    • RATES

      private static final long[] RATES
      Rate limits for netdb operations.
    • MAX_CONCURRENT_PER_FLOODFILL

      private static final int MAX_CONCURRENT_PER_FLOODFILL
      Max concurrent outbound IterativeSearch queries per floodfill peer. Above this we'll pick a different floodfill to distribute load.
      See Also:
    • PUBLISH_DELAY

      private static final long PUBLISH_DELAY
      Delay in ms before publishing.
      See Also:
    • EXPIRY_GRACE_PERIOD

      private static final long EXPIRY_GRACE_PERIOD
      Grace period, in ms, a locally-published LeaseSet's lease dates may already be past before validateLeaseSetExpiry() rejects it.
      See Also:
    • MIN_PER_PEER_TIMEOUT

      private static final int MIN_PER_PEER_TIMEOUT
      Smallest allowed period.
      See Also:
    • MAX_PER_PEER_TIMEOUT

      private static final int MAX_PER_PEER_TIMEOUT
      We want FNDF.PUBLISH_TIMEOUT and RepublishLeaseSetJob.REPUBLISH_LEASESET_TIMEOUT to be greater than MAX_PER_PEER_TIMEOUT * TIMEOUT_MULTIPLIER by a factor of at least 3 or 4, to allow at least that many peers to be attempted for a store.
      See Also:
    • TIMEOUT_MULTIPLIER

      private static final int TIMEOUT_MULTIPLIER
      Multiplier for Kademlia RPC timeout calculation.
      See Also:
    • PROACTIVE_REFRESH_THRESHOLD

      private static final long PROACTIVE_REFRESH_THRESHOLD
      Time to lease expiry, in ms, below which a tracked client LeaseSet is refreshed proactively instead of waiting for the next access. Only applies to the client NetDB, not the main NetDB. Each refresh cycle removes LeaseSets not accessed in 150s, re-fetches every tracked LeaseSet, and refreshes early when expiry is nearer than this value.
      See Also:
  • Constructor Details

    • KademliaNetworkDatabaseFacade

      public KademliaNetworkDatabaseFacade(RouterContext context, Hash dbid)
      Initializes the Kademlia-based network database facade.
      Parameters:
      context - the router context
      dbid - the unique identifier for this network database
  • Method Details

    • searchComplete

      void searchComplete(Hash key)
      The search for the given key is no longer active.
      Parameters:
      key - the key whose search is complete
    • refreshConfig

      private static void refreshConfig(RouterContext ctx)
      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 - router context whose properties are read into the cache
    • bucketSize

      static int bucketSize(RouterContext context)
      Bucket size (K) from the property, clamped to what KBucketSet accepts.
      Parameters:
      context - the router context to read the property from
      Returns:
      the bucket size, at least 5
    • isInitialized

      public boolean isInitialized()
      Checks whether the network database has been fully initialized.
      Overrides:
      isInitialized in class NetworkDatabaseFacade
      Returns:
      true if the database is initialized and ready for use, false otherwise
    • createPeerSelector

      protected PeerSelector createPeerSelector()
      Creates a peer selector for the network database. Only applicable for the main database.
      Returns:
      a new PeerSelector instance
      Throws:
      IllegalStateException - if called on a client database
    • getPeerSelector

      public PeerSelector getPeerSelector()
      Returns the main database's peer selector.
      Returns:
      the PeerSelector instance, or null if this is a client database
    • reseedChecker

      public ReseedChecker reseedChecker()
      Reseed checker, or null for a client DB.
      Overrides:
      reseedChecker in class NetworkDatabaseFacade
      Returns:
      the reseed checker
    • blindCache

      protected BlindCache blindCache()
      Returns the blind data cache used by this database.

      We still always use a single blind cache in the main Db(for now), see issue #421 on i2pgit.org/i2p-hackers/i2p.i2p for details. This checks if we're the main DB already and returns our blind cache if we are. If not, it looks up the main Db and gets it.

      Returns:
      the BlindCache instance, never null
    • getKBuckets

      KBucketSet<Hash> getKBuckets()
      KBucketSet for the main DB.
      Returns:
      the main DB's KBucketSet. Client DBs do not have their own.
    • getDataStore

      DataStore getDataStore()
      The data store.
      Returns:
      the backing store used to look up and store kademlia data
    • getLastExploreNewDate

      long getLastExploreNewDate()
      Time of the last explore run.
      Returns:
      the last explore new date
    • setLastExploreNewDate

      void setLastExploreNewDate(long when)
      Time of the last explore run.
      Parameters:
      when - the new date
    • getExploreKeys

      public Set<Hash> getExploreKeys()
      Keys to explore.
      Returns:
      an unmodifiable set, empty until the database is initialized
    • removeFromExploreKeys

      public void removeFromExploreKeys(Collection<Hash> toRemove)
      Remove keys from the exploration set.
      Parameters:
      toRemove - keys to remove
    • queueForExploration

      public void queueForExploration(Collection<Hash> keys)
      Queue keys for exploration.
      Parameters:
      keys - keys to queue
    • shutdown

      public void shutdown()
      Shut down the NetDB and all its jobs.
    • rescan

      public void rescan()
      Rescan the netdb directory for new RouterInfo files.
      Overrides:
      rescan in class NetworkDatabaseFacade
    • getDbDir

      String getDbDir()
      For the main DB only. Sub DBs are not persisted and must not access this directory.
      Returns:
      null before startup() is called; non-null thereafter, even for subdbs.
    • isClientDb

      public boolean isClientDb()
      Check if the database is a client DB.
      Returns:
      true if the database is a client DB, false otherwise
    • startup

      public void startup()
      Open the backing store, build the KBuckets, and prime the negative cache and the recurring expiry, refresh, and exploration jobs. Called once by the router at startup.
      Throws:
      RuntimeException - if the on-disk store cannot be opened
    • createHandlers

      protected void createHandlers()
      Unused, see override.
    • findNearestRouters

      public Set<Hash> findNearestRouters(Hash key, int maxNumRouters, Set<Hash> peersToIgnore)
      The routers closest to that key in response to a remote lookup. Only used by ../HDLMJ Set MAY INCLUDE our own router - add to peersToIgnore if you don't want.
      Specified by:
      findNearestRouters in class NetworkDatabaseFacade
      Parameters:
      key - the real key, NOT the routing key
      maxNumRouters - The maximum number of routers to return
      peersToIgnore - can be null
      Returns:
      set of router hashes closest to the key
    • isRecentlyQueried

      boolean isRecentlyQueried(Hash peer)
      Check if a floodfill peer was queried recently (within cooldown period).
      Parameters:
      peer - the floodfill peer
      Returns:
      true if the peer was queried within the last 60s
    • markQueried

      void markQueried(Hash peer)
      Mark a floodfill peer as recently queried. Other searches will avoid this peer for the cooldown period.
      Parameters:
      peer - the floodfill peer
    • incrementActiveFloodfillQuery

      int incrementActiveFloodfillQuery(Hash floodfill)
      Increment the active outbound query count for a floodfill peer. Call when sendQuery() dispatches a DatabaseLookupMessage to this peer.
      Parameters:
      floodfill - the floodfill peer
      Returns:
      the new count
    • decrementActiveFloodfillQuery

      void decrementActiveFloodfillQuery(Hash floodfill)
      Decrement the active outbound query count for a floodfill peer. Call when the search for this peer completes, fails, or times out.
      Parameters:
      floodfill - the floodfill peer
    • isFloodfillOverloaded

      boolean isFloodfillOverloaded(Hash floodfill)
      Check if a floodfill peer already has too many active outbound queries from this router. Spreads the load across available floodfills so no single peer is saturated.
      Parameters:
      floodfill - the floodfill peer
      Returns:
      true if the peer should be skipped for now
    • getAllRouters

      public Set<Hash> getAllRouters()
      Hashes for all known routers.
      Specified by:
      getAllRouters in class NetworkDatabaseFacade
      Returns:
      set of router hashes
    • getKnownRouters

      public int getKnownRouters()
      This used to return the number of routers that were in both the kbuckets AND the data store, which was fine when the kbuckets held everything. But now that is probably not what you want. Just return the count in the data store.
      Overrides:
      getKnownRouters in class NetworkDatabaseFacade
      Returns:
      0 if this is a client DB
    • getKnownLeaseSets

      public int getKnownLeaseSets()
      This is only used by StatisticsManager to publish the count if we are floodfill. So to hide a clue that a popular eepsite is hosted on a floodfill router, only count leasesets that are "received as published", as of 0.7.14.
      Overrides:
      getKnownLeaseSets in class NetworkDatabaseFacade
      Returns:
      the known lease sets
    • getKBucketSetSize

      protected int getKBucketSetSize()
      Size of the KBucketSet. The KBucketSet contains RIs only.
      Returns:
      the number of RIs in the KBucketSet, or 0 before it is built
    • getBlindData

      public BlindData getBlindData(SigningPublicKey spk)
      BlindData for the given key.
      Overrides:
      getBlindData in class NetworkDatabaseFacade
      Parameters:
      spk - unblinded key
      Returns:
      BlindData or null
    • setBlindData

      public void setBlindData(BlindData bd)
      BlindData to put in the cache.
      Overrides:
      setBlindData in class NetworkDatabaseFacade
      Parameters:
      bd - new BlindData to put in the cache
    • getBlindData

      public List<BlindData> getBlindData()
      All cached BlindData.
      Overrides:
      getBlindData in class NetworkDatabaseFacade
      Returns:
      every BlindData held in the blind cache
    • removeBlindData

      public boolean removeBlindData(SigningPublicKey spk)
      For console ConfigKeyringHelper.
      Overrides:
      removeBlindData in class NetworkDatabaseFacade
      Parameters:
      spk - the unblinded public key
      Returns:
      true if removed
    • routingKeyChanged

      public void routingKeyChanged()
      Notify the netDB that the routing key changed at midnight UTC.
      Overrides:
      routingKeyChanged in class NetworkDatabaseFacade
    • lookupLocally

      public DatabaseEntry lookupLocally(Hash key)
      Validated entry stored locally.
      Specified by:
      lookupLocally in class NetworkDatabaseFacade
      Parameters:
      key - the hash of the RouterInfo or LeaseSet to look up
      Returns:
      RouterInfo, LeaseSet, or null, validated
    • lookupLocallyWithoutValidation

      public DatabaseEntry lookupLocallyWithoutValidation(Hash key)
      Not for use without validation.
      Specified by:
      lookupLocallyWithoutValidation in class NetworkDatabaseFacade
      Parameters:
      key - the hash of the RouterInfo or LeaseSet to look up
      Returns:
      RouterInfo, LeaseSet, or null, NOT validated
    • lookupLeaseSet

      public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs)
      Look up a LeaseSet, locally first.

      Searches remotely if the LeaseSet is not held locally, is not negative-cached, and is not a local destination this router hosts.

      Specified by:
      lookupLeaseSet in class NetworkDatabaseFacade
      Parameters:
      key - the LeaseSet key
      onFindJob - run if the LeaseSet is found locally or in the search, may be null
      onFailedLookupJob - run if the lookup cannot be attempted or fails, may be null
      timeoutMs - how long to wait for the search before failing
    • lookupLeaseSet

      public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest)
      Lookup using the client's tunnels Use lookupDestination(Hash, Job, long, Hash) if you don't need the LS or don't need it validated.

      A negative-cached key is not searched again: the failure job is run instead. A client sub-NetDb local miss for a destination this router hosts also fails without a search, since only the main NetDb holds such a LeaseSet.

      Specified by:
      lookupLeaseSet in class NetworkDatabaseFacade
      Parameters:
      key - the LeaseSet key
      onFindJob - run if the LeaseSet is found locally or in the search, may be null
      onFailedLookupJob - run if the router is uninitialized, the key is negative-cached, or the search fails, may be null
      timeoutMs - how long to wait for the search before failing
      fromLocalDest - use these tunnels for the lookup, or null for exploratory
    • shouldFailLocalWithoutRemoteSearch

      static boolean shouldFailLocalWithoutRemoteSearch(boolean isClientDb, boolean isLocalDest)
      Whether a client sub-NetDb local miss for a destination this router hosts must fail immediately instead of starting a network search. Locally-published LeaseSets live in the main NetDb (mirrored on publish); querying floodfills for our own key is always wasted work and the client sub-Db path has no reply routing for that search.
      Parameters:
      isClientDb - true when this facade is a client sub-NetDb
      isLocalDest - true when the key is a destination hosted on this router
      Returns:
      true to fail without a remote search
    • shouldFallbackLocalLookupToMain

      static boolean shouldFallbackLocalLookupToMain(boolean isClientDb, boolean isLocalDest, boolean foundLocally)
      Whether a client sub-NetDb local miss should be re-checked in the main NetDb. Only for destinations we host; remote keys must stay isolated in the caller's sub-NetDb.
      Parameters:
      isClientDb - true when this facade is a client sub-NetDb
      isLocalDest - true when the key is a destination hosted on this router
      foundLocally - true when this facade already held a current LeaseSet
      Returns:
      true to consult the main NetDb
    • isLocalDestination

      private boolean isLocalDestination(Hash key)
      Whether the key is one of our own destinations.
      Parameters:
      key - destination hash to test, null returns false
      Returns:
      true if the key is a destination currently registered locally
    • getMainFacade

      private KademliaNetworkDatabaseFacade getMainFacade()
      Main (router) NetDb facade, or null if unavailable.
      Returns:
      the main facade, or null
    • lookupLeaseSetRemotely

      public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest)
      Unconditionally lookup using the client's tunnels, with no jobs. No local lookup and no LeaseSet validation. Use this to refresh a LeaseSet before expiration.

      The one check that does apply is the negative cache: a negative-cached key returns without searching, since a recent search already established that the key is unresolvable. Nothing is sent to the caller if the router is uninitialized.

      Specified by:
      lookupLeaseSetRemotely in class NetworkDatabaseFacade
      Parameters:
      key - the LeaseSet key
      fromLocalDest - use these tunnels for the lookup, or null for exploratory
    • lookupLeaseSetRemotely

      public void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest)
      Unconditionally lookup using the client's tunnels.

      Same negative-cache suppression as the two-argument overload: a negative-cached key is not searched again and the failure job is run instead. Nothing is searched if the router is uninitialized.

      Specified by:
      lookupLeaseSetRemotely in class NetworkDatabaseFacade
      Parameters:
      key - the LeaseSet key
      onFindJob - run if the LeaseSet is found, may be null
      onFailedLookupJob - run if the router is uninitialized, the key is negative-cached, or the search fails, may be null
      timeoutMs - how long to wait for the search before failing
      fromLocalDest - use these tunnels for the lookup, or null for exploratory
    • lookupLeaseSetLocally

      public LeaseSet lookupLeaseSetLocally(Hash key)
      LeaseSet stored locally.
      Specified by:
      lookupLeaseSetLocally in class NetworkDatabaseFacade
      Parameters:
      key - the destination hash whose LeaseSet is sought
      Returns:
      the LeaseSet or null
    • getLocalLeaseSet

      private LeaseSet getLocalLeaseSet(Hash key)
      Read a current LeaseSet from this facade's store only. Returns null if missing, not a LeaseSet, or not current.
      Parameters:
      key - destination or blinded key
      Returns:
      the LeaseSet or null
    • accessLeaseSet

      public void accessLeaseSet(Hash key)
      Record access to a LeaseSet for refresh tracking. Call this when actively using a LeaseSet (tunnel build, outbound message). Tracks all remote destinations, hostname or not, tunnel pool or not - b32/hash-only services (SAM, BOB, anonymous browsing) need refreshing too, and getOutboundPool() is keyed by local client hash, so it can never be used to gate remote destinations. Do NOT call for HostChecker lookups.
      Specified by:
      accessLeaseSet in class NetworkDatabaseFacade
      Parameters:
      key - the destination hash of the LeaseSet that was used
    • refreshLocalLeaseSetIfExpiring

      private void refreshLocalLeaseSetIfExpiring(Hash key, long now)
      Nudge the inbound pool to re-publish our own LeaseSet when a client is actively using it and the earliest lease is inside the proactive window. No-op without a stored LeaseSet or when the earliest lease still has ample remaining life.
      Parameters:
      key - local destination hash
      now - current router time (ms)
    • removeLeaseSetFromTracking

      public void removeLeaseSetFromTracking(Hash key)
      Remove a LeaseSet from refresh tracking. Call this after HostChecker completes to avoid unnecessary refreshes.
      Specified by:
      removeLeaseSetFromTracking in class NetworkDatabaseFacade
      Parameters:
      key - the destination hash of the LeaseSet to stop tracking
    • lookupDestination

      public void lookupDestination(Hash key, Job onFinishedJob, long timeoutMs, Hash fromLocalDest)
      Lookup using the client's tunnels Succeeds even if LS validation and store fails due to unsupported sig type, expired, etc.

      Note that there are not separate success and fail jobs. Caller must call lookupDestinationLocally(Hash) in the job to determine success.

      The finished job is also run, without any search, if the router is uninitialized or the key is negative-cached.

      Specified by:
      lookupDestination in class NetworkDatabaseFacade
      Parameters:
      key - the destination key
      onFinishedJob - run when the lookup finishes, may not be null
      timeoutMs - how long to wait for the search before finishing
      fromLocalDest - use these tunnels for the lookup, or null for exploratory
    • lookupDestinationLocally

      public Destination lookupDestinationLocally(Hash key)
      Destination stored locally, or null.
      Specified by:
      lookupDestinationLocally in class NetworkDatabaseFacade
      Parameters:
      key - the destination hash to look up
      Returns:
      the Destination or null
    • containsCapability

      private boolean containsCapability(RouterInfo ri, char capability)
      Whether the router advertises the given capability.
      Parameters:
      ri - router whose capability string is examined
      capability - one of the Router.CAPABILITY_* characters, e.g. 'G'
      Returns:
      true if that character appears in the capability string
    • lookupRouterInfo

      public void lookupRouterInfo(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs)
      Look up a RouterInfo, resolving over the network when not cached locally.

      Screening (country/capability bans, blocklists) applies only to an entry we actually hold; a screened-out entry fails the callback instead of succeeding. A cache miss always starts a real search: data-plane callers (transit next-hop resolution in BuildHandler and TunnelParticipant, tunnel receivers, message distributors) depend on this actually finding the peer, and an instant fail here turns every next-hop miss into a rejected join or a silently dropped message. Negatively-cached keys short-circuit inside IterativeSearchJob, so repeated searches for known-dead peers stay cheap.

      Specified by:
      lookupRouterInfo in class NetworkDatabaseFacade
      Parameters:
      key - the router hash whose RouterInfo is sought
      onFindJob - job to run on success
      onFailedLookupJob - job to run on failure
      timeoutMs - timeout in milliseconds
    • lookupRouterInfoRemote

      public void lookupRouterInfoRemote(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs)
      Look up a RouterInfo by hash, performing a network search if not locally cached. Unlike lookupRouterInfo(Hash, Job, Job, long) which calls onFailedLookupJob immediately for unknown routers, this method schedules an IterativeSearchJob when the RI is absent from the local netdb. The caller should provide a timeoutMs shorter than the acceptable delay (typical: 8-15 seconds).

      The onFindJob fires when the RI is available locally (either it was already present or the search completed). The onFailedLookupJob fires on search timeout or failure.

      Caller must clean up via removeRouterInfo(Hash) after extracting the needed data.

      Parameters:
      key - the Router hash to look up
      onFindJob - run when RI is local (may be null)
      onFailedLookupJob - run on lookup failure (may be null)
      timeoutMs - max wait in ms (bounded internally by the adaptive lookup cap)
    • shouldBanlistBasedOnCountry

      private boolean shouldBanlistBasedOnCountry(RouterInfo _ri, Hash key)
      Should we banlist this router based on country restrictions? Checks if: - we are in strict country mode and router is in same country - blockMyCountry is enabled - router is in our country (strict country mode).
      Parameters:
      _ri - router info under consideration, not consulted by the test
      key - router hash, used to look up strict-country membership
      Returns:
      true if the peer's country makes it banlistable
    • shouldBanlistXG

      private boolean shouldBanlistXG(RouterInfo ri)
      Determine whether the given router should be banlisted due to being an XG router that is neither reachable nor unreachable and the XG banlist option is enabled.
      Parameters:
      ri - the router info to evaluate
      Returns:
      true if the router matches the XG banlist criteria
    • shouldBanlistLU

      private boolean shouldBanlistLU(RouterInfo ri)
      Determine whether the given router should be banlisted due to being: - an unreachable L-tier router (CAPABILITY_BW12),

      This is typically used to filter out low-performing routers.

      Parameters:
      ri - the router info to evaluate
      Returns:
      true if the router matches the LU banlist criteria
    • tooManyIntroducers

      static boolean tooManyIntroducers(Collection<RouterAddress> addrs)
      Whether any single transport address advertises more introducers than the SSU2 spec allows. Every introducer slot carries a relay tag, so a tag at or beyond the cap means the peer wrote more slots than it may. Checked per address, not in total: a dual-stack router may legitimately carry the cap once on v4 and again on v6, and the console flattens both lists.
      Parameters:
      addrs - the router's transport addresses, may be null or empty
      Returns:
      true if one address declares more than MAX_INTRO_SLOTS introducers
    • shouldBanlistIntroducers

      private boolean shouldBanlistIntroducers(RouterInfo ri)
      Determine whether the given router should be banlisted for advertising more introducers on one transport address than the SSU2 spec allows. Out-of-spec introducer counts are used by scanners to inflate netdb storage and by modified clients to hide behind relay churn.
      Parameters:
      ri - the router info to evaluate
      Returns:
      true if the router matches the introducer-cap ban criteria
    • invalidRouterInfoBanReason

      String invalidRouterInfoBanReason(RouterInfo ri)
      The ban reason if this RouterInfo fails one of the RouterInfo validation rules - a version above every released version, an impossible publication date, or both the reachable and the unreachable flag at once - or null if it passes. Each rule has its own toggle on /configban. The reason strings match what the transport handshakes record, so a peer is penalised identically however we learn of it.
      Parameters:
      ri - the router info to evaluate
      Returns:
      the ban reason for the first rule it breaks, or null if it breaks none
    • invalidRouterInfoBanReason

      static String invalidRouterInfoBanReason(RouterInfo ri, boolean banVersion, boolean banPubDate, boolean banCaps)
      The validation rule a RouterInfo breaks, given which of the three rules are switched on. The self-router check and the toggle reads stay with the caller; this is the pure part, so the rule ordering and the reason strings can be tested without a router context.
      Parameters:
      ri - the router info to evaluate, may be null
      banVersion - whether the fabricated-version rule is enabled
      banPubDate - whether the impossible-publication-date rule is enabled
      banCaps - whether the contradictory-reachability rule is enabled
      Returns:
      the reason for the first rule broken, or null if none
    • shouldBanlistByCapability

      private boolean shouldBanlistByCapability(RouterInfo ri)
      Determine whether the given router should be banlisted based on custom capability patterns configured by the user.
      Parameters:
      ri - the router info to evaluate
      Returns:
      true if the router matches any custom capability ban pattern
    • allowPolicyBan

      private boolean allowPolicyBan(Hash key)
      Whether policy bans (country/XG/LU/capability) may be applied to this router during resolution. Controlled by router.banlist.banNextHop: when false, peers we are not directly connected to - transit next-hop candidates and client tunnel endpoints heard from the network - are exempt, so transit and client traffic never banlist a peer merely because it appeared as a resolution target. Security screening (permanent/hostile blocklists) is unaffected.
      Parameters:
      key - the router being resolved
      Returns:
      true if policy bans may fire for this lookup
    • handleCustomCapabilityBan

      private void handleCustomCapabilityBan(RouterInfo ri, Hash key, Job onFailedLookupJob)
      Handle banning a router that matches custom capability ban patterns, for four hours.
      Parameters:
      ri - router info to ban, source of the IP:port in the ban log
      key - router hash to banlist and drop from the netdb
      onFailedLookupJob - queued to fail the pending lookup, or null
    • handleIntroducerBan

      private void handleIntroducerBan(RouterInfo ri, Hash key, Job onFailedLookupJob)
      Handle banning a router that advertises more introducers on one address than the SSU2 spec allows. Same four-hour term the SSU2 handshake ban uses, so a peer is penalised identically however we learn of it.
      Parameters:
      ri - router info to ban, source of the IP:port in the ban log
      key - router hash to banlist and drop from the netdb
      onFailedLookupJob - job to requeue if the lookup is abandoned, or null
    • handleInvalidRouterInfoBan

      private void handleInvalidRouterInfoBan(RouterInfo ri, Hash key, String reason, Job onFailedLookupJob)
      Handle banning a RouterInfo that breaks one of the RouterInfo validation rules - fabricated version, impossible publication date, or contradictory reachability flags. Same 24-hour term the transport handshakes use for the same rule, so a peer is penalised identically however we learn of it.
      Parameters:
      ri - the offending router info
      key - the router hash
      reason - the rule it broke, from invalidRouterInfoBanReason(RouterInfo)
      onFailedLookupJob - job to requeue a lookup that resolved to this router, or null
    • removeRouterInfo

      public void removeRouterInfo(Hash key)
      Remove a RouterInfo from the local netdb. No-op if the key is not present or is not a RouterInfo. Safe to call on any hash — non-RouterInfo entries are left untouched.
      Parameters:
      key - the Router hash to remove
    • removeFromNetDb

      private void removeFromNetDb(Hash key)
      Remove a router from the NetDb without banning it. Used internally by the purge sweep and handleBanlistAndRemove.
      Parameters:
      key - router hash to drop, null is a no-op
    • purgeMatchingRouters

      public void purgeMatchingRouters()
      Trigger a retroactive purge sweep of the NetDb. Bans and removes all routers matching enabled LU/XG/custom-cap bans. Only call this on config change, not on startup or disable.
      Overrides:
      purgeMatchingRouters in class NetworkDatabaseFacade
    • isPermanentlyBlocklisted

      private boolean isPermanentlyBlocklisted(Hash key)
      Whether the router is on the permanent blocklist.
      Parameters:
      key - router hash to look for in the Banlist
      Returns:
      true if the Banlist holds the key with no expiry
    • isHostileBlocklisted

      private boolean isHostileBlocklisted(Hash key)
      Whether the router is on the hostile blocklist.
      Parameters:
      key - router hash to look for in the Banlist
      Returns:
      true if the Banlist holds the key as hostile
    • handleBanlistAndRemove

      private void handleBanlistAndRemove(RouterInfo ri, Hash key, Job onFailedLookupJob)
      Banlist a router for one hour as an unreachable low-bandwidth peer older than MIN_VERSION, then drop it from the data store, the routing buckets and the unverified queue.
      Parameters:
      ri - router info being banned, source of the IP:port in the log
      key - router hash to banlist and drop from the netdb
      onFailedLookupJob - requeued as the lookup's failure, or null
    • handlePermanentBlocklist

      private void handlePermanentBlocklist(RouterInfo _ri, Hash key, Job onFailedLookupJob)
      Drop the RouterInfo of a router already on the permanent blocklist; no new ban entry is written, the existing one stands.
      Parameters:
      _ri - router info being dropped, not consulted
      key - router hash removed from the netdb and the routing tables
      onFailedLookupJob - requeued as the lookup's failure, or null
    • handleHostileBlocklist

      private void handleHostileBlocklist(RouterInfo _ri, Hash key, Job onFailedLookupJob)
      Drop the RouterInfo of a router tagged hostile on the Banlist, without extending or adding a ban.
      Parameters:
      _ri - router info being dropped, not consulted
      key - router hash removed from the netdb and the routing tables
      onFailedLookupJob - queued to fail the pending lookup, or null
    • lookupRouterInfoLocally

      public RouterInfo lookupRouterInfoLocally(Hash key)
      This will return immediately with the result or null. However, this may still fire off a lookup if the RI is present but expired (and will return null). This may result in deadlocks. For true local only, use lookupLocallyWithoutValidation(Hash).
      Specified by:
      lookupRouterInfoLocally in class NetworkDatabaseFacade
      Parameters:
      key - the router hash whose RouterInfo is sought
      Returns:
      null always for client dbs
    • getProactiveRepublishThreshold

      private long getProactiveRepublishThreshold()
      Proactive republish threshold from config or default (3 minutes). If a lease is expiring within this threshold, it gets republished immediately. Tunable via i2p.netdb.proactiveRepublishThreshold (default: 180000).
      Returns:
      the proactive republish threshold
    • publish

      public void publish(LeaseSet localLeaseSet) throws IllegalArgumentException
      Publishes a local LeaseSet to the network: stores it in this facade and, for a client facade, also in the floodfill facade, then schedules republishing. LeaseSet expiry dates are validated first (not expired before publish).
      Specified by:
      publish in class NetworkDatabaseFacade
      Parameters:
      localLeaseSet - the LeaseSet to publish
      Throws:
      IllegalArgumentException - if the LeaseSet is invalid or expired
    • storeLocalLeaseSetCopy

      private void storeLocalLeaseSetCopy(LeaseSet localLeaseSet)
      Store the local copy, forcing overwrite; propagate IAE to the caller.
      Parameters:
      localLeaseSet - the LeaseSet a local client just published
      Throws:
      IllegalArgumentException - if storing it fails validation
    • handleNonPublishedLeaseSet

      private void handleNonPublishedLeaseSet(Hash hash)
      A local client whose LS is not published to the network (i2cp.dontPublishLeaseSet, e.g. HTTP proxy) still needs the local copy re-minted while it is active. Client leases last ~6 min but tunnels rotate on a ~10-min cycle, so without a republish schedule the local LeaseSet shows expired in the netdb for minutes at a time.
      Parameters:
      hash - destination hash of a client we host but do not publish
    • isGracefulExitShutdown

      private boolean isGracefulExitShutdown()
      Whether the router is shutting down gracefully.
      Returns:
      true if a graceful shutdown with defined exit codes is in progress
    • mirrorToMainFacade

      private void mirrorToMainFacade(LeaseSet localLeaseSet)
      A locally-published LeaseSet legitimately occupies both the client facade (where the client pushed it) and the floodfill facade (where the router console and the network look it up). Storing the copy into the floodfill facade here makes hosted services retrievable immediately, without waiting for the network to flood the LeaseSet back to us. The NetDbRenderer dedups the two facades' entries on the netdb page.
      Parameters:
      localLeaseSet - copy to place in the main (floodfill) facade
    • validateLeaseSetExpiry

      private void validateLeaseSetExpiry(LeaseSet leaseSet)
      Reject a LeaseSet whose leases are already in the past, allowing EXPIRY_GRACE_PERIOD of slack for clock skew.
      Parameters:
      leaseSet - the locally-published LeaseSet about to be stored
      Throws:
      IllegalArgumentException - if either lease date is more than the grace period in the past
    • scheduleRepublish

      private void scheduleRepublish(Hash hash)
      Queues the LeaseSet for future republishing. First publications are queued immediately; subsequent republishes are batched within a 15-second window to reduce job queue pressure.

      Proactively starts republishing 3 minutes before lease expiration to ensure network propagation has ample time before the lease expires.

      Parameters:
      hash - destination hash of the LeaseSet to republish
    • cancelActiveRepublishJob

      private boolean cancelActiveRepublishJob(Hash hash)
      Cancel any queued RepublishLeaseSetJob for the given hash. This ensures that the next fresh run picks up the latest LeaseSet rather than using one that was stale when the job was queued.
      Parameters:
      hash - destination hash whose queued republish job is withdrawn
      Returns:
      true if a job was cancelled, false if none existed
    • removePublishingJob

      void removePublishingJob(Hash hash, RepublishLeaseSetJob job)
      Remove a specific job from the tracking set.
      Parameters:
      hash - the destination hash
      job - the job to remove
    • hasActiveRepublishJob

      boolean hasActiveRepublishJob(Hash hash)
      Check if an active republish job exists for the given destination.
      Parameters:
      hash - the destination hash
      Returns:
      true if active
    • registerPublishingJob

      boolean registerPublishingJob(RepublishLeaseSetJob job)
      Register a new job for tracking. Skips registration if a job is already active.
      Parameters:
      job - the job to register
      Returns:
      true if job was registered, false if one was already active
    • stopPublishing

      void stopPublishing(Hash target)
      Stops publishing the given LeaseSet.
      Parameters:
      target - hash to stop publishing
    • publish

      public void publish(RouterInfo localRouterInfo) throws IllegalArgumentException
      Stores to local db only. Overridden in FNDF to actually send to the floodfills.
      Specified by:
      publish in class NetworkDatabaseFacade
      Parameters:
      localRouterInfo - the RouterInfo to publish
      Throws:
      IllegalArgumentException - if the local router info is invalid or if this is a client DB
    • routerInfoPublishSuccessful

      void routerInfoPublishSuccessful()
      Record the current time as the last successful RI publication.
    • getLastRouterInfoPublishTime

      public long getLastRouterInfoPublishTime()
      Time of the last successful RI publication.
      Overrides:
      getLastRouterInfoPublishTime in class NetworkDatabaseFacade
      Returns:
      ms since the epoch of the last successful publication, 0 if never
    • validate

      public String validate(Hash key, LeaseSet leaseSet) throws UnsupportedCryptoException
      Validates whether the given LeaseSet is acceptable as valid and current based on current known parameters.

      This method performs several checks including:

      • Verifying the key matches the LeaseSet destination.
      • Validating the LeaseSet's cryptographic signature.
      • Checking if the LeaseSet is too old (expired).
      • Checking if the LeaseSet expires too far in the future.

      Note: Unlike RouterInfos, this validation is only done once at storage time. Afterward, LeaseSet.isCurrent() should be used to check currency.

      Parameters:
      key - the expected key (destination hash) for this LeaseSet
      leaseSet - the LeaseSet instance to validate
      Returns:
      a descriptive reason why the LeaseSet is invalid or expired, or null if the LeaseSet is valid
      Throws:
      UnsupportedCryptoException - if the LeaseSet uses an unsupported cryptographic type/signature
    • validateKeyMatch

      private String validateKeyMatch(Hash key, LeaseSet leaseSet)
      Check that the key matches the LeaseSet hash.
      Parameters:
      key - the expected key (destination hash) for this LeaseSet
      leaseSet - the LeaseSet instance to validate
      Returns:
      a descriptive reason why the key does not match, or null
    • validateSignature

      private String validateSignature(Hash key, LeaseSet leaseSet, String leaseBase32) throws UnsupportedCryptoException
      Verify the LeaseSet's cryptographic signature validity.
      Parameters:
      key - the expected key (destination hash) for this LeaseSet
      leaseSet - the LeaseSet instance to validate
      leaseBase32 - base32 of the LeaseSet hash, for logging
      Returns:
      a descriptive reason why the signature is invalid, or null
      Throws:
      UnsupportedCryptoException - if the signature type is unsupported
    • checkExpiredLeaseSet

      private String checkExpiredLeaseSet(Hash key, LeaseSet leaseSet, long earliest, long latest, long now, String idShort)
      Reject a LeaseSet whose timestamps are outdated (stale).
      Parameters:
      key - the expected key (destination hash) for this LeaseSet
      leaseSet - the LeaseSet instance to validate
      earliest - earliest relevant date
      latest - latest relevant date
      now - current time in ms, from the router clock
      idShort - shortened destination ID for logs and messages
      Returns:
      a descriptive reason why the LeaseSet is expired, or null
    • checkFutureExpiration

      private String checkFutureExpiration(LeaseSet leaseSet, int type, long latest, long now, String idShort)
      Reject a LeaseSet that expires too far into the future, to handle clock skew issues.
      Parameters:
      leaseSet - the LeaseSet instance to validate
      type - the LeaseSet type
      latest - latest relevant date
      now - current time in ms, from the router clock
      idShort - shortened destination ID for logs and messages
      Returns:
      a descriptive reason why the LeaseSet is rejected, or null
    • store

      public LeaseSet store(Hash key, LeaseSet leaseSet) throws IllegalArgumentException
      Store the LeaseSet without persisting it to disk.
      Specified by:
      store in class NetworkDatabaseFacade
      Parameters:
      key - the LeaseSet key
      leaseSet - the LeaseSet to store
      Returns:
      the previous entry for the key, or null
      Throws:
      IllegalArgumentException - if the LeaseSet is not valid
    • store

      public LeaseSet store(Hash key, LeaseSet leaseSet, boolean force) throws IllegalArgumentException
      Store the leaseSet.

      If the store fails due to unsupported crypto, it will negative cache the hash until restart.

      Parameters:
      key - the hash key
      leaseSet - the leaseSet to store
      force - always store even if not newer
      Returns:
      previous entry or null
      Throws:
      IllegalArgumentException - if the leaseSet is not valid
      UnsupportedCryptoException - if that's why it failed.
    • copyStoreMetadata

      private void copyStoreMetadata(LeaseSet rv, LeaseSet leaseSet)
      Copy the received-by / received-as-reply / received-as-published metadata flags from the incoming LeaseSet onto the stored copy, without re-storing the entry.
      Parameters:
      rv - the stored copy, non-null
      leaseSet - the incoming LeaseSet
    • checkForHashCollision

      private void checkForHashCollision(LeaseSet rv, LeaseSet leaseSet, boolean force)
      Reject a store whose LeaseSet hash collides with an existing LeaseSet for a different destination.
      Parameters:
      rv - the stored copy, or null
      leaseSet - the incoming LeaseSet
      force - if true, skip the collision check
      Throws:
      IllegalArgumentException - on a hash collision
    • resolveBlindData

      private void resolveBlindData(EncryptedLeaseSet encls, LeaseSet leaseSet)
      Resolve blind data for an encrypted LeaseSet so validate() can verify the signature, setting the secret before the destination.
      Parameters:
      encls - the encrypted LeaseSet
      leaseSet - the incoming LeaseSet, for the signing key
    • handleBlindStore

      private void handleBlindStore(EncryptedLeaseSet encls, LeaseSet leaseSet)
      After storing, handle the blind data bookkeeping: an encrypted LeaseSet we have now decrypted is stored under its own key, and a blinded-when-published LeaseSet marks its destination as blinded.
      Parameters:
      encls - the encrypted LeaseSet, or null
      leaseSet - the stored LeaseSet
    • isNewer

      public static boolean isNewer(LeaseSet a, LeaseSet b)
      Utility to determine if a is newer than b. Uses publish date if a and b are both LS2, else earliest lease date.
      Parameters:
      a - non-null
      b - non-null
      Returns:
      if a is newer than b
    • shouldAcceptLeaseSet

      static boolean shouldAcceptLeaseSet(LeaseSet stored, LeaseSet incoming, long now)
      Determine whether an incoming LeaseSet may replace the currently stored copy.

      The anti-clobber rule: a strictly-newer incoming copy always replaces the stored copy; an equal- or older-dated incoming copy is rejected so a late echo or duplicate cannot clobber fresher data (see isNewer(LeaseSet, LeaseSet)).

      Exception: when the stored copy has lapsed - its latest lease ends within Router.CLOCK_FUDGE_FACTOR of now - the stored copy carries no reachability value, so any incoming copy (still validated by the caller before store(Hash, LeaseSet)) is accepted to restore service. Without this, a hidden service that re-publishes the same LeaseSet2 generation (unchanged publish date) can never refresh a lapsed local copy, leaving the destination unreachable until the service happens to generate a brand-new LeaseSet2.

      Parameters:
      stored - the currently stored copy, non-null
      incoming - the incoming copy, non-null
      now - the current time in ms
      Returns:
      true if the incoming copy should replace the stored copy
    • validate

      private String validate(Hash key, RouterInfo routerInfo) throws IllegalArgumentException
      Determine whether this routerInfo will be accepted as valid and current given what we know now. Call this only on first store, to check the key and signature once.

      If the store fails due to unsupported crypto, it will banlist the router hash until restart and then throw UnsupportedCryptoException.

      Parameters:
      key - hash the entry is stored under, compared against the RouterInfo's own identity hash
      routerInfo - the RouterInfo about to be stored
      Returns:
      reason why the entry is not valid, or null if it is valid
      Throws:
      UnsupportedCryptoException - if that's why it failed.
      IllegalArgumentException
    • validate

      String validate(RouterInfo routerInfo) throws IllegalArgumentException
      Determine whether this routerInfo will be accepted as valid and current given what we know now.

      Call this before each use, to check expiration.

      Parameters:
      routerInfo - the router info to validate
      Returns:
      reason why the entry is not valid, or null if it is valid
      Throws:
      IllegalArgumentException
    • shouldSkipValidation

      private boolean shouldSkipValidation()
      Determines whether validation should be skipped based on initialization status or dummy communication system.
      Returns:
      true if validation should be skipped, false otherwise
    • getRouterId

      private String getRouterId(RouterInfo routerInfo)
      Generates a short identifier for a router based on its hash.
      Parameters:
      routerInfo - the RouterInfo to extract the ID from
      Returns:
      the first 6 characters of the base64-encoded router hash
    • banInvalidNTCPAddresses

      private boolean banInvalidNTCPAddresses(RouterInfo routerInfo, long now, String caps, String routerId)
      Checks for invalid NTCP2 addresses in the given RouterInfo and bans the router if any are found.
      Parameters:
      routerInfo - the RouterInfo to validate
      now - current timestamp in milliseconds
      caps - the capabilities string of the router
      routerId - the short ID of the router
      Returns:
      true if the router has invalid NTCP addresses and was banned, false otherwise
    • isUptimeLongEnough

      private boolean isUptimeLongEnough(long uptime)
      Checks if the router's uptime is long enough to begin validating other routers.

      The minimum uptime is determined by the property "router.validateRoutersAfter" (in minutes), or defaults to 20 minutes.

      Parameters:
      uptime - how long the router has been up, in milliseconds
      Returns:
      true if the uptime is sufficient, false otherwise
    • computeAdjustedExpiration

      private long computeAdjustedExpiration(int existingRouters)
      Computes the expiration time for a RouterInfo based on current network conditions.

      The expiration time can be customized via the "router.expireRouterInfo" property (in hours), or defaults based on the number of existing routers or whether this is a floodfill.

      Parameters:
      existingRouters - the number of routers currently stored on disk
      Returns:
      the adjusted expiration time in milliseconds
    • checkCountryBlocking

      private boolean checkCountryBlocking(RouterInfo routerInfo, String caps, String routerId, Hash h)
      Checks if the given router should be blocked due to country restrictions.

      This includes: - Strict country mode - Hidden mode - Configuration-based country bans - XG router bans.

      Parameters:
      routerInfo - the RouterInfo to evaluate
      caps - the capabilities string of the router
      routerId - the short ID of the router
      h - the Hash of the router
      Returns:
      true if the router should be blocked, false otherwise
    • checkXG

      private boolean checkXG(RouterInfo routerInfo, String caps, String routerId, Hash h)
      Whether the router should be XG-banned: an X-tier (unlimited bandwidth) router advertising the G (no tunnels) capability. The ban is one hour.
      Parameters:
      routerInfo - router under validation, source of the IP:port logged
      caps - capability string, checked for 'f' to label the ban log
      routerId - truncated base64 hash, used only in the log line
      h - router hash the ban is written against
      Returns:
      true if the router is an XG router, banlisted here or already
    • checkLU

      private boolean checkLU(RouterInfo routerInfo, String caps, String routerId, Hash h)
      Ban LU (low bandwidth) routers unconditionally for 1 hour. These routers flood the network with no meaningful bandwidth contribution.
      Parameters:
      routerInfo - router under validation, source of the IP:port logged
      caps - capability string, null means no ban is possible
      routerId - truncated base64 hash, used only in the log line
      h - router hash the ban is written against
      Returns:
      true if the router is a low-tier unreachable peer
    • isRouterXG

      private boolean isRouterXG(RouterInfo routerInfo, boolean isUs)
      Determines whether the given router qualifies as an XG router that should be blocked.

      An XG router is defined as: - Has the G capability (no tunnels) - Has the X (unlimited bandwidth) capability.

      Parameters:
      routerInfo - the RouterInfo to evaluate
      isUs - true if the router is the local router
      Returns:
      true if the router is an XG router and should be blocked
    • checkFutureRouterInfo

      private String checkFutureRouterInfo(RouterInfo routerInfo, long now, String caps, String routerId, Hash h, boolean isUs)
      Checks if the given router info was published in the future and bans it if so.
      Parameters:
      routerInfo - the RouterInfo to evaluate
      now - current timestamp in milliseconds
      caps - the capabilities string of the router
      routerId - the short ID of the router
      h - the Hash of the router
      isUs - true if the router is the local router
      Returns:
      a descriptive string if the router is from the future, null otherwise
    • checkRouterVersion

      private String checkRouterVersion(RouterInfo routerInfo, String caps, String routerId, Hash h)
      Checks if the given router is running a version older than the minimum allowed.

      If so, it bans the router until restart.

      Parameters:
      routerInfo - the RouterInfo to evaluate
      caps - the capabilities string of the router
      routerId - the short ID of the router
      h - the Hash of the router
      Returns:
      a descriptive string if the router is too old, null otherwise
    • dropSlowRouter

      private String dropSlowRouter(RouterInfo routerInfo, long now, int existing, String caps, String routerId)
      Checks if the given router should be dropped due to being a slow tier (K, L, or M) and outdated.
      Parameters:
      routerInfo - the RouterInfo to evaluate
      now - current timestamp in milliseconds
      existing - number of routers currently stored on disk
      caps - the capabilities string of the router
      routerId - the short ID of the router
      Returns:
      a descriptive string if the router should be dropped, null otherwise
    • lookupRIUnvalidated

      RouterInfo lookupRIUnvalidated(Hash key)
      Look up a peer's RouterInfo without running the full validate(RouterInfo) ban cascade.

      lookupLocallyWithoutValidation(Hash) returns any database entry, so the entry type is checked here; lookupRouterInfoLocally(Hash) would have done that plus the validation. Callers must only use the result where a validating lookup would answer the same question — presence, or a predicate over the peer's own immutable RouterInfo fields.

      Parameters:
      key - the peer hash
      Returns:
      the RouterInfo, or null if this peer is not held as a RouterInfo
    • checkAddressesAndIntroducers

      private String checkAddressesAndIntroducers(RouterInfo routerInfo, String caps, String routerId, boolean isUs, boolean dontFail)
      Checks if the router has no valid addresses or introducers and has been published too long ago.

      Only applies once the router is past the 54 minute "introduced" window and while still inside the startup grace period (dontFail) is skipped, so a fresh router is never dropped on this check.

      Parameters:
      routerInfo - the RouterInfo to evaluate
      caps - the capabilities string of the router
      routerId - the short ID of the router
      isUs - true if the router is the local router
      dontFail - whether to skip failure checks
      Returns:
      a descriptive string if the router should be dropped, null otherwise
    • checkExpirationBasedDrop

      private String checkExpirationBasedDrop(RouterInfo routerInfo, boolean upLongEnough, long adjustedExpiration, long now, String caps, String routerId, boolean isUs)
      Checks if the router has expired based on configured expiration time.
      Parameters:
      routerInfo - the RouterInfo to evaluate
      upLongEnough - true if the local router has been up long enough
      adjustedExpiration - the computed expiration time in milliseconds
      now - current timestamp in milliseconds
      caps - the capabilities string of the router
      routerId - the short ID of the router
      isUs - true if the router is the local router
      Returns:
      a descriptive string if the router should be dropped, null otherwise
    • checkShortExpiration

      private String checkShortExpiration(RouterInfo routerInfo, String caps, String routerId, boolean isUs)
      Why the router's short expiration is disqualifying, or null. Once a RouterInfo is older than ROUTER_INFO_EXPIRATION_SHORT, an SSU-only peer with no introducers, or one unreachable on every transport, is dropped.
      Parameters:
      routerInfo - router to check, null returns null
      caps - capability string, used only to build the reason text
      routerId - truncated base64 hash, used only in the reason text
      isUs - true to exempt our own RouterInfo from being dropped
      Returns:
      reason to drop the entry, or null to keep it
    • checkStaleRouterInfo

      private String checkStaleRouterInfo(RouterInfo routerInfo, boolean upLongEnough, int existing, String routerId, boolean isUs)
      Whether an otherwise-acceptable RouterInfo has aged past computeAdjustedExpiration(int) and should now be dropped.

      This is the last-resort stale-entry policy, applied after the address, introducer, expiration-property, and short-expiration checks. It only runs once the local router has been up long enough (isUptimeLongEnough(long)) and never for the local router, and it is suppressed while fewer than MIN_REMAINING_ROUTERS routers are stored on disk, so a thinning network does not drop down to nothing. Capabilities are not consulted here; checkAddressesAndIntroducers(RouterInfo, String, String, boolean, boolean) is the check for missing transports.

      Parameters:
      routerInfo - the RouterInfo to evaluate
      upLongEnough - true if the local router has been up long enough
      existing - the number of routers currently stored on disk
      routerId - the short ID of the router
      isUs - true if the router is the local router
      Returns:
      a descriptive string if the router should be dropped, null otherwise
    • store

      public RouterInfo store(Hash key, RouterInfo routerInfo) throws IllegalArgumentException
      Store the routerInfo.

      If the store fails due to unsupported crypto, it will banlist the router hash until restart and then throw UnsupportedCrytpoException.

      Specified by:
      store in class NetworkDatabaseFacade
      Parameters:
      key - the hash key
      routerInfo - the router info to store
      Returns:
      previous entry or null
      Throws:
      IllegalArgumentException - if the routerInfo is not valid
      UnsupportedCryptoException - if that's why it failed.
    • store

      RouterInfo store(Hash key, RouterInfo routerInfo, boolean persist) throws IllegalArgumentException
      Store the routerInfo.

      If the store fails due to unsupported crypto, it will banlist the router hash until restart and then throw UnsupportedCrytpoException.

      Parameters:
      key - the hash key
      routerInfo - the router info to store
      persist - whether to persist to disk
      Returns:
      previous entry or null
      Throws:
      IllegalArgumentException - if the routerInfo is not valid
      UnsupportedCryptoException - if that's why it failed.
    • stripStoreWrapper

      static String stripStoreWrapper(String message)
      Strip the "Invalid NetDbStore attempt" wrapper from a store rejection message, keeping the capability flags and the Router [id] the console renders as a link.
      Parameters:
      message - the rejection message, may be null
      Returns:
      the bare rejection detail, for log output
    • addContact

      private void addContact(Hash key, RouterInfo routerInfo)
      Insert a newly-stored peer into the routing buckets, gated on two local-only checks (no wire-format change):
      1. verify-before-add — a peer merely named in someone else's DatabaseSearchReply has never answered us, so it waits in _unverifiedPeers until direct-contact evidence arrives (a reply, a successful send, or an established session). This is the main dead-peer contamination vector for the routing table.
      2. IP diversity — cap how many entries of one IP group (a /16 for IPv4, a /48 for IPv6) one bucket and the whole table will hold, so a single entity cannot eclipse our routing table.
      Parameters:
      key - the peer hash
      routerInfo - the peer's RouterInfo (for its addresses)
    • addContact

      boolean addContact(Hash key)
      Policy entry point for peers learned from search replies, where no RouterInfo is in hand yet: direct-contact gate only. The diversity check runs when the RI lands via store(Hash, LeaseSet). Rejected peers are queued and probed/promoted by the ProbeStalePeerJob cycle.
      Parameters:
      key - the peer hash
      Returns:
      true if the peer was inserted into its bucket now
    • queueUnverified

      private void queueUnverified(Hash key)
      Queue a peer for later bucket promotion once it proves itself, sweeping expired entries when the queue is full.
      Parameters:
      key - peer hash to hold pending direct-contact evidence
    • hasDirectContact

      boolean hasDirectContact(Hash peer)
      Have we ever heard from this peer directly, as opposed to merely being told about it? An established session or a profile with a received message or successful send counts.
      Parameters:
      peer - the peer hash, non-null
      Returns:
      true if the peer has answered us at some point
    • hasDirectContact

      static boolean hasDirectContact(PeerProfile prof)
      Direct-contact test on profile evidence only: heard-from or successful-send, never heard-about (that only means someone mentioned them). Null-safe.
      Parameters:
      prof - the peer's profile or null
      Returns:
      true if the profile shows direct contact
    • promoteUnverifiedPeers

      int promoteUnverifiedPeers()
      Move pending peers that have earned direct-contact evidence into the routing buckets, and drop those that waited too long. Called by ProbeStalePeerJob each cycle, which also probes the pending peers so live ones earn evidence quickly.
      Returns:
      number promoted into buckets
    • getUnverifiedPeerCount

      int getUnverifiedPeerCount()
      The pending-verification queue size, for tests and the debug console.
      Returns:
      zero or more
    • getUnverifiedPeersSnapshot

      Set<Hash> getUnverifiedPeersSnapshot()
      Snapshot of the pending-verification queue, for the probe cycle to target. The queue itself stays internal.
      Returns:
      non-null copy of the pending peer hashes
    • ipDiversityAllows

      boolean ipDiversityAllows(Hash key, RouterInfo routerInfo)
      Would adding this peer to its bucket exceed the per-bucket or global IP-group caps? Peers with no literal-IP address are unconstrained.
      Parameters:
      key - the peer hash
      routerInfo - the peer's RouterInfo
      Returns:
      true if the diversity policy allows the add
    • sharesIPGroup

      private boolean sharesIPGroup(Set<Long> groups, Hash peer)
      Does this bucket entry share an IP group with any of the given groups?
      Parameters:
      groups - IP group keys to test against
      peer - bucket entry whose RouterInfo supplies the groups
      Returns:
      true if the entry is a known RouterInfo matching one of them
    • ipGroups

      static Set<Long> ipGroups(RouterInfo ri)
      The distinct IP groups of a router's literal-IP addresses. Package private for testing.
      Parameters:
      ri - router whose literal-IP addresses are grouped
      Returns:
      non-null set of group keys, empty if no literal IPs
    • ipGroup

      static Long ipGroup(byte[] ip)
      IP group key: /16 for IPv4, /48 for IPv6, packed into a long with a family marker bit so the two families never collide. Hostnames (getIP() null) have no group.
      Parameters:
      ip - 4- or 16-byte address, or null
      Returns:
      the group key, or null if not a literal IP
    • processStoreFailure

      private void processStoreFailure(Hash h, DatabaseEntry entry) throws UnsupportedCryptoException
      If the validate fails, call this to determine if it was because of unsupported crypto.

      If so, this will banlist-forever the router hash or permanently negative cache the dest hash, and then throw the exception. Otherwise it does nothing.

      Parameters:
      h - hash the failed store was attempted under
      entry - the entry that failed validation, RouterInfo or LeaseSet
      Throws:
      UnsupportedCryptoException - if that's why it failed.
    • checkLeaseSetSigType

      private void checkLeaseSetSigType(Hash h, LeaseSet ls) throws UnsupportedCryptoException
      Reject LeaseSets with unsupported signature types; negative-cache the destination permanently.
      Parameters:
      h - destination hash the store was attempted under, log-only
      ls - LeaseSet whose key certificate names the signature type
      Throws:
      UnsupportedCryptoException - if the sig type is unavailable or RSA
    • checkRouterInfoSigType

      private void checkRouterInfoSigType(Hash h, RouterInfo ri) throws UnsupportedCryptoException
      Reject RouterInfos with unsupported signature types; ban until restart.
      Parameters:
      h - router hash the permanent ban is written against
      ri - RouterInfo that failed signature validation
      Throws:
      UnsupportedCryptoException - if the sig type is unavailable
    • sigTypeDescription

      private static String sigTypeDescription(KeyCertificate kc, SigType type)
      Human-readable signature type for log messages.
      Parameters:
      kc - key certificate whose sig type code is the fallback text
      type - resolved signature type, null when it is not recognized
      Returns:
      the sig type name, or the raw type code when unnamed
    • fail

      public void fail(Hash dbEntry)
      Final remove for a leaseset. For a router info, will look up in the network before dropping.
      Specified by:
      fail in class NetworkDatabaseFacade
      Parameters:
      dbEntry - the key of the entry to fail
    • lookupBeforeDropping

      protected void lookupBeforeDropping(Hash peer, RouterInfo info)
      Don't use directly - see F.N.D.F. override.
      Parameters:
      peer - the router hash to drop after the lookup failure
      info - the router info
    • dropAfterLookupFailed

      boolean dropAfterLookupFailed(Hash peer)
      Final remove for a router info. Do NOT use for leasesets.
      Parameters:
      peer - the peer hash
      Returns:
      true if logged
    • unpublish

      public void unpublish(LeaseSet localLeaseSet)
      Description copied from class: NetworkDatabaseFacade
      Unpublish a LeaseSet from the network database.
      Specified by:
      unpublish in class NetworkDatabaseFacade
      Parameters:
      localLeaseSet - the LeaseSet to unpublish
    • search

      abstract SearchJob search(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, boolean isLease)
      Begin a kademlia-style iterative search for the key, which can take up to timeoutMs and will fire the appropriate jobs on success or timeout (or if the search completes without any match).

      Abstract because only a concrete facade knows how to reach floodfills; FloodfillNetworkDatabaseFacade implements this with IterativeSearchJob. Data-plane callers such as lookupRouterInfo(Hash, Job, Job, long) route transit traffic through here, so there is deliberately no base fallback: a facade that cannot search must say so at compile time.

      Parameters:
      key - the hash to search for
      onFindJob - job on find
      onFailedLookupJob - job on failure
      timeoutMs - timeout in ms
      isLease - whether searching for lease
      Returns:
      implementation-defined; results are delivered via the callbacks
    • search

      abstract SearchJob search(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, boolean isLease, Hash fromLocalDest)
      Search using the client's tunnels; see search(Hash, Job, Job, long, boolean).
      Parameters:
      key - the hash to search for
      onFindJob - job on find
      onFailedLookupJob - job on failure
      timeoutMs - timeout in ms
      isLease - whether searching for lease
      fromLocalDest - use these tunnels for the lookup, or null for exploratory
      Returns:
      implementation-defined; results are delivered via the callbacks
    • getLeases

      public Set<LeaseSet> getLeases()
      Description copied from class: NetworkDatabaseFacade
      All known LeaseSets for display.
      Overrides:
      getLeases in class NetworkDatabaseFacade
      Returns:
      set of LeaseSets, or empty
    • getClientLeases

      public Set<LeaseSet> getClientLeases()
      LeaseSets published by this router's clients.
      Overrides:
      getClientLeases in class NetworkDatabaseFacade
      Returns:
      the local LeaseSets, or null before the database is initialized
    • getPublishedLeases

      public Set<LeaseSet> getPublishedLeases()
      LeaseSets published to the network.
      Overrides:
      getPublishedLeases in class NetworkDatabaseFacade
      Returns:
      the local LeaseSets that shouldPublishLeaseSet approves, or null before the database is initialized
    • getUnpublishedLeases

      public Set<LeaseSet> getUnpublishedLeases()
      LeaseSets not published to the network.
      Overrides:
      getUnpublishedLeases in class NetworkDatabaseFacade
      Returns:
      the local LeaseSets that shouldPublishLeaseSet rejects, or null before the database is initialized
    • getFloodfillLeases

      public Set<LeaseSet> getFloodfillLeases()
      LeaseSets stored in the floodfill database.
      Overrides:
      getFloodfillLeases in class NetworkDatabaseFacade
      Returns:
      the stored LeaseSets, or null before the database is initialized
    • getRouters

      public Set<RouterInfo> getRouters()
      RouterInfos stored in the database.
      Overrides:
      getRouters in class NetworkDatabaseFacade
      Returns:
      the stored RouterInfos, empty in client mode, or null before the database is initialized
    • getPeerTimeout

      public int getPeerTimeout(Hash peer)
      How long to wait for one peer's reply, scaled from its profile.
      Parameters:
      peer - the router hash whose profile sets the timeout; must not be null
      Returns:
      the timeout in ms, 7500-45000; 45000 when there is no profile data
    • sendStore

      abstract void sendStore(Hash key, DatabaseEntry ds, Job onSuccess, Job onFailure, long sendTimeout, Set<Hash> toIgnore)
      See implementation in FNDF.
      Parameters:
      key - the DatabaseEntry hash
      ds - the database entry
      onSuccess - may be null; called on reply-based store success (not used for wide-flood-only RI path)
      onFailure - may be null; called when no floodfill peers are available or reply-based store fails
      sendTimeout - timeout in ms for the reply-based FloodfillStoreJob path
      toIgnore - may be null, if non-null, all attempted and skipped targets will be added as of 0.9.53; passed through to FloodfillStoreJob (unused for wide-flood-only RI path)
    • lookupFailed

      void lookupFailed(Hash key)
      Increment in the negative lookup cache.
      Parameters:
      key - for Destinations or RouterIdentities
    • lookupTimeout

      void lookupTimeout(Hash key)
      Pure-timeout search failure (no peer replied). Higher negative-cache threshold than lookupFailed(Hash).
      Parameters:
      key - the key that timed out
    • isNegativeCached

      boolean isNegativeCached(Hash key)
      Is the key in the negative lookup cache?
      Parameters:
      key - for Destinations or RouterIdentities
      Returns:
      true if cached
    • peekNegativeCached

      public boolean peekNegativeCached(Hash key)
      Negative-cache check without recording an abort stat. Used by callers that need to branch on cache state before deciding cooldown/stats, so a single send path does not double-count netDb.negativeCache.
      Parameters:
      key - the key to check
      Returns:
      true if the key is negatively cached (transient or permanent)
    • clearNegativeCache

      public void clearNegativeCache(Hash key)
      Clear any transient (non-permanent) negative-cache entry for the given key so the next lookupLeaseSet(Hash, Job, Job, long) performs a real search instead of aborting instantly. Permanent negatives (failPermanently(Destination)) are left intact. Used by the outbound client message path to re-probe a destination whose LeaseSet was valid recently but is undergoing a transient gap.
      Parameters:
      key - the destination hash
    • failPermanently

      void failPermanently(Destination dest)
      Negative cache until restart.
      Parameters:
      dest - the Destination to remember as unreachable until restart
    • isNegativeCachedForever

      public boolean isNegativeCachedForever(Hash key)
      Is it permanently negative cached?
      Overrides:
      isNegativeCachedForever in class NetworkDatabaseFacade
      Parameters:
      key - only for Destinations; for RouterIdentities, see Banlist
      Returns:
      whether negative cached forever
    • renderStatusHTML

      public void renderStatusHTML(Writer out) throws IOException
      Render the KBucket summary and a per-bucket table. Writes nothing before startup(). The individual keys are not listed; they carry no diagnostic value and made the page unreadable.
      Specified by:
      renderStatusHTML in interface Service
      Overrides:
      renderStatusHTML in class NetworkDatabaseFacade
      Parameters:
      out - where to write the HTML
      Throws:
      IOException - on write errors
    • peerRenderer

      private java.util.function.Function<String,String> peerRenderer()
      Turns a base64 hash into the standard router-info reference (flag, netdb link, bandwidth) for the bucket entry lists.
      Returns:
      a function mapping a base64 hash to html
    • _t

      private String _t(String s)
      Console translation for the debug page strings.
      Parameters:
      s - English string to look up
      Returns:
      the localized text, or s itself when no translation exists
    • buildBucketTable

      static String buildBucketTable(List<String[]> rows, int capacity, java.util.function.Function<String,String> entryRenderer, java.util.function.Function<String,String> tr)
      Build the bucket table from the rows of KBucketSet.getDebugBucketRows(): bucket index, XOR-distance bit range, entry count as a details/summary disclosure whose expanded content is the entry hashes rendered by the given function, and fill as a percentage of capacity. Package-visible for testing.
      Parameters:
      rows - the bucket rows
      capacity - the per-bucket capacity, greater than zero
      entryRenderer - renders each entry hash as html
      tr - translates a label, identity in tests
      Returns:
      the table html, never null
    • entryLinks

      static String entryLinks(String keys, java.util.function.Function<String,String> entryRenderer)
      Entry hashes rendered through the given function, sorted for stable display.
      Parameters:
      keys - comma-separated base64 hashes, may be empty
      entryRenderer - renders each hash as html
      Returns:
      the entries html, or an em-dash if there are no keys
    • getDebugStats

      public long[] getDebugStats()
      Debug overview stats: total keys, bucket count, per-bucket capacity and fullest bucket size, as {keys, buckets, capacity, fullest}. Null where the facade has no kademlia buckets. Reads the live bucket set under its read lock.
      Overrides:
      getDebugStats in class NetworkDatabaseFacade
      Returns:
      the stats, or null
    • toString

      public String toString()
      Name this netdb for use in log messages.
      Overrides:
      toString in class Object
      Returns:
      "MainNetDb" for the main netdb, or "ClientNetDb [xxxxxxxx]" with the first 8 base32 characters of the netdb id for a client netdb
    • getBlockedCountries

      private Set<String> getBlockedCountries()
      Blocked countries, parsed once from the property and cached.
      Returns:
      lower-case country codes from router.blockCountries, empty if none are configured
    • getStoredRouterInfoCount

      public int getStoredRouterInfoCount()
      Number of RouterInfo files stored on disk, if using PersistentDataStore.
      Returns:
      number of RIs on disk, or 0 if not using persistent storage
    • refreshClientLeaseSets

      private void refreshClientLeaseSets()
      Refresh client lease sets.
    • pruneLeaseSetTracking

      private void pruneLeaseSetTracking()
      Evict oldest tracked entries to cap map size.
    • proactivelyRefreshIfExpiring

      private boolean proactivelyRefreshIfExpiring(Hash key, long now, NamingService ns)
      Refresh a tracked LeaseSet early when it is about to expire. Always uses client tunnels for client subDb refresh.
      Parameters:
      key - destination hash of the tracked LeaseSet
      now - current router time in ms, compared with the lease expiry
      ns - naming service used only to name the entry in the log
      Returns:
      true if the proactive refresh was triggered
    • logName

      private static String logName(NamingService ns, Hash key)
      Best-effort display name for a tracked LeaseSet in logs: the registered hostname when available, otherwise a truncated base32. Never gates refresh.
      Parameters:
      ns - naming service to reverse-lookup, may be null
      key - LeaseSet hash to name, used for the base32 fallback
      Returns:
      the registered hostname, or the hash as [8 base32 chars]