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

class TunnelRendererextends Object
For /tunnels.jsp, used by TunnelHelper.
  • Field Details

    • TUNNEL_PAREN

      private static final Pattern TUNNEL_PAREN
      Matches the parenthesised name in a tunnel nickname.
    • ATT_PREFIX

      private static final Pattern ATT_PREFIX
      "AT&T" followed by anything (whois cleanup).
    • AMP_T_RUN

      private static final Pattern AMP_T_RUN
      A bare "&T" run (whois cleanup).
    • _context

      private final RouterContext _context
      The router context.
    • DISPLAY_LIMIT

      private int DISPLAY_LIMIT
      Tunnels listed before the display is truncated.
    • MAX_BEFORE_STREAMING

      private static final int MAX_BEFORE_STREAMING
      Render rows in a single write up to this count; above it, flush every STREAM_BATCH rows so the page paints progressively.
      See Also:
    • STREAM_BATCH

      private static final int STREAM_BATCH
      Rows rendered per flush when streaming a large table.
      See Also:
    • _fragmentKeys

      private boolean _fragmentKeys
      Emit a per-row data-key (peer hash) for worker-side row diffing; fragment renders only, so full pages stay byte-for-byte identical.
    • KEY_LEN

      private static final int KEY_LEN
      Length of the truncated base64 hash used as a per-row data-key in fragment mode.
      See Also:
    • displayed

      private int displayed
      Tunnels rendered so far on this page.
    • FORMAT_SYMBOLS

      private static final DecimalFormatSymbols FORMAT_SYMBOLS
      Locale symbols snapshotted once at class load, cloned by every formatter.
    • TWO_DECIMALS

      private static final ThreadLocal<DecimalFormat> TWO_DECIMALS
      DecimalFormat is not thread-safe, so tunnel rows get one formatter per thread.
    • ZERO_DECIMALS

      private static final ThreadLocal<DecimalFormat> ZERO_DECIMALS
      Per-thread formatter for whole numbers.
    • FMT_SCRATCH

      private static final ThreadLocal<StringBuffer> FMT_SCRATCH
      Scratch buffer for the formatters; NumberFormat can only format into a StringBuffer.
    • FMT_POS

      private static final ThreadLocal<FieldPosition> FMT_POS
      Reusable parse position; a new FieldPosition per call would defeat the reusable scratch buffer.
    • ZEROES

      private static final String ZEROES
      The ".00" that a whole number formats to and the trimmed forms drop.
      See Also:
    • routerInfoCache

      private final TunnelRenderer.BoundedCache<Hash, RouterInfo> routerInfoCache
      Cached router infos for the tunnel graph.
    • reverseLookupResults

      Cached reverse lookups for the tunnel graph.
    • peerToIP

      private final TunnelRenderer.BoundedCache<Hash,String> peerToIP
      Cached peer to IP mappings for the tunnel graph.
  • Constructor Details

    • TunnelRenderer

      public TunnelRenderer(RouterContext ctx)
      Hold the router context every render method reads its pools and statistics from.
      Parameters:
      ctx - the router context to render from
  • Method Details

    • fmt

      private static void fmt(StringBuilder buf, double val)
      Append a value with two decimal places.
      Parameters:
      buf - the buffer to append to
      val - the value to format
    • fmt0

      private static void fmt0(StringBuilder buf, double val)
      Append a value with no decimal places, rounded half up.
      Parameters:
      buf - the buffer to append to
      val - the value to format
    • fmtTrim

      private static void fmtTrim(StringBuilder buf, double val)
      Append a value with two decimal places, dropping every ".00".
      Parameters:
      buf - the buffer to append to
      val - the value to format
    • format

      private static StringBuffer format(DecimalFormat formatter, double val)
      Format through the calling thread's reusable scratch buffer.
      Parameters:
      formatter - the per-thread formatter
      val - the value to format
      Returns:
      the reusable buffer holding the formatted text
    • renderStatusHTML

      public void renderStatusHTML(Writer out) throws IOException
      Render the whole tunnel status page: the exploratory, client and participating pool summaries followed by the pool detail tables.
      Parameters:
      out - the writer to render to
      Throws:
      IOException - if writing fails
    • renderParticipating

      public void renderParticipating(Writer out, boolean bySpeed) throws IOException
      Render the table of tunnels this router participates in, ordered either by speed or by how recently they were added.
      Parameters:
      out - the writer to render to
      bySpeed - true for the fastest variety, false for most recent
      Throws:
      IOException - if writing fails
    • renderParticipatingFragment

      public void renderParticipatingFragment(Writer out, boolean bySpeed, String id) throws IOException
      Render only the named fragment of the participating tunnels table for the contentonly fragment mode of the transit pages: the "transitPeers" tbody or the "statusnotes" tfoot. Renders nothing for an unknown id, on hidden-mode errors, or when no transit tunnels currently exist, so a document fragment that omits the element falls back to a whole-div full-page refresh on the client.
      Parameters:
      out - the writer to render to
      bySpeed - true for the fastest variety, false for most recent
      id - the element id to render
      Throws:
      IOException - if writing fails
    • renderParticipatingInternal

      private void renderParticipatingInternal(Writer out, boolean bySpeed, String fragmentId) throws IOException
      Render the participating tunnels block, or a single named fragment of it. With a null fragmentId the full block is written exactly as the public renderParticipating always did. The per-element mode emits only that element, so the auto-refresh worker can morph just the live tbody or tfoot from a contentonly response.
      Parameters:
      out - the writer to render to
      bySpeed - true for the fastest variety, false for most recent
      fragmentId - the fragment element id, or null for the full block
      Throws:
      IOException - if writing fails
    • renderTransitSummary

      public void renderTransitSummary(Writer out) throws IOException
      Render the transit tunnel summary: the counts of transit tunnels this router builds, and the peers they are shared with.
      Parameters:
      out - the writer to render to
      Throws:
      IOException - if writing fails
    • renderTransitSummaryFragment

      public void renderTransitSummaryFragment(Writer out, String id) throws IOException
      Render only the "transitPeers" tbody of the transit-summary table for the contentonly fragment mode of the transitsummary page. Renders nothing for an unknown id, in hidden mode, or when fewer than two transit tunnels currently exist, so a fragment that omits the element falls back to a whole-div full-page refresh on the client.
      Parameters:
      out - the writer to render to
      id - the element id to render
      Throws:
      IOException - if writing fails
    • renderTransitSummaryInternal

      private void renderTransitSummaryInternal(Writer out, String fragmentId) throws IOException
      Render the transit-summary table, or a single named fragment of it. With a null fragmentId the full table is written exactly as the public renderTransitSummary always did. The fragment mode emits only the named tbody so the auto-refresh worker can morph just the live rows from a contentonly response.
      Parameters:
      out - the writer to render to
      fragmentId - the fragment element id, or null for the full table
      Throws:
      IOException - if writing fails
    • renderPeers

      public void renderPeers(Writer out) throws IOException
      Render the tunnel peer count table, the "all peers" tbody, or the totals footer row.

      Full-page mode renders header, rows, and footer as one table. Fragment mode (contentonly) renders just the named element so the page can refresh the tbody rows and footer without re-sending the full table.

      Parameters:
      out - the writer to render to
      Throws:
      IOException - if writing fails
    • renderPeerFragment

      public void renderPeerFragment(Writer out, String id) throws IOException
      Render a single named element for the contentonly fragment mode of the tunnel peer count page: the "all peers" tbody with data-key rows, or the totals footer row. Renders nothing for unknown ids.
      Parameters:
      out - the writer to render to
      id - the element id
      Throws:
      IOException - if writing fails
    • preparePeerRows

      private TunnelRenderer.PeerRows preparePeerRows()
      Count tunnels per peer, resolve RouterInfos and reverse lookups, and build the validated peer list shared by the full and fragment renders.
      Returns:
      the prepared counts and peer list
    • appendPeerRow

      private void appendPeerRow(StringBuilder chunkSb, Hash h, RouterInfo info, int tunnelCount, int partCount, int localTunnelCount, int transitTunnelCount, String versionTip, String unknownLabel, String configurePeerTip, String editLabel)
      Append one tunnel peer count row: identity cells plus local and transit tunnel bars and the edit link.
      Parameters:
      chunkSb - the buffer the row markup is appended to
      h - the peer's router hash
      info - the peer's router info, or null if it is not in the NetDb
      tunnelCount - total local tunnels, the denominator of the local bar
      partCount - total transit tunnels, the denominator of the transit bar
      localTunnelCount - how many local tunnels this peer is in
      transitTunnelCount - how many transit tunnels this peer is in
      versionTip - pre-translated tooltip for the version link
      unknownLabel - pre-translated label when the version is unknown
      configurePeerTip - pre-translated tooltip for the edit link
      editLabel - pre-translated label of the edit link
    • appendPeerFooterRow

      private void appendPeerFooterRow(StringBuilder footerSb, int validPeerCount, int tunnelCount, int partCount)
      Append the totals footer row of the tunnel peer count table.
      Parameters:
      footerSb - the buffer the footer row markup is appended to
      validPeerCount - peers with a router info, shown as "unique peers"
      tunnelCount - total local tunnels, shown as "local"
      partCount - total transit tunnels, shown as "transit", row omitted at 0
    • appendPeerFooter

      private void appendPeerFooter(StringBuilder footerSb, int validPeerCount, int tunnelCount, int partCount)
      Append the closing tfoot and wrapper for the tunnel peer count table.
      Parameters:
      footerSb - the buffer the footer row and closing markup are appended to
      validPeerCount - peers with a router info, shown as "unique peers"
      tunnelCount - total local tunnels, shown as "local"
      partCount - total transit tunnels, shown as "transit", row omitted at 0
    • getReverseLookupInfo

      private TunnelRenderer.ReverseLookupResult getReverseLookupInfo(Hash h, RouterInfo info, long uptime)
      Performs a cached reverse lookup for the given router hash and its RouterInfo, returning canonical hostname, domain, and cleaned WHOIS data if available.

      Uses internal cache to avoid repeated DNS lookups and performs string cleanup on WHOIS data for better display. Reverse lookups occur only if enabled and uptime exceeds 30 seconds.

      Parameters:
      h - the router's hash identifier
      info - the RouterInfo instance for the router (may be null)
      uptime - current router uptime in milliseconds
      Returns:
      a ReverseLookupResult holding the IP, canonical hostname, domain, and WHOIS info
    • renderTunnelFragment

      public void renderTunnelFragment(Writer out, String id) throws IOException
      Render the "tunnelsContainer" fragment for the contentonly fragment mode of the local tunnels page: the container div plus the tunnel summaries and the tunnel-guide section it holds on the full page. The element is written without the "hidden" attribute that the full page uses for the no-JS fallback, because the JS-enabled page shows and hides the block interactively and the browser hides it while the refresh runs anyway.
      Parameters:
      out - the writer to render to
      id - the element id to render
      Throws:
      IOException - if writing fails
    • renderGuide

      public void renderGuide(Writer out) throws IOException
      Renders an HTML table describing the bandwidth tiers used for tunnels, including their ranges and labels, and writes the output to the provided Writer.
      Parameters:
      out - the Writer to which the HTML content is written
      Throws:
      IOException - if an I/O error occurs during writing
    • range

      static String range(int f, int t)
      Format one tunnel capacity band for display. The bounds are given in binary (1024) kilobytes per second, as the Router.MIN_BW_* constants are, and are rescaled to decimal KB/s. The upper bound is printed one short of its exact value so adjacent bands do not overlap on the page.
      Parameters:
      f - start of the band in binary KB/s, inclusive
      t - end of the band in binary KB/s, exclusive
      Returns:
      the band as a "first - last KB/s" string
    • getTunnelName

      private String getTunnelName(TunnelPool in)
      Get display name for the tunnel.
      Parameters:
      in - the inbound pool whose settings provide the destination nickname
      Returns:
      the escaped nickname, or the base32 destination when unnamed
    • getPoolTip

      private String getPoolTip(TunnelPool in)
      Get the pool's torrent names for the tooltip, when the tunnel is a shared I2PSnark pool destination and the i2psnark.poolMembers session property is set. Single-torrent pools have the torrent's name for a nickname, so the check matches all I2PSnark tunnels; dedicated destinations have no poolMembers property.
      Parameters:
      in - the tunnel pool
      Returns:
      the escaped tooltip text, or null for a dedicated destination
    • renderPool

      private void renderPool(Writer out, TunnelPool in, TunnelPool outPool) throws IOException
      Renders one tunnel pool's table.
      Parameters:
      out - where the HTML is written
      in - the inbound pool, may be null
      outPool - the outbound pool, may be null
      Throws:
      IOException - if the write fails
    • appendTableHeader

      private void appendTableHeader(StringBuilder buf, int maxLength)
      Append the tunnel table header row: In/Out, Status, Expiry, Latency, Data, Gateway, Participants, and Endpoint columns. The Participants column spans the longest tunnel minus the first and last hops.
      Parameters:
      buf - the buffer the header markup is appended to
      maxLength - the longest tunnel length in hops, deciding which participant and endpoint columns are emitted
    • renderTunnelRow

      private int renderTunnelRow(StringBuilder buf, TunnelInfo info, long timeLeft, int maxLength, String tib, String tob, String localHopTip, String localLabel, String tunnelIdTip)
      Append one tunnel row: direction badge, test status, expiry bar, latency, data transferred, and the peer cells.

      Terminates the row only - the caller closes </tbody> once, after the last row.

      Parameters:
      buf - the buffer the row markup is appended to
      info - the tunnel to render
      timeLeft - ms until the tunnel expires, greater than 0
      maxLength - the longest tunnel in the table, the peer cells are padded to
      tib - pre-translated "Inbound" label for the direction cell
      tob - pre-translated "Outbound" label for the direction cell
      localHopTip - pre-translated tooltip for the local hop badge
      localLabel - pre-translated label for the local hop badge
      tunnelIdTip - pre-translated tooltip for the hop's tunnel id
      Returns:
      the processed message count, for the bandwidth footer
    • appendPeerCells

      private void appendPeerCells(StringBuilder buf, TunnelInfo info, int length, int maxLength, boolean isAdvanced, String localHopTip, String localLabel, String tunnelIdTip)
      Append the peer cells for one tunnel: the local hop renders as a "Local" badge with the tunnel id when advanced mode is on, other hops render as netdb links with their tunnel ids. Zero-hop and short tunnels are padded with empty cells to align the table columns.
      Parameters:
      buf - the buffer the peer cells are appended to
      info - the tunnel whose hops are rendered
      length - the number of hops in this tunnel
      maxLength - the longest tunnel in the table, the number of cells to pad to
      isAdvanced - true to show each hop's tunnel id, from the advanced-mode property
      localHopTip - pre-translated tooltip for the local hop badge
      localLabel - pre-translated label for the local hop badge
      tunnelIdTip - pre-translated tooltip for the hop's tunnel id
    • flushBuf

      private void flushBuf(Writer out, StringBuilder buf) throws IOException
      Write the buffered HTML to the output writer and clear the buffer, used to flush large tables in batches so the page paints progressively.
      Parameters:
      out - the writer the buffer is written to
      buf - the buffer to write and then clear
      Throws:
      IOException - if writing fails
    • renderTestStatus

      private void renderTestStatus(StringBuilder buf, TunnelInfo info)
      Append the tunnel test status cell, with the status-specific tooltip.
      Parameters:
      buf - the buffer the status cell is appended to
      info - the tunnel whose test status is displayed
    • renderLifetimeBandwidth

      public void renderLifetimeBandwidth(Writer out, TunnelPool in, TunnelPool outPool) throws IOException
      Render the lifetime bandwidth table: bytes sent and received by each tunnel of the two pools combined, longest-lived tunnel first.
      Parameters:
      out - the writer to render to
      in - inbound pool to list, or null for none
      outPool - outbound pool to list, or null for none
      Throws:
      IOException - if writing fails
    • countTunnelsPerPeer

      private int countTunnelsPerPeer(ObjectCounter<Hash> lc)
      Tally the exploratory and client tunnels longer than one hop, counting each of their peers into lc.
      Parameters:
      lc - the counter to fill in, keyed by peer hash
      Returns:
      total number of non-fallback expl. + client tunnels
    • countParticipatingPerPeer

      private int countParticipatingPerPeer(ObjectCounter<Hash> pc)
      Tally the transit tunnels this router participates in, counting the receive-from and send-to peer of each into pc.
      Parameters:
      pc - the counter to fill in, keyed by the participating peer hashes
      Returns:
      total number of part. tunnels
    • netDbLink

      private String netDbLink(Hash peer)
      Builds the netdb link for one peer.
      Parameters:
      peer - the peer hash
      Returns:
      the HTML link
    • peerFlag

      private String peerFlag(Hash peer)
      Builds the country flag image for one peer.
      Parameters:
      peer - the peer hash
      Returns:
      the HTML image tag, empty if unknown
    • appendPeerIdentity

      private void appendPeerIdentity(StringBuilder sb, Hash h, String hB64, String truncHash, String version, RouterInfo info, String ip, TunnelRenderer.ReverseLookupResult rl, String versionTip, String banlistedTip, String unknownLabel, boolean isBanned)
      Append the identity cells shared by the peer tables: country flag, router hash link, version with netdb link, tier caps, IP address, and reverse-lookup domain. The callers append the data cells and the row terminator.
      Parameters:
      sb - the buffer the identity cells are appended to
      h - the hash of the peer being rendered
      hB64 - base64 of the peer hash for the netdb link
      truncHash - short hash label
      version - router version, may be null
      info - RouterInfo for the caps cell, may be null
      ip - primary IP address, may be null
      rl - reverse lookup result, may be null
      versionTip - tooltip for the version link
      banlistedTip - tooltip for the banlisted marker
      unknownLabel - fallback label for missing domains
      isBanned - whether the peer is banlisted
    • getShareBandwidth

      private int getShareBandwidth()
      Copied from ConfigNetHelper.
      Returns:
      in KBytes per second
    • _t

      private String _t(String s)
      Translate a string.
      Parameters:
      s - the translation key, holding the English text when untranslated
      Returns:
      the translated string, or s itself when no translation exists
    • _t

      public String _t(String s, Object o)
      Translate a string and substitute one parameter into it. Single quotes in s must be doubled for MessageFormat; do not double them in o.
      Parameters:
      s - the string to be translated, containing {0}
      o - the parameter, not translated itself
      Returns:
      the translated string with {0} replaced by o
    • renderExpiryBar

      private void renderExpiryBar(StringBuilder buf, long timeLeft)
      Generate a percentage bar for expiry time, appending straight to the row buffer.
      Parameters:
      buf - the buffer the bar markup is appended to
      timeLeft - ms until the tunnel expires, clamped at 0, bar full at 10 minutes
    • renderPoolSummary

      private void renderPoolSummary(Writer out, TunnelPool in, TunnelPool outPool, Hash client) throws IOException
      Render a summary table for a tunnel pool.
      Parameters:
      out - the writer to render to
      in - the inbound pool, not null
      outPool - the outbound pool, or null for none
      client - the destination the pool serves, unused by the current body
      Throws:
      IOException - if writing fails
    • getNextExpiry

      private long getNextExpiry(TunnelPool pool)
      Get next tunnel expiry from pool (excludes failed tunnels).
      Parameters:
      pool - the pool scanned for the earliest live tunnel expiry
      Returns:
      ms since the epoch of that expiry, 0 if no tunnel qualifies