java.lang.Object
net.i2p.router.transport.TransportImpl
net.i2p.router.transport.ntcp.NTCPTransport
All Implemented Interfaces:
Transport

public class NTCPTransportextends TransportImpl
Non-blocking TCP (NTCP) transport implementation for I2P.

This class provides the primary TCP-based transport for I2P communication using Java NIO for non-blocking I/O operations. It supports both NTCP 1 and NTCP 2 protocols with advanced features like connection pooling, bandwidth management, and sophisticated peer management.

Protocol Features:

  • NTCP 1: Basic encrypted TCP transport
  • NTCP 2: Enhanced protocol with improved efficiency
  • Configurable bandwidth limits and throttling
  • Connection pooling and reuse
  • IPv4 and IPv6 support
  • Automatic protocol negotiation

Architecture:

  • Non-blocking I/O with NIO channels
  • Separate reader and writer threads
  • Event-driven message processing
  • Connection state machines for establishment
  • Peer reputation and cost-based routing

Connection Management:

  • Multiple bid tiers (fast, slow, high-cost)
  • Connection pooling and reuse
  • Automatic failover and retry logic
  • Peer blacklisting and banlist support
  • Field Details

    • _log

      private final Log _log
      Logger for NTCP connections.
    • _banLogger

      private final BanLogger _banLogger
      Records why routers were banned.
    • _fastBid

      private final NTCPTransport.SharedBid _fastBid
      Peer selection bid for fast peers.
    • _slowBid

      private final NTCPTransport.SharedBid _slowBid
      Peer selection bid for slow peers.
    • _slowCostBid

      private final NTCPTransport.SharedBid _slowCostBid
      Bid raising the cost of slow peers.
    • _nearCapacityBid

      private final NTCPTransport.SharedBid _nearCapacityBid
      Save some conns for inbound.
    • _nearCapacityCostBid

      private final NTCPTransport.SharedBid _nearCapacityCostBid
      Bid raising costs when near capacity.
    • _transientFail

      private final NTCPTransport.SharedBid _transientFail
      Bid for peers with transient failures.
    • _conLock

      private final Object _conLock
      Lock for the connection maps.
    • _conByIdent

      private final ConcurrentHashMap<Hash, NTCPConnection> _conByIdent
      Open connections, by peer hash.
    • _pumper

      private final EventPumper _pumper
      NIO event pumper for the connections.
    • _reader

      private final Reader _reader
      The accept and connect thread.
    • _writer

      private Writer _writer
      The write thread, null until started.
    • _ssuPort

      private int _ssuPort
      SSU port advertised in NTCP2 handshakes.
    • _endpoints

      private final Set<InetSocketAddress> _endpoints
      Bound listening endpoints. All entries MUST be resolved InetSocketAddress instances (created via port-only or InetAddress constructors), NOT unresolved hostname-based addresses. InetSocketAddress.equals(Object) returns false when comparing resolved vs. unresolved, so contains() checks would silently fail on unresolved entries.
    • _networkID

      private final int _networkID
      The network id we communicate on.
    • _establishing

      private final Set<NTCPConnection> _establishing
      List of NTCPConnection of connections not yet established that we want to remove on establishment or close on timeout.
    • _replayFilter

      private final DecayingBloomFilter _replayFilter
      "bloom filter".
    • _haveIPv6Address

      private boolean _haveIPv6Address
      Do we have a public IPv6 address?
    • _lastInboundIPv4

      private long _lastInboundIPv4
      When the last inbound IPv4 connection arrived.
    • _lastInboundIPv6

      private long _lastInboundIPv6
      When the last inbound IPv6 connection arrived.
    • PROP_I2NP_NTCP_HOSTNAME

      public static final String PROP_I2NP_NTCP_HOSTNAME
      Config key for an explicitly configured hostname the NTCP transport advertises. The SSU equivalent is i2np.udp.host, not hostname. Value sourced from Transport.PROP_I2NP_NTCP_HOSTNAME.
      See Also:
    • PROP_I2NP_NTCP_PORT

      public static final String PROP_I2NP_NTCP_PORT
      Config key for the port the NTCP transport listens for inbound connections on. Value sourced from Transport.PROP_I2NP_NTCP_PORT.
      See Also:
    • PROP_I2NP_NTCP_AUTO_PORT

      public static final String PROP_I2NP_NTCP_AUTO_PORT
      Config key controlling whether NTCP may auto-update its advertised port based on peer feedback. Value sourced from Transport.PROP_I2NP_NTCP_AUTO_PORT.
      See Also:
    • PROP_I2NP_NTCP_AUTO_IP

      public static final String PROP_I2NP_NTCP_AUTO_IP
      Config key controlling whether NTCP may auto-update its advertised IP based on peer feedback. Value sourced from Transport.PROP_I2NP_NTCP_AUTO_IP.
      See Also:
    • DEFAULT_COST

      private static final int DEFAULT_COST
      Default peer selection cost for NTCP.
      See Also:
    • NTCP2_OUTBOUND_COST

      private static final int NTCP2_OUTBOUND_COST
      Peer selection cost for outbound NTCP2.
      See Also:
    • PROP_BIND_INTERFACE

      public static final String PROP_BIND_INTERFACE
      This is rarely if ever used, default is to bind to wildcard address.
      See Also:
    • _finisher

      private final NTCPSendFinisher _finisher
      Closes connections after their writes finish.
    • _xdhFactory

      private final X25519KeyFactory _xdhFactory
      Factory for the NTCP2 ephemeral key pairs.
    • _lastBadSkew

      private long _lastBadSkew
      When a bad clock skew was last logged.
    • RATES

      private static final long[] RATES
      Rate stat periods for the connection statistics.
    • SUPPRESSION_PATTERNS

      private static final Set<String> SUPPRESSION_PATTERNS
      Disconnect reasons with repetitive log suppression.
    • MIN_SIGTYPE_VERSION

      public static final String MIN_SIGTYPE_VERSION
      RI sigtypes supported in 0.9.16.
      See Also:
    • STYLE

      public static final String STYLE
      Style identifier for the NTCP transport. Value sourced from Transport.STYLE_NTCP.
      See Also:
    • STYLE2

      public static final String STYLE2
      Style identifier for the NTCP2 protocol variant. Value sourced from Transport.STYLE_NTCP2.
      See Also:
    • NTCP2_INT_VERSION

      static final int NTCP2_INT_VERSION
      NTCP2 protocol version.
      See Also:
    • NTCP2_VERSION

      static final String NTCP2_VERSION
      "2".
    • NTCP2_VERSION_ALT

      static final String NTCP2_VERSION_ALT
      "2,".
    • PQ_INT_VERSION

      static final int PQ_INT_VERSION
      0 to disable, or 3/4/5 for enctypes 5/6/7.
      See Also:
    • PQ_VERSION

      static final String PQ_VERSION
      PQ protocol version string.
    • PROP_NTCP2_SP

      public static final String PROP_NTCP2_SP
      Config key for the base-64 NTCP2 static private key. Value sourced from Transport.PROP_NTCP2_SP.
      See Also:
    • PROP_NTCP2_IV

      public static final String PROP_NTCP2_IV
      Config key for the base-64 NTCP2 static IV. Value sourced from Transport.PROP_NTCP2_IV.
      See Also:
    • NTCP2_IV_LEN

      private static final int NTCP2_IV_LEN
      NTCP2 handshake IV length, in bytes.
      See Also:
    • NTCP2_KEY_LEN

      private static final int NTCP2_KEY_LEN
      NTCP2 handshake key length, in bytes.
      See Also:
    • MIN_DOWNTIME_TO_REKEY

      private static final long MIN_DOWNTIME_TO_REKEY
      Downtime after which the NTCP2 static key is replaced.
      See Also:
    • MIN_DOWNTIME_TO_REKEY_HIDDEN

      private static final long MIN_DOWNTIME_TO_REKEY_HIDDEN
      Downtime after which a hidden router rekeys.
      See Also:
    • _ntcp2StaticPubkey

      private final byte[] _ntcp2StaticPubkey
      Our NTCP2 static public key.
    • _ntcp2StaticPrivkey

      private final byte[] _ntcp2StaticPrivkey
      Our NTCP2 static private key.
    • _ntcp2StaticIV

      private final byte[] _ntcp2StaticIV
      Our NTCP2 static initialization vector.
    • _b64Ntcp2StaticPubkey

      private final String _b64Ntcp2StaticPubkey
      Static public key, base64, for the router info.
    • _b64Ntcp2StaticIV

      private final String _b64Ntcp2StaticIV
      Static IV, base64, for the router info.
    • FAILSAFE_CLOSE_MEMORY_MS

      private static final long FAILSAFE_CLOSE_MEMORY_MS
      How far back a failsafe close keeps its peer attributable.

      Long enough that a pool noticing the loss later in its own walk still finds the cause, short enough that the structure stays small and a peer reconnecting is not blamed for the connection it lost minutes ago.

      See Also:
    • MAX_FAILSAFE_CLOSE_MEMORY

      private static final int MAX_FAILSAFE_CLOSE_MEMORY
      Upper bound on peers remembered for failsafe closes. Chosen so the worst-case scan finds an evictable entry in bounded time on the close path, which is already the expensive one.
      See Also:
    • _failsafeClosesAt

      private final Map<Hash,Long> _failsafeClosesAt
      Peers this transport closed an idle session to, and when.

      A closed session is indistinguishable from a dead peer by anyone who only sees the absence, so the fact is recorded here and read back by the pool that has to attribute the loss. Bounded by age and by count. Once full the oldest entry is dropped rather than refusing to record, because the newest close is the one most likely to be the cause being investigated.

    • ESTABLISH_TIMEOUT

      static volatile int ESTABLISH_TIMEOUT
      How long from initial connection attempt (accept() or connect()) until the con must be established to avoid premature close()ing. Tuned to ~3-5x average establish time; the Tuner further adjusts this at runtime.
  • Constructor Details

    • NTCPTransport

      public NTCPTransport(RouterContext ctx, X25519KeyFactory xdh)
      Registers the NTCP rate statistics and loads or creates the NTCP2 static keys; nothing is started until startListening().
      Parameters:
      ctx - the router context
      xdh - null to disable NTCP2
  • Method Details

    • setupPort

      private int setupPort()
      Pick a port if not previously configured. Only if UDP is disabled.
      Returns:
      the port or -1
    • inboundEstablished

      NTCPConnection inboundEstablished(NTCPConnection con)
      Registers a newly established inbound connection, replacing any existing connection for the same peer. Updates reachability status and connection statistics.
      Parameters:
      con - The newly established NTCPConnection.
      Returns:
      The previous NTCPConnection to the same peer if one existed, or null otherwise.
    • updateInboundIPStats

      private void updateInboundIPStats(boolean ipv6, long created)
      Updates statistics and reachability status related to inbound connections based on IP version and connection creation time. Triggers address change notification if this is the first inbound connection of the IP family.
      Parameters:
      ipv6 - True if the connection is IPv6, false if IPv4.
      created - The creation timestamp of the inbound connection.
    • outboundMessageReady

      protected void outboundMessageReady()
      Processes the next outbound message by retrieving or creating a connection, preparing it for sending, and handling related failures or bans.
      Specified by:
      outboundMessageReady in class TransportImpl
    • getConnectionOrCreateNew

      private NTCPConnection getConnectionOrCreateNew(Hash ih, RouterInfo target)
      Retrieves an existing NTCPConnection for the given peer hash or creates a new one. Synchronizes minimally on the connection map to avoid race conditions.
      Parameters:
      ih - The hash identifier of the target router identity.
      target - The RouterInfo object representing the connection target.
      Returns:
      An existing or newly created NTCPConnection, or null if creation failed.
    • getIPPortFromRouterInfo

      private String getIPPortFromRouterInfo(RouterInfo ri)
      Extract IP:port from RouterInfo for NTCP transport.
      Parameters:
      ri - the router info to read the NTCP host and port from, null yields "UNKNOWN"
      Returns:
      the IP port from router info
    • prepareConnectionForSending

      private void prepareConnectionForSending(NTCPConnection con, OutNetMessage msg) throws IOException
      Prepares the given NTCPConnection for sending the specified message, including checking message types and connection version, sending control info if needed, and ensuring the channel is open.
      Parameters:
      con - The NTCPConnection to prepare and send on.
      msg - The outbound message to send.
      Throws:
      IOException - If channel operations fail.
    • logConnectionSetupError

      private void logConnectionSetupError(Exception e)
      Logs errors or warnings related to connection setup failures, differentiating between IOExceptions and IllegalStateExceptions with appropriate log levels.
      Parameters:
      e - The exception that occurred during connection setup.
    • afterSend

      public void afterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue, long msToSend)
      Notify after the message send attempt completes.
      Overrides:
      afterSend in class TransportImpl
      Parameters:
      msg - message in question
      sendSuccessful - true if the peer received it
      allowRequeue - true if we should try other transports if available
      msToSend - how long it took to transfer the data to the peer
    • bid

      public TransportBid bid(RouterInfo toAddress, int dataSize)
      Bid on sending the message to the target.
      Parameters:
      toAddress - the target router's contact information
      dataSize - size of message payload, assumes full 16-byte header, transports should adjust as necessary for their overhead
      Returns:
      a TransportBid containing send details, or null if unwilling to send
    • isTooLargeForNTCP2

      static boolean isTooLargeForNTCP2(int dataSize)
      Whether the message is too large for NTCP2 to carry.

      The passed-in dataSize assumes a 16-byte header; NTCP2 uses a 9-byte header, so there are 7 bytes to spare over the NTCP2 maximum.

      Parameters:
      dataSize - the message data size, assuming the 16-byte header
      Returns:
      true if the message cannot fit on NTCP2
    • classifyNetworkId

      static NTCPTransport.NetworkIdIssue classifyNetworkId(int nid, int ourNetworkID)
      Classify the peer's network id relative to ours, for the ban-on-mismatch decision in bid(RouterInfo, int).
      Parameters:
      nid - the peer's announced network id
      ourNetworkID - our own network id
      Returns:
      OK if equal; NO_NETWORK if the peer sent the no-network sentinel (~0); WRONG_NETWORK otherwise
    • isSigTypeUsable

      static boolean isSigTypeUsable(SigType type)
      Whether the peer's signature type is usable: it must exist and be available on this build.
      Parameters:
      type - the peer's signature type
      Returns:
      true if we can sign with (or accept) that type
    • isConnectableVersion

      static boolean isConnectableVersion(boolean weAreDSA, String theirVersion)
      Whether we can connect on signatures: if we ourselves advertise a non-DSA signature type, the peer must announce a version at least as new as MIN_SIGTYPE_VERSION. A DSA-signing router never has a version restriction.
      Parameters:
      weAreDSA - true if our own signature type is DSA_SHA1
      theirVersion - the peer's announced version
      Returns:
      true if the version satisfies the signature-type floor
    • chooseBidTier

      static NTCPTransport.BidTier chooseBidTier(boolean haveCapacity, boolean highCost)
      Select the bid tier from the capacity/cost cascade, in the stable order SLOW > SLOW_COST > NEAR_CAPACITY > NEAR_CAPACITY_COST.
      Parameters:
      haveCapacity - whether the transport has spare connection capacity
      highCost - whether the peer's address cost exceeds DEFAULT_COST
      Returns:
      the tier to quote
    • bidFor

      private TransportBid bidFor(NTCPTransport.BidTier tier)
      Map a bid tier to the cached shared bid, so the compare-and-log hot path allocates nothing.
      Parameters:
      tier - the tier selected by chooseBidTier(boolean, boolean)
      Returns:
      the cached bid for that tier
    • isExpectedRaceCondition

      static boolean isExpectedRaceCondition(Exception e)
      Whether the exception is the expected channel-setup race: the peer started building the tunnel before we called prepareOutbound().
      Parameters:
      e - the exception thrown during connection setup
      Returns:
      true if it is the benign preparation race
    • isOwnRouterInfoStore

      static boolean isOwnRouterInfoStore(I2NPMessage m, Hash ourHash)
      Whether a DatabaseStoreMessage stored our own RouterInfo under our own key.

      Such a store is looped-back control info: the router already has its own RouterInfo, so the message must not be handed to the send pipeline as data; only the optional flood spike (see isRouterInfoStoreFlood(I2NPMessage)) is relevant.

      Parameters:
      m - the outbound message
      ourHash - our own router hash
      Returns:
      true if the message is a store of our own RouterInfo
    • isRouterInfoStoreFlood

      static boolean isRouterInfoStoreFlood(I2NPMessage m)
      Whether a DatabaseStoreMessage of our own RouterInfo carries a flood reply token. Only meaningful when isOwnRouterInfoStore(I2NPMessage, Hash) already returned true for the same message.
      Parameters:
      m - the outbound message
      Returns:
      true if the store requests a flood
    • shouldSendInfoNow

      static boolean shouldSendInfoNow(boolean shouldSkipInfo, boolean shouldFlood, int version)
      Whether the outbound message should be sent on the connection instead of skipped. A store of our own RouterInfo is skipped unless it carries a flood request, or until the NTCP2 version 1 behavior is in use.
      Parameters:
      shouldSkipInfo - whether the message is a store of our own RouterInfo
      shouldFlood - whether that store requests a flood
      version - the connection's NTCP version
      Returns:
      true if the message should be handed to the send pipeline
    • isAlreadyInProgress

      static boolean isAlreadyInProgress(EstablishState est)
      Whether the connection's outbound establishment has already left the initial state, in which case prepareOutbound() must not be called again.
      Parameters:
      est - the connection's establishment state, or null
      Returns:
      true if establishment is already in progress
    • getTargetAddress

      private RouterAddress getTargetAddress(RouterInfo target)
      Get first available address we can use.
      Parameters:
      target - the peer whose first usable NTCP address is returned
      Returns:
      address or null
    • isValid

      private boolean isValid(byte[] addr)
      An IPv6 address is only valid if we are configured to support IPv6 AND we have a public IPv6 address.
      Parameters:
      addr - may be null, returns false
      Returns:
      true only for a publicly routable address; a 16-byte address additionally requires that we hold a public IPv6
    • allowConnection

      public boolean allowConnection()
      Whether an additional outbound connection may be accepted.
      Returns:
      true if the connection count is below TransportImpl.getMaxConnections()
    • sendComplete

      void sendComplete(OutNetMessage msg)
      Queue up the afterSend call, which can take some time with jobs, etc.
      Parameters:
      msg - the message that finished sending, whose afterSend runs later on the finisher thread
    • noteFailsafeClose

      void noteFailsafeClose(Hash peer, long now)
      Record that an idle session to this peer was just closed.
      Parameters:
      peer - the peer whose session was closed
      now - current time in ms
    • pruneFailsafeCloses

      private boolean pruneFailsafeCloses(long now)
      Drop remembered closes that have aged out of the memory window.
      Parameters:
      now - current time in ms
      Returns:
      true when at least one entry was removed
    • failsafeCloseStillRemembered

      static boolean failsafeCloseStillRemembered(long closedAt, long now, long window)
      Whether a remembered close is still inside its memory window. Pure decision helper for unit tests.
      Parameters:
      closedAt - when the session was closed in ms, or 0 when never
      now - current time in ms
      window - how long the close stays remembered; non-positive remembers nothing
      Returns:
      true when the close is still recent enough to be reported
    • wasFailsafeClosed

      public boolean wasFailsafeClosed(Hash peer, long withinMs)
      Whether the peer's most recent connection was closed by the failsafe.
      Specified by:
      wasFailsafeClosed in interface Transport
      Overrides:
      wasFailsafeClosed in class TransportImpl
      Parameters:
      peer - the peer to ask about
      withinMs - how far back counts as recent; non-positive means nothing is recent
      Returns:
      true when this transport closed a session to the peer that recently
    • isEstablished

      public boolean isEstablished(Hash dest)
      Description copied from class: TransportImpl
      Whether the given peer is established.
      Specified by:
      isEstablished in interface Transport
      Overrides:
      isEstablished in class TransportImpl
      Parameters:
      dest - hash of the peer to check
      Returns:
      false; only a real transport reports established sessions
    • isConnecting

      public boolean isConnecting(Hash dest)
      Whether a connection attempt is in progress to the given peer.
      Specified by:
      isConnecting in interface Transport
      Overrides:
      isConnecting in class TransportImpl
      Parameters:
      dest - hash of the peer to check
      Returns:
      true if the connection is not closed and has not completed the handshake
    • isBacklogged

      public boolean isBacklogged(Hash dest)
      Whether the connection to the given peer is backlogged.
      Specified by:
      isBacklogged in interface Transport
      Overrides:
      isBacklogged in class TransportImpl
      Parameters:
      dest - hash of the peer to check
      Returns:
      true if the connection is established, has been up at least 15 seconds, and the bandwidth limiter flags its outbound queue
    • mayDisconnect

      public void mayDisconnect(Hash peer)
      Tell the transport that we may disconnect from this peer. This is advisory only.
      Specified by:
      mayDisconnect in interface Transport
      Overrides:
      mayDisconnect in class TransportImpl
      Parameters:
      peer - hash of the peer that may be disconnected
    • forceDisconnect

      public void forceDisconnect(Hash peer)
      Tell the transport to disconnect from this peer.
      Parameters:
      peer - hash of the peer to forcefully disconnect from
    • forceDisconnect

      public void forceDisconnect(Hash peer, String reason)
      Tell the transport to disconnect from this peer with a reason for logging.
      Parameters:
      peer - the peer to drop, identified by its router hash
      reason - reason for disconnection (for logging), may be null
    • removeCon

      The connection removed; usually the con passed in, but possibly a second connection with the same peer.
      Parameters:
      con - the connection being torn down, whose remote peer identifies it
      Returns:
      usually the con passed in, but possibly a second connection with the same peer... only con or null as of 0.9.37
    • countPeers

      public int countPeers()
      Number of known connections.
      Specified by:
      countPeers in interface Transport
      Specified by:
      countPeers in class TransportImpl
      Returns:
      the number of peers this transport knows of, established or not
    • getPeerCounts

      public int[] getPeerCounts()
      Peer counts by transport type and direction.
      Returns:
      8 bytes: version 1 4 bytes all zeros, version 2 ipv4 in/out, ipv6 in/out
    • getPeers

      public Collection<NTCPConnection> getPeers()
      For /peers UI only. Not a public API, not for external use.
      Returns:
      not a copy, do not modify
    • getEstimatedRTT

      public int getEstimatedRTT(Hash peer)
      Round trip time measured for this peer during the NTCP2 handshake.

      Answers from the session itself rather than from any estimate, so the value has exactly one source: NTCPConnection.getEstimatedRTT(), written once when the handshake completes. Previously this inherited the interface default of 0, which meant no NTCP2 peer was ever considered to have a measured latency, and every profile first-hop RTT derived from a transport reading stayed empty.

      Returns 0 when there is no session or the session has not finished establishing; callers already treat 0 as unknown rather than as an impossibly good peer.

      Parameters:
      peer - the peer to report on
      Returns:
      the measured handshake round trip time in ms, or 0 if unmeasured
    • getEstimatedRTTTime

      public long getEstimatedRTTTime(Hash peer)
      When getEstimatedRTT(Hash) was measured for this peer.

      NTCP2 has no acknowledgement to refresh its reading, so the value is the handshake's for the life of the session and this reports when that handshake completed. A caller that stamps the present onto the value instead would keep a day-old measurement looking fresh and would hold the profile's staleness window open indefinitely.

      Parameters:
      peer - the peer to report on
      Returns:
      the handshake completion time in ms, or Transport.RTT_TIME_UNKNOWN if there is no session or it has not established
    • getEstablished

      public List<Hash> getEstablished()
      Connected peers.
      Returns:
      a copy, modifiable
    • countActivePeers

      public int countActivePeers()
      How many peers have we talked to in the last minute? As of 0.9.20, actually returns active peer count, not total.
      Specified by:
      countActivePeers in interface Transport
      Specified by:
      countActivePeers in class TransportImpl
      Returns:
      the number of such peers
    • countActiveSendPeers

      public int countActiveSendPeers()
      How many peers are we actively sending messages to (this minute).
      Returns:
      active send peer count
    • setLastBadSkew

      void setLastBadSkew(long skew)
      A positive number means our clock is ahead of theirs.
      Parameters:
      skew - the rejected clock skew in seconds
    • getClockSkews

      public List<Long> getClockSkews()
      Peer clock skews on this transport. List composed of Long, each element representing a peer skew in seconds. A positive number means our clock is ahead of theirs.
      Specified by:
      getClockSkews in interface Transport
      Overrides:
      getClockSkews in class TransportImpl
      Returns:
      the clock skews
    • isHXHIValid

      boolean isHXHIValid(byte[] hxhi)
      Incoming connection replay detection. As there is no timestamp in the first message, we can't detect something long-delayed. To be fixed in next version of NTCP.
      Parameters:
      hxhi - using first 8 bytes only
      Returns:
      true if these 8 bytes have not been seen in the last 10 minutes
    • startListening

      public void startListening()
      Starts the NTCP transport listening process, ensuring only one pumper is running by checking existing state since the caller may not stop the transport correctly. It configures and binds local addresses, handles firewall and network interface settings, and sets fallback addresses as needed. This method is synchronized to prevent concurrent starts.
    • chooseListenPort

      private int chooseListenPort(RouterAddress addr, boolean ssuDisabled)
      Selects the port to listen on. Private helper for startListening().

      An address handed back by SSU configuration wins; otherwise the NTCP port is used if SSU (the usual port oracle) is disabled, falling back to the SSU-discovered port.

      Parameters:
      addr - the transport's current configured address, or null
      ssuDisabled - whether UDP is disabled
      Returns:
      the chosen listen port, possibly _ssuPort
    • shouldSkipSavedAddress

      static boolean shouldSkipSavedAddress(boolean ipv6, boolean ipv6Firewalled, boolean propIPv6Firewalled, boolean ssuDisabled, boolean ipv4Firewalled)
      Whether a saved local address should be skipped for publishing. Pure decision helper for restoreSavedLocalAddresses(int, boolean).

      Internet-facing saved addresses are skipped when their family is firewalled; IPv6 additionally honors the explicit i2p.ipv6.firewalled property when UDP is enabled.

      Parameters:
      ipv6 - the address family
      ipv6Firewalled - IPv6 firewall detected
      propIPv6Firewalled - the i2p.ipv6.firewalled property
      ssuDisabled - whether UDP is disabled
      ipv4Firewalled - IPv4 firewall detected
      Returns:
      true if the address must not be published
    • restoreSavedLocalAddresses

      private void restoreSavedLocalAddresses(int port, boolean ssuDisabled)
      Restores the saved local addresses as the published address set. Private helper for startListening().

      Only reached when no address could be bound or configured. Firewalled families are dropped from the set; if no publishable address remains, an outbound-only NTCP2 address is published instead.

      Parameters:
      port - the selected listen port
      ssuDisabled - whether UDP is disabled
    • setOutboundForSkipped

      private void setOutboundForSkipped(int count, boolean skipv6, boolean skipv4)
      Fills in an outbound-only NTCP2 address when saved addresses were partially or fully skipped. Private helper for restoreSavedLocalAddresses(int, boolean).

      With nothing published an outbound NTCP2 address covering both families is published; when only one family was skipped, a single-family outbound marker is merged in.

      Parameters:
      count - number of successfully published saved addresses
      skipv6 - IPv6 addresses were skipped
      skipv4 - IPv4 addresses were skipped
    • setOutboundNTCP2Address

      private void setOutboundNTCP2Address()
      Outbound only, both IPv4 and IPv6, NTCP2 with "s" and "v" only.
    • setOutboundNTCP2Address

      private void setOutboundNTCP2Address(boolean ipv6)
      Outbound only, either IPv4 or IPv6, NTCP2 with "s" and "v" only.
      Parameters:
      ipv6 - true to build the IPv6 outbound address, false for IPv4
    • restartListening

      private void restartListening(RouterAddress addr, boolean ipv6)
      Only called by externalAddressReceived(byte[], boolean, int). Calls replaceAddress() or removeAddress(). To remove all addresses, call replaceAddress(null) directly.

      Doesn't actually restart unless addr is non-null and the port is different from the current listen port. If addr is null, removes the addresses specified (v4 or v6)

      If we had interface addresses before, we lost them.

      Parameters:
      addr - may be null to indicate remove the address
      ipv6 - only used when addr is null, selects address family to remove
    • startIt

      private void startIt()
      Start up. Caller must synchronize.
    • isAlive

      public boolean isAlive()
      Whether the pumper thread is alive.
      Returns:
      true if the transport's pumper thread is running
    • adjustReaderThreads

      public void adjustReaderThreads()
      Adjust reader threads to match configured count.
    • adjustWriterThreads

      public void adjustWriterThreads()
      Adjust writer threads to match configured count.
    • bindAddress

      private RouterAddress bindAddress(int port)
      Only does something if port > 0 and port != current bound port (or there's no current port, or the configured interface or hostname changed). If we are changing the bound port, this restarts everything, which takes a long time.

      call from synchronized method.

      Parameters:
      port - the requested bind port, does nothing if <= 0
      Returns:
      new address ONLY if bound to specific address, otherwise null
    • resolveBindTarget

      private InetAddress resolveBindTarget(String bindTo)
      Resolves the configured bind target to an IP address. Private helper for bindAddress(int).

      An unresolvable configured interface is reported and treated as a wildcard bind (the published address keeps the configured host name).

      Parameters:
      bindTo - the configured interface or fixed host, or null for wildcard
      Returns:
      the resolved address, or null to bind the wildcard
    • buildBoundAddress

      private RouterAddress buildBoundAddress(InetAddress bindToAddr, String bindTo, int port)
      Builds the RouterAddress to publish for a specific-interface bind. Private helper for bindAddress(int).

      The address identifies the bound host and port with the standard NTCP2 options, so a host-specific bind is announced even though every inbound listener shares the transport's cost model.

      Parameters:
      bindToAddr - the resolved bind address
      bindTo - the configured host name or interface as published
      port - the listen port
      Returns:
      the published address
    • isAlreadyListening

      static boolean isAlreadyListening(Set<InetSocketAddress> endpoints, InetSocketAddress addr, InetAddress bindToAddr, int port)
      Whether the transport is already listening on the requested address. Pure decision helper for bindAddress(int).

      An exact match on the bound address short-circuits, as does a hostname bind on the same port as an existing wildcard bind - changing from wildcard to a specified host would otherwise force a needless restart.

      Parameters:
      endpoints - the currently bound server-socket addresses
      addr - the address about to be bound
      bindToAddr - the configured bind target, or null for wildcard
      port - the requested listen port
      Returns:
      true if nothing needs to change
    • isExternalOnlyPortChange

      static boolean isExternalOnlyPortChange(int port, int externalPort, int internalPort)
      Whether a UDP port change is external-only and needs no NTCP restart. Pure decision helper for bindAddress(int).

      When UDP's external port changed to the port being bound but the internal port stayed, the NAT mapping moved; NTCP keeps listening on the internal port and just republishes.

      Parameters:
      port - the requested NTCP listen port
      externalPort - the configured UDP external port
      internalPort - the configured UDP internal port
      Returns:
      true when only the published port must change
    • getFixedHost

      private String getFixedHost()
      The host to advertise, fixed by config if set.
      Returns:
      configured host (as an IP String) or null. Must be one of our local interfaces.
    • stopWaitAndRestart

      private void stopWaitAndRestart()
      Caller must sync.
    • getReader

      Reader getReader()
      The single reader thread shared by every NTCPConnection: one reader is started for the transport, and connections register with it rather than starting a thread each.
      Returns:
      the transport's shared reader thread
    • getWriter

      Writer getWriter()
      The single writer thread shared by every NTCPConnection, started alongside the reader.
      Returns:
      the transport's shared writer thread
    • getStyle

      public String getStyle()
      Transport style.
      Returns:
      always the string "NTCP"
    • getAltStyle

      public String getAltStyle()
      Alternate supported style.
      Overrides:
      getAltStyle in class TransportImpl
      Returns:
      "NTCP2" always
    • getPublishStyle

      private String getPublishStyle()
      The style to publish.
      Returns:
      "NTCP2" always
    • getPumper

      EventPumper getPumper()
      The single event pumper shared by every NTCPConnection, which also drives the periodic close of connections that never establish.
      Returns:
      the transport's shared event pumper
    • getXDHFactory

      X25519KeyFactory getXDHFactory()
      The X25519 key factory backing NTCP2 static key agreement, absent when the router was configured without NTCP2.
      Returns:
      null if not configured for NTCP2
    • getEstablishTimeout

      public static int getEstablishTimeout()
      NTCP establish timeout in ms.
      Returns:
      the current establishment timeout, 1500 to 10000
    • setEstablishTimeout

      public static void setEstablishTimeout(int ms)
      NTCP establish timeout, bounded 1500-10000ms.
      Parameters:
      ms - the requested timeout in ms, clamped into 1500 to 10000
    • establishing

      void establishing(NTCPConnection con)
      Add us to the establishment timeout process.
      Parameters:
      con - the connection being established, which expireTimedOut() closes if it has not established in time
    • expireTimedOut

      void expireTimedOut()
      Called in the EventPumper no more than once a second or so, closing any unconnected/unestablished connections.
    • configureLocalAddress

      private RouterAddress configureLocalAddress()
      Generally returns null. Caller must synch on this. Note this is only called from startListening(). Only returns non-null if port is configured.
      Returns:
      the configured local address, normally null for outbound-only, non-null only when a valid NTCP port is set
    • createNTCPAddress

      private RouterAddress createNTCPAddress()
      This only creates an address if the hostname AND port are set in router.config, which should be rare. Otherwise, notifyReplaceAddress() below takes care of it. Note this is only called from startListening() via configureLocalAddress(). Unlike in UDP rebuildExternalAddress(), this only runs once, at startup, so we won't pick up IP changes. Only returns non-null if port is configured.
      Returns:
      the address built from the configured hostname and port, null if either is missing or invalid
    • addNTCP2Options

      private void addNTCP2Options(Properties props)
      Add the required options to the properties for a NTCP2 address. Host/port must already be set in props if they are going to be.
      Parameters:
      props - the address properties to add the NTCP2 options to
    • getNTCP2StaticPubkey

      byte[] getNTCP2StaticPubkey()
      The NTCP2 static public key Bob publishes to Alice, base64 of the raw key.
      Returns:
      the NTCP2 static public key
    • getNTCP2StaticPrivkey

      byte[] getNTCP2StaticPrivkey()
      The NTCP2 static private key for this router's own NTCP2 sessions.
      Returns:
      the NTCP2 static private key
    • getNTCP2StaticIV

      byte[] getNTCP2StaticIV()
      The NTCP2 static IV, shared by both sides of an NTCP2 session.
      Returns:
      the NTCP2 static IV
    • getNTCPVersion

      private static int getNTCPVersion(RouterAddress addr)
      Valid NTCP version of Bob's NTCP address for our outbound connections as Alice.
      Parameters:
      addr - Bob's NTCP router address to evaluate
      Returns:
      the valid version 2-5, 1 for old NTCP1, or 0 if unusable
    • getConfiguredIP

      private String getConfiguredIP()
      Single configured IP (as a String) or null if not configured or invalid. Resolves a hostname to an IP. Called at startup via createNTCPAddress() and later via externalAddressReceived().
      Returns:
      the configured IP
    • alreadyHaveFamily

      static boolean alreadyHaveFamily(boolean v4, boolean v6, int addrLen)
      Whether an address family has already contributed an address to the configured-IP list. Pure decision helper for getConfiguredIP().

      Hostnames may resolve to several addresses; at most one IPv4 and one IPv6 address are published.

      Parameters:
      v4 - an IPv4 address is already selected
      v6 - an IPv6 address is already selected
      addrLen - address length in bytes, 4 for IPv4 or 16 for IPv6
      Returns:
      true if that family is already represented
    • isBlankName

      static boolean isBlankName(String name)
      Whether the configured hostname is absent or unusable. Pure decision helper for getConfiguredIP().

      Empty, whitespace-only, and the literal "null" (from a cleared config) values are all treated as unset.

      Parameters:
      name - the i2p.ntcp.hostname value, or null
      Returns:
      true if no usable configured host exists
    • choosePrimaryIP

      static String choosePrimaryIP(List<String> ipstrings)
      Picks the primary configured IP: the first IPv4, else the first IPv6. Pure decision helper for getConfiguredIP().
      Parameters:
      ipstrings - the collected addresses, in resolution order
      Returns:
      the primary address; the list must not be empty
    • getDefaultCost

      private int getDefaultCost(boolean isIPv6)
      Returns the peer selection cost for this transport.
      Parameters:
      isIPv6 - true to price an IPv6 connection
      Returns:
      the default cost
    • externalAddressReceived

      public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port)
      UDP changed addresses, tell NTCP and (possibly) restart.
      Specified by:
      externalAddressReceived in interface Transport
      Specified by:
      externalAddressReceived in class TransportImpl
      Parameters:
      source - defined in Transport.java
      ip - typ. IPv4 or IPv6 non-local; may be null to indicate IPv4 failure or port info only
      port - 0 for unknown or unchanged
    • externalAddressRemoved

      public void externalAddressRemoved(Transport.AddressSource source, boolean ipv6)
      Notify a transport of an external address change. This may be from a local interface, UPnP, a config change, etc. This should not be called if the ip didn't change (from that source's point of view), or is a local address. May be called multiple times for IPv4 or IPv6. The transport should also do its own checking on whether to accept notifications from this source.

      This can be called after the transport is running.

      Specified by:
      externalAddressRemoved in interface Transport
      Overrides:
      externalAddressRemoved in class TransportImpl
      Parameters:
      source - defined in Transport.java
      ipv6 - true for IPv6, false for IPv4
    • addressChanged

      private void addressChanged(CommSystemFacade.Status old)
      Only called if SSU is disabled AND our address changed. Tell the event log, and tell the router.
      Parameters:
      old - the reachability status before the change
    • externalAddressReceived

      private boolean externalAddressReceived(byte[] ip, boolean isIPv6, int port)
      UDP changed addresses, tell NTCP and restart. Port may be set to indicate requested port even if ip is null.
      Parameters:
      ip - previously validated; may be null to indicate IPv4 failure or port info only
      isIPv6 - true for the IPv6 address, false for IPv4
      port - the requested port, 0 when not specified
      Returns:
      true if our address changed
    • forwardPortStatus

      public void forwardPortStatus(byte[] ip, int port, int externalPort, boolean success, String reason)
      If we didn't used to be forwarded, and we have an address, and we are configured to use UPnP, update our RouterAddress

      Don't do anything now. If it fails, we don't know if it's because there is no firewall, or if the firewall rejected the request. So we just use the SSU reachability status to decide whether to enable inbound NTCP. SSU will have CSFI build a new NTCP address when it transitions to OK.

      Specified by:
      forwardPortStatus in interface Transport
      Overrides:
      forwardPortStatus in class TransportImpl
      Parameters:
      ip - may be null
      port - the internal port
      externalPort - the external port, which for now should always be the same as the internal port if the forwarding was successful.
      success - true if the router managed to establish the mapping
      reason - the text describing the outcome, for the console and the logs
    • getRequestedPort

      public int getRequestedPort()
      The port requested by config, -1 for automatic.
      Specified by:
      getRequestedPort in interface Transport
      Overrides:
      getRequestedPort in class TransportImpl
      Returns:
      current IPv4 port, else NTCP configured port, else -1 (but not UDP port if auto)
    • decideReachabilityHeader

      static CommSystemFacade.Status decideReachabilityHeader(boolean fwV4, boolean fwV6, boolean alive, boolean hasV4, boolean hasV6, boolean showFirewalled)
      Decides the reachability status that does not depend on live inbound connections. Pure decision helper for getReachabilityStatus().

      Mirrors the ordering of the original cascades exactly: both families firewalled yields rejection before the liveness check, and a router with no published address reports firewalled only once it has been up long enough for the status to be meaningful.

      Parameters:
      fwV4 - IPv4 firewall reported
      fwV6 - IPv6 firewall reported
      alive - whether the transport is currently listening
      hasV4 - a published non-firewalled IPv4 address is present
      hasV6 - a published non-firewalled IPv6 address is present
      showFirewalled - SSU disabled and the router has been up more than 10 minutes
      Returns:
      the final status, or null when a live inbound-connection check is required
    • decideReachabilityFromInboundActivity

      static CommSystemFacade.Status decideReachabilityFromInboundActivity(boolean v4OK, boolean v6OK, boolean v4Disabled, boolean v6Disabled, boolean fwV4, boolean fwV6, boolean hasV4, boolean hasV6, boolean haveIPv6Address, boolean showFirewalled)
      Decides the reachability status from recent inbound activity of each address family. Pure decision helper for getReachabilityStatus().

      When either family has seen an inbound connection recently, the verdict is positive for both families unless the other family is explicitly firewalled, disabled, or simply absent.

      Parameters:
      v4OK - recent IPv4 inbound activity (or later enabled by a live connection)
      v6OK - recent IPv6 inbound activity (or later enabled by a live connection)
      v4Disabled - IPv4 address family disabled by configuration
      v6Disabled - IPv6 address family disabled by configuration
      fwV4 - IPv4 firewall reported
      fwV6 - IPv6 firewall reported
      hasV4 - a published non-firewalled IPv4 address is present
      hasV6 - a published non-firewalled IPv6 address is present
      haveIPv6Address - an IPv6 address was ever seen on a local interface or SSU
      showFirewalled - SSU disabled and the router has been up more than 10 minutes
      Returns:
      the final status, or null when the live inbound-connection check is required
    • decideReachabilityTail

      static CommSystemFacade.Status decideReachabilityTail(boolean v4OK, boolean v6OK, boolean v4Disabled, boolean showFirewalled, boolean haveIPv6Address)
      Decides the reachability status after the live inbound-connection scan. Pure decision helper for getReachabilityStatus().

      Half-OK verdicts fall back to the per-family status of the working family; a family that reports OK only because of a live connection and is the only working family reports as reachable.

      Parameters:
      v4OK - whether v4 may be treated as reachable after the scan
      v6OK - whether v6 may be treated as reachable after the scan
      v4Disabled - IPv4 address family disabled by configuration
      showFirewalled - SSU disabled and the router has been up more than 10 minutes
      haveIPv6Address - an IPv6 address was ever seen on a local interface or SSU
      Returns:
      the final status; never null
    • isFamilyDisabled

      static boolean isFamilyDisabled(TransportUtil.IPv6Config config, boolean isIPv6)
      Whether an address family is disabled by the IPv6 configuration. Pure decision helper for getReachabilityStatus().

      An IPv6-disabled router publishes no IPv6 addresses and an IPv6-only router publishes no IPv4 addresses; anything in between enables both families.

      Parameters:
      config - the router's IPv6 configuration
      isIPv6 - the address family to query
      Returns:
      true if that family is disabled
    • isBlank

      static boolean isBlank(String s)
      Whether a configured value counts as absent.
      Parameters:
      s - the value
      Returns:
      true if it is null or the empty string
    • wantsAutoHost

      static boolean wantsAutoHost(String enabled, boolean ssuOK)
      Whether the auto-host setting wants to publish an externally detected IP. Pure decision helper for externalAddressReceived(byte[], boolean, int).

      Hostname configuration trumps auto-IP (encoded as "false"), a value of "always" ignores reachability, otherwise "true" takes effect only when SSU reports the address as usable.

      Parameters:
      enabled - the normalized i2p.ntcp.autoip preference
      ssuOK - whether a usable IP was supplied in the notification
      Returns:
      true when the auto host should be applied
    • wantsConfiguredHost

      static boolean wantsConfiguredHost(String enabled, String name, String ohost)
      Whether the configured hostname should be published in place of the current host. Pure decision helper for externalAddressReceived(byte[], boolean, int).

      Only when auto-IP is off, a hostname is configured, and it differs from the currently published host does the configuration win.

      Parameters:
      enabled - the normalized i2p.ntcp.autoip preference
      name - the configured hostname, or null
      ohost - the currently published host, or null
      Returns:
      true when the configured host should be applied
    • wantsRemoveAutoHost

      static boolean wantsRemoveAutoHost(String enabled, boolean ssuOK)
      Whether a previously auto-published address should be dropped. Pure decision helper for externalAddressReceived(byte[], boolean, int).

      Auto-IP hosts are removed when the notify source stops reporting a usable address (e.g. a follow-up SSU peer test determined the router is still firewalled).

      Parameters:
      enabled - the normalized i2p.ntcp.autoip preference
      ssuOK - whether a usable IP was supplied in the notification
      Returns:
      true when the auto host should be removed
    • wantsFullOptions

      static boolean wantsFullOptions(boolean isIPv6, OrderedProperties props, TransportUtil.IPv6Config config)
      Whether the address should carry the full NTCP2 option set. Pure decision helper for externalAddressReceived(byte[], boolean, int).

      The full options are added for IPv4 always, and for IPv6 when the notification carried a usable host or IPv6 is the only enabled family; otherwise the router publishes an outbound-only NTCP2 address instead.

      Parameters:
      isIPv6 - the address family of the notification
      props - the newly built address options
      config - the router's IPv6 configuration
      Returns:
      true when the full options should be applied
    • chooseAutomaticPort

      private String chooseAutomaticPort(String configuredPort, int notifiedPort)
      Selects the port to publish for the NTCP address. Private helper for externalAddressReceived(byte[], boolean, int).

      An explicit configured port trumps everything, and the notification port is only used when auto-port is enabled. A mismatch between the UDP-detected external port and the explicitly configured port is logged - the NAT is probably mapping UDP and TCP differently, so NTCP binds the config.

      Parameters:
      configuredPort - the i2p.ntcp.port value, or null
      notifiedPort - the externally detected port, or 0
      Returns:
      the port to publish, or null to keep the current one
    • handleIPv6FirewalledTransition

      private boolean handleIPv6FirewalledTransition(boolean isIPv6, RouterAddress oldAddr, byte[] ip, int port)
      Handles a notification that carries no host at all. Private helper for externalAddressReceived(byte[], boolean, int).

      When a configured IPv6 address is removed (SSU2 told us to drop it) and the IPv4 address still advertises the IPv6 capability, nothing is published; if the IPv4 address lacks the capability, an outbound-only IPv6 marker is added so peers stop trying IPv6 inbound.

      Parameters:
      isIPv6 - the family being notified
      oldAddr - the current address for that family, may be null for IPv6
      ip - the notification IP, may be null
      port - the notification port, may be 0
      Returns:
      true if the NTCP address changed
    • getReachabilityStatus

      public CommSystemFacade.Status getReachabilityStatus()
      Maybe we should trust UPnP here and report OK if it opened the port, but for now we don't. Just go through and if we have one inbound connection, we must be good. As we drop idle connections pretty quickly, this will be fairly accurate.

      We have to be careful here because much of the router console code assumes that the reachability status is really just the UDP status.

      This only returns OK, DISABLED, or UNKNOWN for IPv4 and IPv6. We leave the FIREWALLED status for UDP.

      Previously returned short, now enum as of 0.9.20.

      Specified by:
      getReachabilityStatus in interface Transport
      Specified by:
      getReachabilityStatus in class TransportImpl
      Returns:
      the reachability status
    • stopListening

      public void stopListening()
      This doesn't (completely) block, caller should check isAlive() before calling startListening() or restartListening(RouterAddress, boolean).
    • shouldSuppressException

      private boolean shouldSuppressException(Throwable t)
      Determines whether the given Throwable (or any of its causes) contains a message that should be suppressed from logging.
      Parameters:
      t - the Throwable to check
      Returns:
      true if the exception should be suppressed, false otherwise
    • getSelectorLoopDelay

      public static long getSelectorLoopDelay()
      Selector loop delay in milliseconds.
      Returns:
      the delay between selector wakeups, 1 to 20
    • setSelectorLoopDelay

      public static void setSelectorLoopDelay(long ms)
      Selector loop delay, bounded 1-20ms.
      Parameters:
      ms - the requested delay in ms, clamped into 1 to 20
    • getMaxIdleLps

      public static int getMaxIdleLps()
      Max idle loop rate in loops per second.
      Returns:
      the idle-loop ceiling in loops per second, 1 to 5000
    • setMaxIdleLps

      public static void setMaxIdleLps(int lps)
      Max idle loop rate in loops per second, bounded 1-5000.
      Parameters:
      lps - the requested ceiling in loops per second, clamped into 1 to 5000
    • getFailsafeIterationFreq

      public static long getFailsafeIterationFreq()
      Failsafe iteration frequency in milliseconds.
      Returns:
      the interval between failsafe passes, 2000 to 30000
    • setFailsafeIterationFreq

      public static void setFailsafeIterationFreq(long ms)
      Failsafe iteration frequency, bounded to 2000-30000ms.
      Parameters:
      ms - the requested interval in ms, clamped into 2000 to 30000
    • getSendFinisherMaxThreads

      public static int getSendFinisherMaxThreads()
      Send finisher max threads.
      Returns:
      the send finisher pool's maximum thread count, 2 to 16
    • setSendFinisherMaxThreads

      public static void setSendFinisherMaxThreads(int threads)
      Send finisher max threads, bounded 2-16.
      Parameters:
      threads - the requested thread ceiling, clamped into 2 to 16
    • getSendFinisherQueueCapacity

      public static int getSendFinisherQueueCapacity()
      Send finisher queue capacity.
      Returns:
      the send finisher queue depth, 256 to 16384
    • setSendFinisherQueueCapacity

      public static void setSendFinisherQueueCapacity(int capacity)
      Send finisher queue capacity, bounded 256-16384.
      Parameters:
      capacity - the requested queue depth, clamped into 256 to 16384
    • adjustSendFinisherThreads

      public void adjustSendFinisherThreads(int threads)
      Adjusts the send finisher thread count for the running pool.
      Parameters:
      threads - new thread count (core and max)
    • getSendFinisherQueueSize

      public int getSendFinisherQueueSize()
      Current send finisher queue depth.
      Returns:
      pending tasks count
    • getSendFinisherUtilization

      public double getSendFinisherUtilization()
      Send finisher pool utilization as a ratio (0.0-1.0). Returns NaN if pool not started.
      Returns:
      the send finisher utilization
    • getReaderUtilization

      public double getReaderUtilization()
      Reader pool utilization as a ratio (0.0-1.0). Returns NaN if not started.
      Returns:
      the reader utilization
    • getWriterUtilization

      public double getWriterUtilization()
      Writer pool utilization as a ratio (0.0-1.0). Returns NaN if not started.
      Returns:
      the writer utilization