java.lang.Object
net.i2p.router.web.helpers.NetDbRenderer

class NetDbRendererextends Object
Renders the network database (netdb) information for the router console. Handles router and leaseset listings, search, and statistics. Optimized for performance with parallel rendering and optional reverse DNS lookups.
  • Field Details

    • _context

      private final RouterContext _context
      The router context.
    • _routerCache

      private final NetDbRouterCache _routerCache
      Cache of router infos for the display.
    • _log

      private final Log _log
      Logger for the netdb page.
    • TWO_DECIMALS

      private static final DecimalFormat TWO_DECIMALS
      Formatter for numbers with two decimals.
    • COMMA_SPACE_SPLIT

      private static final Pattern COMMA_SPACE_SPLIT
      Splits a comma or space separated list.
    • LOOKUP_WAIT

      public static final int LOOKUP_WAIT
      How long to wait for a router lookup before giving up.
      See Also:
    • LS_LOOKUP_WAIT

      public static final int LS_LOOKUP_WAIT
      How long to wait for a remote lease set lookup.
      See Also:
    • localLSCount

      public int localLSCount
      Number of local lease sets, set during lease set rendering.
    • _renderedLeaseSetKeys

      private final Set<Hash> _renderedLeaseSetKeys
      LeaseSet keys already rendered for this request, so a LeaseSet stored in more than one facade is shown only once. A fresh NetDbRenderer is created per request, so no reset is needed.
    • _organizer

      private final ProfileOrganizer _organizer
      Source of the peer profiles.
    • BATCH_SIZE

      private final int BATCH_SIZE
      Router lookups run per batch.
    • RENDER_TASK_TIMEOUT

      private static final long RENDER_TASK_TIMEOUT
      Bound on a single parallel render task so a stalled common pool cannot hang the netdb page.
      See Also:
    • _agoMemo

      private final NetDbRenderer.AgoMemo _agoMemo
      Memo for the "{0} ago" renders of renderRouterInfo(StringBuilder, RouterInfo, boolean), one per renderer.
    • _agoFormat

      private final java.util.function.Function<String,String> _agoFormat
      Expensive translator behind agoMemo(String), bound once so the memo never sees a fresh lambda.
    • _memoryUsedMB

      private volatile long _memoryUsedMB
      Memoized result of memoryUsedMB(), -1 until first use.
    • _memoryUsedValid

      private volatile boolean _memoryUsedValid
      Whether _memoryUsedMB holds a value for this render pass.
    • _capTooltip

      private volatile String _capTooltip
      Memoized capability tooltip for this render pass, null until first use.
    • now

      private long now
      The current time for the age calculations.
    • LOOKUP_INTERVAL_MS

      private static final long LOOKUP_INTERVAL_MS
      Interval between background reverse DNS lookups. 100ms = 10 lookups/second. Gentle on the system, no burst.
      See Also:
    • LOOKUPS_BEFORE_PAUSE

      private static final int LOOKUPS_BEFORE_PAUSE
      Pause after this many lookups to let the system breathe. 500 lookups at 10/sec = 50 seconds, then 1 second pause.
      See Also:
    • PAUSE_AFTER_BATCH_MS

      private static final long PAUSE_AFTER_BATCH_MS
      Pause between lookup batches, in ms.
      See Also:
    • _rdnsQueue

      private static final Queue<String> _rdnsQueue
      Pending IPs for background reverse DNS resolution.
    • _rdnsQueued

      private static final Set<String> _rdnsQueued
      Dedup set — prevents the same IP from being queued multiple times.
    • _rdnsWorkerRunning

      private static final AtomicBoolean _rdnsWorkerRunning
      Guards against multiple concurrent background workers.
    • isRendered

      private boolean isRendered
      True once the summary was rendered.
    • BW_CAPS

      private static final char[] BW_CAPS
      Symbols marking the bandwidth tiers.
    • BW_LABELS

      private static final String[] BW_LABELS
      Labels for the bandwidth tiers.
    • BW_DESCRIPTIONS

      private static final String[] BW_DESCRIPTIONS
      Descriptions of the bandwidth tiers.
    • TALLIES_CACHE_MS

      private static final long TALLIES_CACHE_MS
      How long cached overview tallies stay valid. Well under the ten second /netdb auto-refresh, so it only bounds how long a hash whose country resolves late stays uncounted.
      See Also:
    • _cachedTalliesSource

      private static volatile List<RouterInfo> _cachedTalliesSource
      Tally source list the cached tallies were computed from.
    • _cachedTallies

      private static volatile NetDbRenderer.RouterTallies _cachedTallies
      Cached tallies, valid only for _cachedTalliesSource.
    • _cachedTalliesUntil

      private static volatile long _cachedTalliesUntil
      Expiry for _cachedTallies.
    • reverseLookupCache

      private final LHMCache<String, NetDbRenderer.CacheEntry> reverseLookupCache
      Reverse DNS cache with TTL (24 hours). Small cache since we rely on file-backed rdnsCache in CommSystemFacadeImpl.
    • TTL_24_HOURS

      private static final long TTL_24_HOURS
      Cache lifetime of 24 hours, in ms.
      See Also:
    • SSU

      private static final int SSU
      Filter bit for SSU routers.
      See Also:
    • SSUI

      private static final int SSUI
      Filter bit for SSU introducers.
      See Also:
    • NTCP

      private static final int NTCP
      Filter bit for NTCP routers.
      See Also:
    • IPV6

      private static final int IPV6
      Filter bit for IPv6 routers.
      See Also:
    • TNAMES

      private static final String[] TNAMES
      Display names of the transport filter bits.
  • Constructor Details

    • NetDbRenderer

      public NetDbRenderer(RouterContext ctx)
      Create a renderer bound to the given context.
      Parameters:
      ctx - the router context
  • Method Details

    • fmt

      private static String fmt(double val)
      Formats a number with two decimals.
      Parameters:
      val - the number to format
      Returns:
      the formatted text
    • isFloodfill

      public boolean isFloodfill()
      Whether the router is a floodfill.
      Returns:
      true if this router is a floodfill
    • matchesCapabilities

      private boolean matchesCapabilities(RouterInfo ri, String capabilities)
      Whether the router matches all capability characters in the filter.
      Parameters:
      ri - the router to check
      capabilities - capability characters that must all be present (e.g. "fK")
      Returns:
      whether the router's capability string contains every character
    • renderRouterInfoHTML

      public void renderRouterInfoHTML(Writer out, int pageSize, int page, String routerPrefix, String version, String country, String family, String capabilities, String ipAddress, String sybil, int port, int highPort, SigType signatureType, EncType encryptionType, String mtu, String ipv6Address, String ssuCapabilities, String transport, int cost, int introducerCount) throws IOException
      Renders router information matching search criteria to the given writer. Supports filtering by version, country, family, capabilities, IP, port, etc. Streams results to reduce memory pressure on low-memory systems. Performs reverse DNS lookups in parallel if enabled.
      Parameters:
      out - Writer to output HTML
      pageSize - number of results per page
      page - zero-based page index
      routerPrefix - optional base64 hash prefix to filter routers (null for all)
      version - optional version string to filter routers
      country - optional country code(s) (comma/space separated) to filter routers
      family - optional router family name to filter routers
      capabilities - optional capability characters (e.g. "fK") to match all
      ipAddress - optional IPv4 address or prefix to filter routers
      sybil - optional; if non-null, collects hashes for Sybil analysis
      port - optional port or start of range (used with highPort)
      highPort - optional end of port range
      signatureType - optional signature type to filter routers
      encryptionType - optional encryption type to filter routers
      mtu - optional MTU value to filter routers
      ipv6Address - optional IPv6 address or prefix to filter routers
      ssuCapabilities - optional SSU capability characters to match
      transport - optional transport style (e.g., "NTCP", "SSU")
      cost - optional cost value to filter router addresses
      introducerCount - ignored, retained for signature compatibility
      Throws:
      IOException - if writing fails
    • appendUrlParam

      private void appendUrlParam(StringBuilder sb, String key, String value)
      Appends a URL parameter to the given StringBuilder if the value is not null.
      Parameters:
      sb - StringBuilder to append to
      key - URL parameter name
      value - parameter value, may be null
    • writeNoResults

      private void writeNoResults(StringBuilder buf, String routerPrefix, String version, String country, String family, String capabilities, String ipAddress, int port, int highPort, String mtu, String ipv6Address, String ssuCapabilities, int cost, SigType signatureType, EncType encryptionType, String transport)
      Writes a message indicating no routers matched the search criteria.
      Parameters:
      buf - buffer the "no routers matched" HTML is appended to
      routerPrefix - optional router hash prefix
      version - optional version string
      country - optional country code
      family - optional family name
      capabilities - optional capability string
      ipAddress - optional IPv4 address
      port - optional port or start of range
      highPort - optional end of port range
      mtu - optional MTU value
      ipv6Address - optional IPv6 address
      ssuCapabilities - optional SSU capabilities
      cost - optional address cost
      signatureType - optional signature type
      encryptionType - optional encryption type
      transport - optional transport style
    • paginate

      private void paginate(StringBuilder buf, StringBuilder ubuf, int page, int pageSize, boolean morePages, int sz)
      Renders pagination controls.
      Parameters:
      buf - buffer the pagination HTML is appended to
      ubuf - URL parameters for links
      page - current page (0-based)
      pageSize - results per page
      morePages - true if there are more pages after this one
      sz - total number of results
    • isUnreachable

      private boolean isUnreachable(RouterInfo ri)
      Checks whether the router is marked unreachable.
      Parameters:
      ri - the router info to check
      Returns:
      true if unreachable
    • lookupRouterInfoWithWait

      private RouterInfo lookupRouterInfoWithWait(NetworkDatabaseFacade networkDatabase, Hash hash, long timeout)
      Looks up a RouterInfo by its hash with a timeout. Tries local lookup first, then remote, then local again.
      Parameters:
      networkDatabase - the network database facade
      hash - the router hash
      timeout - max time to wait in milliseconds
      Returns:
      the RouterInfo or null if not found
    • precacheReverseDNSLookups

      public Map<String,String> precacheReverseDNSLookups(Collection<RouterInfo> routers)
      Pre-resolves reverse DNS for the given routers, returning the cached results and queuing the rest for background staggered lookups.
      Parameters:
      routers - routers whose primary IPs to resolve
      Returns:
      map of IP to hostname for already-cached lookups
    • enqueueRdnsLookups

      private void enqueueRdnsLookups(List<String> ips)
      Queue uncached IPs for background staggered reverse DNS lookup. The background worker processes one lookup every LOOKUP_INTERVAL_MS, with a pause after every LOOKUPS_BEFORE_PAUSE lookups. Results accumulate in rdnsCache for future page loads.
      Parameters:
      ips - numeric addresses to resolve, as formatted for display; addresses already queued are ignored
    • startRdnsWorker

      private void startRdnsWorker()
      Start the background staggered rdns worker if not already running. Uses the async getCanonicalHostName() to avoid blocking on DNS/WHOIS.
    • runRdnsWorker

      private void runRdnsWorker()
      Staggered reverse-DNS worker: drains the RDNS queue one lookup per LOOKUP_INTERVAL_MS, pausing after every LOOKUPS_BEFORE_PAUSE. Runs on a daemon thread.
    • renderLeaseSetHTML

      public void renderLeaseSetHTML(Writer out, boolean debug, Hash client) throws IOException
      Renders all leasesets.
      Parameters:
      out - Writer to output HTML
      debug - if true, sort by distance and show debug info
      client - if non-null, render only leasesets for that client
      Throws:
      IOException - if an I/O error occurs
    • renderLeaseSetListFragment

      public void renderLeaseSetListFragment(Writer out, boolean debug) throws IOException
      Renders the leaseset listing and keyspace estimate for the contentonly fragment mode of the netdb page, reusing the full lease list render.
      Parameters:
      out - the writer that receives the leaseset listing HTML
      debug - if true, show debug info
      Throws:
      IOException - if an I/O error occurs
    • renderLocalLeaseSetList

      public void renderLocalLeaseSetList(Writer out) throws IOException
      Renders the local (per-client) leaseset listing, wrapping the lease tables in the #lsWrapper div so the netdb page refreshes them with the same contentonly fragment path as the remote listing. The summary table is emitted before the div, mirroring the remote layout. Used by both the full local netdb page and the fragment mode.
      Parameters:
      out - the writer that receives the local leaseset listing HTML
      Throws:
      IOException - if an I/O error occurs
    • renderLocalSummary

      public void renderLocalSummary(Writer out) throws IOException
      Renders the local leaseset summary header (hidden until JS shows it).
      Parameters:
      out - where the HTML is written
      Throws:
      IOException - if the writer fails
    • renderLeaseSet

      public void renderLeaseSet(Writer out, String hostname, boolean debug) throws IOException
      Renders a single leaseset by hostname or b32.
      Parameters:
      out - Writer to output HTML
      hostname - the destination b32, full hash, or hostname
      debug - if true, show debug info
      Throws:
      IOException - if an I/O error occurs
    • renderLeaseSet

      private void renderLeaseSet(StringBuilder buf, LeaseSet ls, boolean debug, long now, boolean linkSusi, String distance)
      Renders a single LeaseSet as HTML.
      Parameters:
      buf - buffer the LeaseSet HTML is appended to
      ls - the LeaseSet to render
      debug - if true, include debug info like distance
      now - current time for expiry calculation
      linkSusi - if true, link to susidns (unused)
      distance - hash distance from local router (for debug)
    • getLocalClientNickname

      private String getLocalClientNickname(Hash key)
      Local client nickname for a destination hash.
      Parameters:
      key - the destination hash
      Returns:
      the nickname or a truncated base64 hash
    • renderStatusHTML

      public void renderStatusHTML(Writer out, int pageSize, int page, int mode) throws IOException
      Renders the network database status page.
      Parameters:
      out - Writer to output HTML
      pageSize - number of routers per page
      page - zero-based page index
      mode - selects which view to render: 0 = summary charts, 1 = full router infos, 2 = compact router infos, 3 = summary charts sorted by country count
      Throws:
      IOException - if an I/O error occurs
    • renderRoutersToWriter

      public void renderRoutersToWriter(Collection<RouterInfo> routers, Writer out, boolean isLocal, int page, int pageSize) throws IOException
      Renders a list of RouterInfo objects to the given Writer. Uses parallel rendering for sets up to 100 routers, streams for larger sets.
      Parameters:
      routers - the routers to render
      out - where the HTML is written
      isLocal - true to mark the routers as local
      page - zero-based page index
      pageSize - number of routers per page
      Throws:
      IOException - if the writer fails
    • renderRoutersToWriter

      public void renderRoutersToWriter(Collection<RouterInfo> routers, Writer out, boolean isLocal, int page, int pageSize, boolean applyPagination) throws IOException
      Renders a list of RouterInfo objects to the given Writer. Uses parallel rendering for sets up to 100 routers, streams for larger sets.
      Parameters:
      routers - the routers to render
      out - where the HTML is written
      isLocal - true to mark the routers as local
      page - zero-based page index
      pageSize - number of routers per page
      applyPagination - whether to apply pagination internally (false if list is already paginated)
      Throws:
      IOException - if the writer fails
    • renderSummaryTables

      private void renderSummaryTables(StringBuilder buf, ObjectCounterUnsafe<String> versions, ObjectCounterUnsafe<String> countries, int[] transportCount, Map<String,int[]> countryTiers)
      Renders the summary tables (versions, bandwidth, transports, countries).
      Parameters:
      buf - buffer the table HTML is appended to
      versions - router counts keyed by the router.version option string
      countries - router counts keyed by two-letter country code
      transportCount - router counts indexed by the classifyTransports value
      countryTiers - per-country [X-tier, floodfill] counts
    • renderVersionsTable

      private void renderVersionsTable(StringBuilder buf, ObjectCounterUnsafe<String> versions)
      Renders the router versions table, highest version first, with one row per version present in the router list.
      Parameters:
      buf - buffer the table HTML is appended to
      versions - router counts keyed by the router.version option string
    • renderBandwidthTiers

      private void renderBandwidthTiers(StringBuilder buf)
      Renders the bandwidth tiers table, one row per tier that has peers.
      Parameters:
      buf - buffer the table HTML is appended to
    • renderCongestionCaps

      private void renderCongestionCaps(StringBuilder buf)
      Renders the congestion capabilities table, or nothing at all when no router in the NetDb advertises one of the three congestion capabilities.
      Parameters:
      buf - buffer the table HTML is appended to
    • renderTransportsTable

      private void renderTransportsTable(StringBuilder buf, int[] transportCount)
      Renders the transports table, one row per transport combination that at least one router uses.
      Parameters:
      buf - buffer the table HTML is appended to
      transportCount - router counts indexed by the classifyTransports value, so the array is as long as the transport name table
    • renderCountryTable

      private void renderCountryTable(StringBuilder buf, ObjectCounterUnsafe<String> countries, Map<String,int[]> countryTiers)
      Renders the country list table with the X-tier, floodfill and total counts for each country; countries whose total drops to zero are left out.
      Parameters:
      buf - buffer the table HTML is appended to
      countries - router counts keyed by two-letter country code, the local router included; the row total subtracts that one
      countryTiers - per-country [X-tier, floodfill] counts; a country absent from the map counts as zero for both columns
    • cachedTallies

      private NetDbRenderer.RouterTallies cachedTallies(List<RouterInfo> routers)
      Overview tallies for the sorted router list, memoized for a few seconds.

      Counting costs a country lookup, an option read and a transport classification per known router, and the sorted list is only replaced on its own expiry. So the list's identity is the stamp the tallies belong to, and the TTL bounds a country that resolves later.

      Parameters:
      routers - the sorted list from NetDbRouterCache
      Returns:
      tallies for that list, never null
    • countFullRouterStats

      private void countFullRouterStats(List<RouterInfo> routers, ObjectCounterUnsafe<String> versions, ObjectCounterUnsafe<String> countries, int[] transportCount, Map<String,int[]> countryTiers)
      Counts the summary statistics for the /netdb overview in a single pass: versions, countries, transports, and per-country X-tier / floodfill totals.
      Parameters:
      routers - routers to tally, the local router included
      versions - version string to count, filled in here
      countries - country code to count, the local router included
      transportCount - transport class index to count, sized for TNAMES
      countryTiers - country code to [X-tier count, floodfill count]
    • getTranslatedCountry

      private String getTranslatedCountry(String code)
      Translated country name for the given country code.
      Parameters:
      code - the two-letter country code to resolve
      Returns:
      the country name translated into the console language, or the untranslated geoIP name, which is the code itself when unknown
    • getCachedReverseDNS

      private String getCachedReverseDNS(String ip)
      Cached reverse DNS hostname for the IP, or null if absent or expired.
      Parameters:
      ip - the address whose cached hostname is wanted
      Returns:
      the hostname cached for the IP, or null if it was never cached or the 24-hour entry has expired
    • putCachedReverseDNS

      private void putCachedReverseDNS(String ip, String hostname)
      Caches a reverse DNS result for 24 hours. A result that repeats the IP or is the literal "unknown" is not worth caching and is dropped.
      Parameters:
      ip - the address the hostname was resolved for
      hostname - the hostname to store, ignored when null, equal to ip, or "unknown"
    • renderRouterInfo

      private void renderRouterInfo(StringBuilder buf, RouterInfo routerInfo, boolean isLocalRouter)
      Renders a single RouterInfo as HTML.
      Parameters:
      buf - buffer the router HTML is appended to
      routerInfo - the router to render
      isLocalRouter - true if this is the local router
    • renderRouterInfo

      private void renderRouterInfo(StringBuilder buf, RouterInfo routerInfo, boolean isLocalRouter, Map<String,String> rdnsLookups)
      Renders a single RouterInfo as HTML with optional pre-resolved reverse DNS lookups.
      Parameters:
      buf - buffer the router HTML is appended to
      routerInfo - the router to render
      isLocalRouter - true if this is the local router
      rdnsLookups - map of IP to hostname for reverse DNS, may be null
    • renderRouterInfoSafe

      private void renderRouterInfoSafe(StringBuilder sb, RouterInfo ri, boolean isLocalRouter, Map<String,String> rdnsLookups)
      Renders a single RouterInfo, isolating any failure to this one entry.

      The netdb listing streams progressively, so an exception escaping a single render would truncate the rest of the page with no way to re-render.

      Parameters:
      sb - buffer the router HTML is appended to
      ri - the router to render
      isLocalRouter - true if this is the local router
      rdnsLookups - map of IP to hostname for reverse DNS, may be null
    • renderRouterInfosInParallel

      public String renderRouterInfosInParallel(Collection<RouterInfo> routerInfos, boolean isLocalRouter)
      Renders multiple RouterInfo objects in parallel, in ordered chunks of BATCH_SIZE. Falls back to synchronous rendering when the set is larger than one batch, to bound peak memory.
      Parameters:
      routerInfos - collection of routers to render
      isLocalRouter - true if rendering the local router
      Returns:
      the rendered HTML for every router, in input order
    • startsWith

      private static boolean startsWith(byte[] haystack, byte[] needle)
      True if the needle is a prefix of the haystack.
      Parameters:
      haystack - the data to check, never null
      needle - non-empty prefix to find
      Returns:
      whether haystack starts with needle
    • classifyTransports

      private static int classifyTransports(RouterInfo info)
      Classifies router transports into bit flags.
      Parameters:
      info - the router whose transport addresses and their options are read
      Returns:
      an index into the transport name table for the router's addresses, or 0 when no transport was recognised
    • getPeerProfileTier

      public String getPeerProfileTier(Hash peer, boolean fullname)
      Peer profile tier name or CSS class.
      Parameters:
      peer - the router hash whose tier is reported; null yields the local tier
      fullname - if true, return full name; else CSS class
      Returns:
      the tier name or class
    • _t

      private String _t(String s)
      Translate a string via the router console messages bundle.
      Parameters:
      s - the string to look up in the bundle
      Returns:
      the translated string, or s itself when no translation exists
    • _x

      private static final String _x(String s)
      Mark a string for translation extraction, a no-op at runtime.
      Parameters:
      s - the string to mark for extraction
      Returns:
      the same string, unchanged, ready for the extractor to find it
    • _t

      private String _t(String s, Object o)
      Translate a string with a parameter via the router console messages bundle.
      Parameters:
      s - string to be translated containing {0}
      o - parameter, not translated
      Returns:
      translated string
    • agoMemo

      private String agoMemo(String duration)
      Translate and memoize "{0} ago" for one rendered row.
      Parameters:
      duration - the age, already run through DataHelper.formatDuration2(long)
      Returns:
      the localized "<duration> ago"
      See Also:
    • memoryUsedMB

      private long memoryUsedMB()
      Resident memory in whole megabytes, for the local row's "Memory usage" cell.

      Memoized because renderRoutersToWriter hands every row in a list the same isLocal flag, so this would otherwise run once per row rather than once per page. The rate itself averages over a minute, longer than any render.

      Returns:
      megabytes of memory in use, 0 if the stat is not registered yet
    • capTooltip

      private String capTooltip()
      The capability link tooltip, resolved once per render pass. The value depends only on the UI language and a renderer is created per request, so the memo cannot go stale within a pass.
      Returns:
      the tooltip suffix inserted before each capability link's span