- All Implemented Interfaces:
Transport
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
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static enumThe bid tier selected by the capacity/cost cascade, in order from most to least attractive.(package private) static enumHow a peer's announced network id compares with ours: the same, absent, or a different network, whichbid(RouterInfo, int)treats as grounds for a ban rather than an unreachable peer.private classCache the bid to reduce object churn.Nested classes/interfaces inherited from interface Transport
Transport.AddressSourceModifier and TypeInterfaceDescriptionstatic enumSource of transport address configuration.Field Summary
Modifier and TypeFieldDescriptionprivate final StringStatic IV, base64, for the router info.private final StringStatic public key, base64, for the router info.private final BanLoggerRecords why routers were banned.private final ConcurrentHashMap<Hash, NTCPConnection> Open connections, by peer hash.private final ObjectLock for the connection maps.private final Set<InetSocketAddress> Bound listening endpoints.private final Set<NTCPConnection> List of NTCPConnection of connections not yet established that we want to remove on establishment or close on timeout.Peers this transport closed an idle session to, and when.private final NTCPTransport.SharedBidPeer selection bid for fast peers.private final NTCPSendFinisherCloses connections after their writes finish.private booleanDo we have a public IPv6 address?private longWhen a bad clock skew was last logged.private longWhen the last inbound IPv4 connection arrived.private longWhen the last inbound IPv6 connection arrived.private final LogLogger for NTCP connections.private final NTCPTransport.SharedBidSave some conns for inbound.private final NTCPTransport.SharedBidBid raising costs when near capacity.private final intThe network id we communicate on.private final byte[]Our NTCP2 static initialization vector.private final byte[]Our NTCP2 static private key.private final byte[]Our NTCP2 static public key.private final EventPumperNIO event pumper for the connections.private final ReaderThe accept and connect thread.private final DecayingBloomFilter"bloom filter".private final NTCPTransport.SharedBidPeer selection bid for slow peers.private final NTCPTransport.SharedBidBid raising the cost of slow peers.private intSSU port advertised in NTCP2 handshakes.private final NTCPTransport.SharedBidBid for peers with transient failures.private WriterThe write thread, null until started.private final X25519KeyFactoryFactory for the NTCP2 ephemeral key pairs.private static final intDefault peer selection cost for NTCP.(package private) static intHow long from initial connection attempt (accept() or connect()) until the con must be established to avoid premature close()ing.private static final longHow far back a failsafe close keeps its peer attributable.private static final intUpper bound on peers remembered for failsafe closes.private static final longDowntime after which the NTCP2 static key is replaced.private static final longDowntime after which a hidden router rekeys.static final StringRI sigtypes supported in 0.9.16.(package private) static final intNTCP2 protocol version.private static final intNTCP2 handshake IV length, in bytes.private static final intNTCP2 handshake key length, in bytes.private static final intPeer selection cost for outbound NTCP2.(package private) static final String"2".(package private) static final String"2,".(package private) static final int0 to disable, or 3/4/5 for enctypes 5/6/7.(package private) static final StringPQ protocol version string.static final StringThis is rarely if ever used, default is to bind to wildcard address.static final StringConfig key controlling whether NTCP may auto-update its advertised IP based on peer feedback.static final StringConfig key controlling whether NTCP may auto-update its advertised port based on peer feedback.static final StringConfig key for an explicitly configured hostname the NTCP transport advertises.static final StringConfig key for the port the NTCP transport listens for inbound connections on.static final StringConfig key for the base-64 NTCP2 static IV.static final StringConfig key for the base-64 NTCP2 static private key.private static final long[]Rate stat periods for the connection statistics.static final StringStyle identifier for the NTCP transport.static final StringStyle identifier for the NTCP2 protocol variant.Disconnect reasons with repetitive log suppression.Fields inherited from class TransportImpl
_context, ADJUST_COST, CAP_IPV4, CAP_IPV4_IPV6, CAP_IPV6, CONGESTION_COST_ADJUSTMENT, PROP_BOOST_CONNECTION_LIMITS, PROP_IPV6_FIREWALLEDModifier and TypeFieldDescriptionprotected final RouterContextThe router context, which every subclass reads its configuration from.protected static final booleanDo we increase the advertised cost when approaching conn limits?static final StringAdvertised reachability value for a working IPv4 address.static final StringAdvertised reachability value for both address families.static final StringAdvertised reachability value for a working IPv6 address.protected static final intAdjustment factor for congestion cost.protected static final StringProperty allowing a transport to lift its connection limit.protected static final StringProperty recording the result of the last IPv6 firewall test.Fields inherited from interface Transport
DEFAULT_SOURCES, PROP_EXTERNAL_HOST, PROP_EXTERNAL_PORT, PROP_FIXED_PORT, PROP_FORCE_INTRODUCERS, PROP_INTERNAL_PORT, PROP_INTRO_KEY, PROP_IP, PROP_IPV6, PROP_LAPTOP_MODE, PROP_SOURCES, PROP_SSU2_IKEY, PROP_SSU2_SP, RTT_TIME_CURRENT, RTT_TIME_UNKNOWN, STYLE_NTCP, STYLE_NTCP2, STYLE_SSU, STYLE_SSU2Modifier and TypeFieldDescriptionstatic final StringDefault value ofTransport.PROP_SOURCES: the local interface, UPnP, and SSU-learned addresses.static final StringConfig key to force advertising a fixed external IP address.static final StringConfig key to force advertising a fixed external port.static final StringConfig key to keep the SSU advertised port fixed regardless of peer feedback.static final StringConfig key to require SSU introducers regardless of our reachability status.static final StringConfig key for the SSU internal port, the port the SSU transport binds.static final StringConfig key for the SSU introducer key published in hidden-mode RouterInfos.static final StringConfig key remembering the last IPv4 address so IP changes can be detected across restarts.static final StringConfig key remembering the last IPv6 address.static final StringConfig key enabling laptop power-saving mode, which reduces connection activity.static final StringConfig key naming the allowed sources of address updates, e.g.static final StringConfig key for the SSU2 static IV.static final StringConfig key for the SSU2 static private key.static final longSentinel forTransport.getEstimatedRTTTime(Hash)meaning the transport's reading is refreshed by live traffic and is never out of date.static final longSentinel forTransport.getEstimatedRTTTime(Hash)meaning the transport does not record when it measured.static final StringStyle identifier for the NTCP transport, used inRouterAddressstyle tags, transport map keys, and style comparisons.static final StringStyle identifier for the NTCP2 protocol variant of the NTCP transport.static final StringStyle identifier for the SSU transport, used in RouterAddress style tags, transport map keys, and style comparisons.static final StringStyle identifier for the SSU2 protocol variant of the SSU transport.Constructor Summary
ConstructorsConstructorDescriptionNTCPTransport(RouterContext ctx, X25519KeyFactory xdh) Registers the NTCP rate statistics and loads or creates the NTCP2 static keys; nothing is started untilstartListening().Method Summary
Modifier and TypeMethodDescriptionprivate voidaddNTCP2Options(Properties props) Add the required options to the properties for a NTCP2 address.private voidOnly called if SSU is disabled AND our address changed.voidAdjust reader threads to match configured count.voidadjustSendFinisherThreads(int threads) Adjusts the send finisher thread count for the running pool.voidAdjust writer threads to match configured count.voidafterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue, long msToSend) Notify after the message send attempt completes.booleanWhether an additional outbound connection may be accepted.(package private) static booleanalreadyHaveFamily(boolean v4, boolean v6, int addrLen) Whether an address family has already contributed an address to the configured-IP list.bid(RouterInfo toAddress, int dataSize) Bid on sending the message to the target.private TransportBidbidFor(NTCPTransport.BidTier tier) Map a bid tier to the cached shared bid, so the compare-and-log hot path allocates nothing.private RouterAddressbindAddress(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).private RouterAddressbuildBoundAddress(InetAddress bindToAddr, String bindTo, int port) Builds the RouterAddress to publish for a specific-interface bind.private StringchooseAutomaticPort(String configuredPort, int notifiedPort) Selects the port to publish for the NTCP address.(package private) static NTCPTransport.BidTierchooseBidTier(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.private intchooseListenPort(RouterAddress addr, boolean ssuDisabled) Selects the port to listen on.(package private) static StringchoosePrimaryIP(List<String> ipstrings) Picks the primary configured IP: the first IPv4, else the first IPv6.(package private) static NTCPTransport.NetworkIdIssueclassifyNetworkId(int nid, int ourNetworkID) Classify the peer's network id relative to ours, for the ban-on-mismatch decision inbid(RouterInfo, int).private RouterAddressGenerally returns null.intHow many peers have we talked to in the last minute? As of 0.9.20, actually returns active peer count, not total.intHow many peers are we actively sending messages to (this minute).intNumber of known connections.private RouterAddressThis only creates an address if the hostname AND port are set inrouter.config, which should be rare.(package private) static CommSystemFacade.StatusdecideReachabilityFromInboundActivity(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.(package private) static CommSystemFacade.StatusdecideReachabilityHeader(boolean fwV4, boolean fwV6, boolean alive, boolean hasV4, boolean hasV6, boolean showFirewalled) Decides the reachability status that does not depend on live inbound connections.(package private) static CommSystemFacade.StatusdecideReachabilityTail(boolean v4OK, boolean v6OK, boolean v4Disabled, boolean showFirewalled, boolean haveIPv6Address) Decides the reachability status after the live inbound-connection scan.(package private) voidAdd us to the establishment timeout process.(package private) voidCalled in the EventPumper no more than once a second or so, closing any unconnected/unestablished connections.private booleanexternalAddressReceived(byte[] ip, boolean isIPv6, int port) UDP changed addresses, tell NTCP and restart.voidexternalAddressReceived(Transport.AddressSource source, byte[] ip, int port) UDP changed addresses, tell NTCP and (possibly) restart.voidexternalAddressRemoved(Transport.AddressSource source, boolean ipv6) Notify a transport of an external address change.(package private) static booleanfailsafeCloseStillRemembered(long closedAt, long now, long window) Whether a remembered close is still inside its memory window.voidforceDisconnect(Hash peer) Tell the transport to disconnect from this peer.voidforceDisconnect(Hash peer, String reason) Tell the transport to disconnect from this peer with a reason for logging.voidforwardPortStatus(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 RouterAddressAlternate supported style.Peer clock skews on this transport.private StringSingle configured IP (as a String) or null if not configured or invalid.private NTCPConnectiongetConnectionOrCreateNew(Hash ih, RouterInfo target) Retrieves an existing NTCPConnection for the given peer hash or creates a new one.private intgetDefaultCost(boolean isIPv6) Returns the peer selection cost for this transport.Connected peers.static intNTCP establish timeout in ms.intgetEstimatedRTT(Hash peer) Round trip time measured for this peer during the NTCP2 handshake.longgetEstimatedRTTTime(Hash peer) WhengetEstimatedRTT(Hash)was measured for this peer.static longFailsafe iteration frequency in milliseconds.private StringThe host to advertise, fixed by config if set.private StringExtract IP:port fromRouterInfofor NTCP transport.static intMax idle loop rate in loops per second.(package private) byte[]The NTCP2 static IV, shared by both sides of an NTCP2 session.(package private) byte[]The NTCP2 static private key for this router's own NTCP2 sessions.(package private) byte[]The NTCP2 static public key Bob publishes to Alice, base64 of the raw key.private static intgetNTCPVersion(RouterAddress addr) Valid NTCP version of Bob's NTCP address for our outbound connections as Alice.int[]Peer counts by transport type and direction.getPeers()For /peers UI only.private StringThe style to publish.(package private) EventPumperThe single event pumper shared by every NTCPConnection, which also drives the periodic close of connections that never establish.Maybe we should trust UPnP here and report OK if it opened the port, but for now we don't.(package private) ReaderThe 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.doubleReader pool utilization as a ratio (0.0-1.0).intThe port requested by config, -1 for automatic.static longSelector loop delay in milliseconds.static intSend finisher max threads.static intSend finisher queue capacity.intCurrent send finisher queue depth.doubleSend finisher pool utilization as a ratio (0.0-1.0).getStyle()Transport style.private RouterAddressgetTargetAddress(RouterInfo target) Get first available address we can use.(package private) WriterThe single writer thread shared by every NTCPConnection, started alongside the reader.doubleWriter pool utilization as a ratio (0.0-1.0).(package private) X25519KeyFactoryThe X25519 key factory backing NTCP2 static key agreement, absent when the router was configured without NTCP2.private booleanhandleIPv6FirewalledTransition(boolean isIPv6, RouterAddress oldAddr, byte[] ip, int port) Handles a notification that carries no host at all.(package private) NTCPConnectionRegisters a newly established inbound connection, replacing any existing connection for the same peer.booleanisAlive()Whether the pumper thread is alive.(package private) static booleanWhether the connection's outbound establishment has already left the initial state, in which case prepareOutbound() must not be called again.(package private) static booleanisAlreadyListening(Set<InetSocketAddress> endpoints, InetSocketAddress addr, InetAddress bindToAddr, int port) Whether the transport is already listening on the requested address.booleanisBacklogged(Hash dest) Whether the connection to the given peer is backlogged.(package private) static booleanWhether a configured value counts as absent.(package private) static booleanisBlankName(String name) Whether the configured hostname is absent or unusable.(package private) static booleanisConnectableVersion(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 asMIN_SIGTYPE_VERSION.booleanisConnecting(Hash dest) Whether a connection attempt is in progress to the given peer.booleanisEstablished(Hash dest) Whether the given peer is established.(package private) static booleanWhether the exception is the expected channel-setup race: the peer started building the tunnel before we called prepareOutbound().(package private) static booleanisExternalOnlyPortChange(int port, int externalPort, int internalPort) Whether a UDP port change is external-only and needs no NTCP restart.(package private) static booleanisFamilyDisabled(TransportUtil.IPv6Config config, boolean isIPv6) Whether an address family is disabled by the IPv6 configuration.(package private) booleanisHXHIValid(byte[] hxhi) Incoming connection replay detection.(package private) static booleanisOwnRouterInfoStore(I2NPMessage m, Hash ourHash) Whether a DatabaseStoreMessage stored our own RouterInfo under our own key.(package private) static booleanWhether a DatabaseStoreMessage of our own RouterInfo carries a flood reply token.(package private) static booleanisSigTypeUsable(SigType type) Whether the peer's signature type is usable: it must exist and be available on this build.(package private) static booleanisTooLargeForNTCP2(int dataSize) Whether the message is too large for NTCP2 to carry.private booleanisValid(byte[] addr) An IPv6 address is only valid if we are configured to support IPv6 AND we have a public IPv6 address.private voidLogs errors or warnings related to connection setup failures, differentiating between IOExceptions and IllegalStateExceptions with appropriate log levels.voidmayDisconnect(Hash peer) Tell the transport that we may disconnect from this peer.(package private) voidnoteFailsafeClose(Hash peer, long now) Record that an idle session to this peer was just closed.protected voidProcesses the next outbound message by retrieving or creating a connection, preparing it for sending, and handling related failures or bans.private voidPrepares 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.private booleanpruneFailsafeCloses(long now) Drop remembered closes that have aged out of the memory window.(package private) NTCPConnectionremoveCon(NTCPConnection con) The connection removed; usually the con passed in, but possibly a second connection with the same peer.private InetAddressresolveBindTarget(String bindTo) Resolves the configured bind target to an IP address.private voidrestartListening(RouterAddress addr, boolean ipv6) Only called byexternalAddressReceived(byte[], boolean, int).private voidrestoreSavedLocalAddresses(int port, boolean ssuDisabled) Restores the saved local addresses as the published address set.(package private) voidQueue up the afterSend call, which can take some time with jobs, etc.static voidsetEstablishTimeout(int ms) NTCP establish timeout, bounded 1500-10000ms.static voidsetFailsafeIterationFreq(long ms) Failsafe iteration frequency, bounded to 2000-30000ms.(package private) voidsetLastBadSkew(long skew) A positive number means our clock is ahead of theirs.static voidsetMaxIdleLps(int lps) Max idle loop rate in loops per second, bounded 1-5000.private voidsetOutboundForSkipped(int count, boolean skipv6, boolean skipv4) Fills in an outbound-only NTCP2 address when saved addresses were partially or fully skipped.private voidOutbound only, both IPv4 and IPv6, NTCP2 with "s" and "v" only.private voidsetOutboundNTCP2Address(boolean ipv6) Outbound only, either IPv4 or IPv6, NTCP2 with "s" and "v" only.static voidsetSelectorLoopDelay(long ms) Selector loop delay, bounded 1-20ms.static voidsetSendFinisherMaxThreads(int threads) Send finisher max threads, bounded 2-16.static voidsetSendFinisherQueueCapacity(int capacity) Send finisher queue capacity, bounded 256-16384.private intPick a port if not previously configured.(package private) static booleanshouldSendInfoNow(boolean shouldSkipInfo, boolean shouldFlood, int version) Whether the outbound message should be sent on the connection instead of skipped.(package private) static booleanshouldSkipSavedAddress(boolean ipv6, boolean ipv6Firewalled, boolean propIPv6Firewalled, boolean ssuDisabled, boolean ipv4Firewalled) Whether a saved local address should be skipped for publishing.private booleanDetermines whether the given Throwable (or any of its causes) contains a message that should be suppressed from logging.private voidstartIt()Start up.voidStarts the NTCP transport listening process, ensuring only one pumper is running by checking existing state since the caller may not stop the transport correctly.voidThis doesn't (completely) block, caller should checkisAlive()before calling startListening() orrestartListening(RouterAddress, boolean).private voidCaller must sync.private voidupdateInboundIPStats(boolean ipv6, long created) Updates statistics and reachability status related to inbound connections based on IP version and connection creation time.(package private) static booleanwantsAutoHost(String enabled, boolean ssuOK) Whether the auto-host setting wants to publish an externally detected IP.(package private) static booleanwantsConfiguredHost(String enabled, String name, String ohost) Whether the configured hostname should be published in place of the current host.(package private) static booleanwantsFullOptions(boolean isIPv6, OrderedProperties props, TransportUtil.IPv6Config config) Whether the address should carry the full NTCP2 option set.(package private) static booleanwantsRemoveAutoHost(String enabled, boolean ssuOK) Whether a previously auto-published address should be dropped.booleanwasFailsafeClosed(Hash peer, long withinMs) Whether the peer's most recent connection was closed by the failsafe.Methods inherited from class TransportImpl
_t, _t, afterSend, afterSend, afterSend, allowLocal, formatIPPort, getContext, getCurrentAddress, getCurrentAddresses, getCurrentIPv4, getIP, getIPv6Config, getMaxConnections, getMostRecentErrorMessages, getNextMessage, getRouterIPPort, getSavedLocalAddresses, getSendPool, getSendPoolCapacity, getTargetAddresses, getTransportMaxConnections, hasCurrentAddress, haveCapacity, haveCapacity, isCurrentIPv4, isIPv4Firewalled, isIPv6Firewalled, isPubliclyRoutable, isUnreachable, markReachable, markUnreachable, messageReceived, ngettext, removeAddress, removeAddress, renderStatusHTML, renderStatusHTML, replaceAddress, resizeSendPool, saveLocalAddress, send, sendPoolCapacityMax, sendPoolCapacityMin, setIP, setListener, setSendPoolCapacity, stopCleanupJob, updateAddress, wasUnreachableModifier and TypeMethodDescriptionprotected StringLooks the string up in the web messages bundle, returning s itself if there is no translation.protected StringTranslate and substitute one parameter.protected voidafterSend(OutNetMessage msg, boolean sendSuccessful) The transport is done sending this message.protected voidafterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue) The transport is done sending this message.protected voidafterSend(OutNetMessage msg, boolean sendSuccessful, long msToSend) The transport is done sending this message.booleanAre we allowed to connect to local addresses?static StringformatIPPort(byte[] ip, int port) Format an IP byte array (4 or 16 bytes) as host:port, for logging.The context this transport runs in.getCurrentAddress(boolean ipv6) What address are we currently listening to? Replaces getCurrentAddress()What addresses are we currently listening to? ReplacesTransportImpl.getCurrentAddress(boolean).protected byte[]IP of the current IPv4 address, from the cache maintained by the address mutators.static byte[]IP of the peer from the last connection (in or out, any transport).The IPv6 configuration for this transport.intPer-transport connection limit.Recent error messages from this transport.protected OutNetMessageNonblocking call to pull the next outbound message off the queue.static StringgetRouterIPPort(RouterInfo router) Best IP:port for a router, for ban logging: the direct connection IP from the transport layer, else a compatible address, else any announced address.protected Collection<InetAddress> Return and then clear all saved local addresses.The send pool instance, for stat access.static intCapacity of the NTCP send pool.getTargetAddresses(RouterInfo target) All available addresses we can use, shuffled and then sorted by cost/preference.static intgetTransportMaxConnections(RouterContext ctx, String style) The transport max connections for the given context and style.booleanDo we have any current address?booleanCan we initiate or accept a connection to another peer, saving some margin.booleanhaveCapacity(int pct) Whether we are under the given capacity level.booleanisCurrentIPv4(byte[] ip) Is the given IP the current external IPv4 address?booleanThis returns true if the force-firewalled setting is configured, false otherwise.booleanThis returns true if the force-firewalled setting is configured, false otherwise.protected booleanisPubliclyRoutable(byte[] addr) Allows IPv6 only if the transport is configured for it.booleanisUnreachable(Hash peer) Whether the given peer is unreachable.voidmarkReachable(Hash peer, boolean isInbound) Called when we establish a peer connection (outbound or inbound).voidmarkUnreachable(Hash peer) Called when we can't reach a peer.voidmessageReceived(I2NPMessage inMsg, RouterIdentity remoteIdent, Hash remoteIdentHash, long msToReceive, int bytesReceived) Message received from the I2NPMessageReader - send it to the listener.protected StringTranslate, choosing between the singular and the plural form.protected voidremoveAddress(boolean ipv6) Remove all existing addresses with the specified IP length (4 or 16).protected voidremoveAddress(RouterAddress address) Remove only this address.voidrenderStatusHTML(Writer out) Make this stuff pretty.voidrenderStatusHTML(Writer out, String urlBase, int sortFlags) Render the transport status HTML to the given writer.protected voidreplaceAddress(RouterAddress address) Replace any existing addresses for the current transport with the same IP length (4 or 16) with the given one.voidResize the NTCP send pool if needed.protected voidsaveLocalAddress(InetAddress address) Save a local address we were notified about before we started.voidsend(OutNetMessage msg) Asynchronously send the message as requested in the message and, if the send is successful, queue up any msg.getOnSendJob job, and register it with the OutboundMessageRegistry (if it has a reply selector).static intThe largest capacityTransportImpl.setSendPoolCapacity(int)accepts.static intThe smallest capacityTransportImpl.setSendPoolCapacity(int)accepts.voidIP of the peer from the last connection (in or out, any transport).voidsetListener(TransportEventListener listener) Who to notify on message availability.static voidsetSendPoolCapacity(int capacity) The NTCP send pool capacity (called by Tuner).voidCancel the unreachable-entry cleanup, if one is scheduled.Ask the transport to update its address based on current information and return it Transports should override.booleanwasUnreachable(Hash peer) Was the peer unreachable (outbound only) the last time we tried it? This is NOT reset if the peer contacts us.
Field Details
_log
Logger for NTCP connections._banLogger
Records why routers were banned._fastBid
Peer selection bid for fast peers._slowBid
Peer selection bid for slow peers._slowCostBid
Bid raising the cost of slow peers._nearCapacityBid
Save some conns for inbound._nearCapacityCostBid
Bid raising costs when near capacity._transientFail
Bid for peers with transient failures._conLock
Lock for the connection maps._conByIdent
Open connections, by peer hash._pumper
NIO event pumper for the connections._reader
The accept and connect thread._writer
The write thread, null until started._ssuPort
private int _ssuPortSSU port advertised in NTCP2 handshakes._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 _networkIDThe network id we communicate on._establishing
List of NTCPConnection of connections not yet established that we want to remove on establishment or close on timeout._replayFilter
"bloom filter"._haveIPv6Address
private boolean _haveIPv6AddressDo we have a public IPv6 address?_lastInboundIPv4
private long _lastInboundIPv4When the last inbound IPv4 connection arrived._lastInboundIPv6
private long _lastInboundIPv6When the last inbound IPv6 connection arrived.PROP_I2NP_NTCP_HOSTNAME
Config key for an explicitly configured hostname the NTCP transport advertises. The SSU equivalent isi2np.udp.host, not hostname. Value sourced fromTransport.PROP_I2NP_NTCP_HOSTNAME.- See Also:
PROP_I2NP_NTCP_PORT
Config key for the port the NTCP transport listens for inbound connections on. Value sourced fromTransport.PROP_I2NP_NTCP_PORT.- See Also:
PROP_I2NP_NTCP_AUTO_PORT
Config key controlling whether NTCP may auto-update its advertised port based on peer feedback. Value sourced fromTransport.PROP_I2NP_NTCP_AUTO_PORT.- See Also:
PROP_I2NP_NTCP_AUTO_IP
Config key controlling whether NTCP may auto-update its advertised IP based on peer feedback. Value sourced fromTransport.PROP_I2NP_NTCP_AUTO_IP.- See Also:
DEFAULT_COST
private static final int DEFAULT_COSTDefault peer selection cost for NTCP.- See Also:
NTCP2_OUTBOUND_COST
private static final int NTCP2_OUTBOUND_COSTPeer selection cost for outbound NTCP2.- See Also:
PROP_BIND_INTERFACE
This is rarely if ever used, default is to bind to wildcard address.- See Also:
_finisher
Closes connections after their writes finish._xdhFactory
Factory for the NTCP2 ephemeral key pairs._lastBadSkew
private long _lastBadSkewWhen a bad clock skew was last logged.RATES
private static final long[] RATESRate stat periods for the connection statistics.SUPPRESSION_PATTERNS
MIN_SIGTYPE_VERSION
RI sigtypes supported in 0.9.16.- See Also:
STYLE
Style identifier for the NTCP transport. Value sourced fromTransport.STYLE_NTCP.- See Also:
STYLE2
Style identifier for the NTCP2 protocol variant. Value sourced fromTransport.STYLE_NTCP2.- See Also:
NTCP2_INT_VERSION
NTCP2_VERSION
"2".NTCP2_VERSION_ALT
"2,".PQ_INT_VERSION
static final int PQ_INT_VERSION0 to disable, or 3/4/5 for enctypes 5/6/7.- See Also:
PQ_VERSION
PQ protocol version string.PROP_NTCP2_SP
Config key for the base-64 NTCP2 static private key. Value sourced fromTransport.PROP_NTCP2_SP.- See Also:
PROP_NTCP2_IV
Config key for the base-64 NTCP2 static IV. Value sourced fromTransport.PROP_NTCP2_IV.- See Also:
NTCP2_IV_LEN
private static final int NTCP2_IV_LENNTCP2 handshake IV length, in bytes.- See Also:
NTCP2_KEY_LEN
private static final int NTCP2_KEY_LENNTCP2 handshake key length, in bytes.- See Also:
MIN_DOWNTIME_TO_REKEY
private static final long MIN_DOWNTIME_TO_REKEYDowntime after which the NTCP2 static key is replaced.- See Also:
MIN_DOWNTIME_TO_REKEY_HIDDEN
private static final long MIN_DOWNTIME_TO_REKEY_HIDDENDowntime after which a hidden router rekeys.- See Also:
_ntcp2StaticPubkey
private final byte[] _ntcp2StaticPubkeyOur NTCP2 static public key._ntcp2StaticPrivkey
private final byte[] _ntcp2StaticPrivkeyOur NTCP2 static private key._ntcp2StaticIV
private final byte[] _ntcp2StaticIVOur NTCP2 static initialization vector._b64Ntcp2StaticPubkey
Static public key, base64, for the router info._b64Ntcp2StaticIV
Static IV, base64, for the router info.FAILSAFE_CLOSE_MEMORY_MS
private static final long FAILSAFE_CLOSE_MEMORY_MSHow 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_MEMORYUpper 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
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_TIMEOUTHow 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
Registers the NTCP rate statistics and loads or creates the NTCP2 static keys; nothing is started untilstartListening().- Parameters:
ctx- the router contextxdh- 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
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:
outboundMessageReadyin classTransportImpl
getConnectionOrCreateNew
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
Extract IP:port fromRouterInfofor 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
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
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:
afterSendin classTransportImpl- Parameters:
msg- message in questionsendSuccessful- true if the peer received itallowRequeue- true if we should try other transports if availablemsToSend- how long it took to transfer the data to the peer
bid
Bid on sending the message to the target.- Parameters:
toAddress- the target router's contact informationdataSize- 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
Classify the peer's network id relative to ours, for the ban-on-mismatch decision inbid(RouterInfo, int).- Parameters:
nid- the peer's announced network idourNetworkID- our own network id- Returns:
- OK if equal; NO_NETWORK if the peer sent the no-network sentinel (~0); WRONG_NETWORK otherwise
isSigTypeUsable
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
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 asMIN_SIGTYPE_VERSION. A DSA-signing router never has a version restriction.- Parameters:
weAreDSA- true if our own signature type is DSA_SHA1theirVersion- the peer's announced version- Returns:
- true if the version satisfies the signature-type floor
chooseBidTier
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 capacityhighCost- whether the peer's address cost exceedsDEFAULT_COST- Returns:
- the tier to quote
bidFor
Map a bid tier to the cached shared bid, so the compare-and-log hot path allocates nothing.- Parameters:
tier- the tier selected bychooseBidTier(boolean, boolean)- Returns:
- the cached bid for that tier
isExpectedRaceCondition
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
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 messageourHash- our own router hash- Returns:
- true if the message is a store of our own RouterInfo
isRouterInfoStoreFlood
Whether a DatabaseStoreMessage of our own RouterInfo carries a flood reply token. Only meaningful whenisOwnRouterInfoStore(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 RouterInfoshouldFlood- whether that store requests a floodversion- the connection's NTCP version- Returns:
- true if the message should be handed to the send pipeline
isAlreadyInProgress
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
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
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
Record that an idle session to this peer was just closed.- Parameters:
peer- the peer whose session was closednow- 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 nevernow- current time in mswindow- how long the close stays remembered; non-positive remembers nothing- Returns:
- true when the close is still recent enough to be reported
wasFailsafeClosed
Whether the peer's most recent connection was closed by the failsafe.- Specified by:
wasFailsafeClosedin interfaceTransport- Overrides:
wasFailsafeClosedin classTransportImpl- Parameters:
peer- the peer to ask aboutwithinMs- 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
Description copied from class:TransportImplWhether the given peer is established.- Specified by:
isEstablishedin interfaceTransport- Overrides:
isEstablishedin classTransportImpl- Parameters:
dest- hash of the peer to check- Returns:
- false; only a real transport reports established sessions
isConnecting
Whether a connection attempt is in progress to the given peer.- Specified by:
isConnectingin interfaceTransport- Overrides:
isConnectingin classTransportImpl- Parameters:
dest- hash of the peer to check- Returns:
- true if the connection is not closed and has not completed the handshake
isBacklogged
Whether the connection to the given peer is backlogged.- Specified by:
isBackloggedin interfaceTransport- Overrides:
isBackloggedin classTransportImpl- 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
Tell the transport that we may disconnect from this peer. This is advisory only.- Specified by:
mayDisconnectin interfaceTransport- Overrides:
mayDisconnectin classTransportImpl- Parameters:
peer- hash of the peer that may be disconnected
forceDisconnect
Tell the transport to disconnect from this peer.- Parameters:
peer- hash of the peer to forcefully disconnect from
forceDisconnect
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:
countPeersin interfaceTransport- Specified by:
countPeersin classTransportImpl- 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
For /peers UI only. Not a public API, not for external use.- Returns:
- not a copy, do not modify
getEstimatedRTT
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
WhengetEstimatedRTT(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_UNKNOWNif there is no session or it has not established
getEstablished
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:
countActivePeersin interfaceTransport- Specified by:
countActivePeersin classTransportImpl- 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
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:
getClockSkewsin interfaceTransport- Overrides:
getClockSkewsin classTransportImpl- 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
Selects the port to listen on. Private helper forstartListening().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 nullssuDisabled- 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 forrestoreSavedLocalAddresses(int, boolean).Internet-facing saved addresses are skipped when their family is firewalled; IPv6 additionally honors the explicit
i2p.ipv6.firewalledproperty when UDP is enabled.- Parameters:
ipv6- the address familyipv6Firewalled- IPv6 firewall detectedpropIPv6Firewalled- thei2p.ipv6.firewalledpropertyssuDisabled- whether UDP is disabledipv4Firewalled- 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 forstartListening().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 portssuDisabled- 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 forrestoreSavedLocalAddresses(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 addressesskipv6- IPv6 addresses were skippedskipv4- 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
Only called byexternalAddressReceived(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 addressipv6- 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
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
Resolves the configured bind target to an IP address. Private helper forbindAddress(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
Builds the RouterAddress to publish for a specific-interface bind. Private helper forbindAddress(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 addressbindTo- the configured host name or interface as publishedport- 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 forbindAddress(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 addressesaddr- the address about to be boundbindToAddr- the configured bind target, or null for wildcardport- 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 forbindAddress(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 portexternalPort- the configured UDP external portinternalPort- the configured UDP internal port- Returns:
- true when only the published port must change
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
getAltStyle
Alternate supported style.- Overrides:
getAltStylein classTransportImpl- Returns:
- "NTCP2" always
getPublishStyle
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
Add us to the establishment timeout process.- Parameters:
con- the connection being established, whichexpireTimedOut()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
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
This only creates an address if the hostname AND port are set inrouter.config, which should be rare. Otherwise, notifyReplaceAddress() below takes care of it. Note this is only called from startListening() viaconfigureLocalAddress(). 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
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
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
Single configured IP (as a String) or null if not configured or invalid. Resolves a hostname to an IP. Called at startup viacreateNTCPAddress()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 forgetConfiguredIP().Hostnames may resolve to several addresses; at most one IPv4 and one IPv6 address are published.
- Parameters:
v4- an IPv4 address is already selectedv6- an IPv6 address is already selectedaddrLen- address length in bytes, 4 for IPv4 or 16 for IPv6- Returns:
- true if that family is already represented
isBlankName
Whether the configured hostname is absent or unusable. Pure decision helper forgetConfiguredIP().Empty, whitespace-only, and the literal "null" (from a cleared config) values are all treated as unset.
- Parameters:
name- thei2p.ntcp.hostnamevalue, or null- Returns:
- true if no usable configured host exists
choosePrimaryIP
Picks the primary configured IP: the first IPv4, else the first IPv6. Pure decision helper forgetConfiguredIP().- 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
UDP changed addresses, tell NTCP and (possibly) restart.- Specified by:
externalAddressReceivedin interfaceTransport- Specified by:
externalAddressReceivedin classTransportImpl- Parameters:
source- defined in Transport.javaip- typ. IPv4 or IPv6 non-local; may be null to indicate IPv4 failure or port info onlyport- 0 for unknown or unchanged
externalAddressRemoved
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:
externalAddressRemovedin interfaceTransport- Overrides:
externalAddressRemovedin classTransportImpl- Parameters:
source- defined in Transport.javaipv6- true for IPv6, false for IPv4
addressChanged
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 onlyisIPv6- true for the IPv6 address, false for IPv4port- 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 RouterAddressDon'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:
forwardPortStatusin interfaceTransport- Overrides:
forwardPortStatusin classTransportImpl- Parameters:
ip- may be nullport- the internal portexternalPort- 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 mappingreason- 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:
getRequestedPortin interfaceTransport- Overrides:
getRequestedPortin classTransportImpl- 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 forgetReachabilityStatus().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 reportedfwV6- IPv6 firewall reportedalive- whether the transport is currently listeninghasV4- a published non-firewalled IPv4 address is presenthasV6- a published non-firewalled IPv6 address is presentshowFirewalled- 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 forgetReachabilityStatus().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 configurationv6Disabled- IPv6 address family disabled by configurationfwV4- IPv4 firewall reportedfwV6- IPv6 firewall reportedhasV4- a published non-firewalled IPv4 address is presenthasV6- a published non-firewalled IPv6 address is presenthaveIPv6Address- an IPv6 address was ever seen on a local interface or SSUshowFirewalled- 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 forgetReachabilityStatus().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 scanv6OK- whether v6 may be treated as reachable after the scanv4Disabled- IPv4 address family disabled by configurationshowFirewalled- SSU disabled and the router has been up more than 10 minuteshaveIPv6Address- an IPv6 address was ever seen on a local interface or SSU- Returns:
- the final status; never null
isFamilyDisabled
Whether an address family is disabled by the IPv6 configuration. Pure decision helper forgetReachabilityStatus().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 configurationisIPv6- the address family to query- Returns:
- true if that family is disabled
isBlank
Whether a configured value counts as absent.- Parameters:
s- the value- Returns:
- true if it is null or the empty string
wantsAutoHost
Whether the auto-host setting wants to publish an externally detected IP. Pure decision helper forexternalAddressReceived(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 normalizedi2p.ntcp.autoippreferencessuOK- whether a usable IP was supplied in the notification- Returns:
- true when the auto host should be applied
wantsConfiguredHost
Whether the configured hostname should be published in place of the current host. Pure decision helper forexternalAddressReceived(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 normalizedi2p.ntcp.autoippreferencename- the configured hostname, or nullohost- the currently published host, or null- Returns:
- true when the configured host should be applied
wantsRemoveAutoHost
Whether a previously auto-published address should be dropped. Pure decision helper forexternalAddressReceived(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 normalizedi2p.ntcp.autoippreferencessuOK- 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 forexternalAddressReceived(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 notificationprops- the newly built address optionsconfig- the router's IPv6 configuration- Returns:
- true when the full options should be applied
chooseAutomaticPort
Selects the port to publish for the NTCP address. Private helper forexternalAddressReceived(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- thei2p.ntcp.portvalue, or nullnotifiedPort- 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 forexternalAddressReceived(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 notifiedoldAddr- the current address for that family, may be null for IPv6ip- the notification IP, may be nullport- the notification port, may be 0- Returns:
- true if the NTCP address changed
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:
getReachabilityStatusin interfaceTransport- Specified by:
getReachabilityStatusin classTransportImpl- Returns:
- the reachability status
stopListening
public void stopListening()This doesn't (completely) block, caller should checkisAlive()before calling startListening() orrestartListening(RouterAddress, boolean).shouldSuppressException
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