java.lang.Object
net.i2p.router.transport.TransportImpl
net.i2p.router.transport.udp.UDPTransport
All Implemented Interfaces:
Transport

public class UDPTransportextends TransportImpl
SSU/SSU2 transport implementation with UDP endpoint management and packet dispatch.
  • Field Details

    • _log

      private final Log _log
      Logger for this class.
    • _banLogger

      private final BanLogger _banLogger
      Logger for peers banned by this transport.
    • _endpoints

      private final List<UDPEndpoint> _endpoints
      The sockets listened on, one per local address.
    • _addDropLock

      private final Object _addDropLock
      Lock serializing peer adds against drop-list changes.
    • _peersByIdent

      private final Map<Hash, PeerState> _peersByIdent
      Map of known peers, keyed by their identity hash. Used for fast lookup of peer state information during message handling and routing.
    • _peersByRemoteHost

      private final Map<RemoteHostId, PeerState> _peersByRemoteHost
      Map of known peers, keyed by their remote host and port. Used to identify peers based on source address in incoming packets.
    • _peersByConnID

      private final Map<Long, PeerState2> _peersByConnID
      Connected peers, by connection id.
    • _recentlyClosedConnIDs

      private final Map<Long, PeerStateDestroyed> _recentlyClosedConnIDs
      Recently closed peers, by connection id, for late packets.
    • _handler

      private PacketHandler _handler
      Thread reading packets off the sockets.
    • _establisher

      private EstablishmentManager _establisher
      Runs the SSU2 handshakes.
    • _fragments

      private final OutboundMessageFragments _fragments
      Queue of outbound message fragments.
    • _pusher

      private volatile PacketPusher _pusher
      Thread pushing queued packets to the sockets.
    • _inboundFragments

      private final InboundMessageFragments _inboundFragments
      Queue of inbound message fragments.
    • _testManager

      private final PeerTestManager _testManager
      Manages peer reachability testing to determine if we are firewalled or reachable.
    • _introManager

      private final IntroductionManager _introManager
      Manages introducers and introductions.
    • _expireEvent

      private final UDPTransport.ExpirePeerEvent _expireEvent
      Timer expiring idle peers.
    • _testEvent

      private final PeerTestEvent _testEvent
      Timer running reachability peer tests.
    • _reachabilityStatus

      private volatile CommSystemFacade.Status _reachabilityStatus
      Our measured reachability.
    • _reachabilityStatusPending

      private volatile CommSystemFacade.Status _reachabilityStatusPending
      A new reachability awaiting confirmation.
    • _reachabilityStatusUnchanged

      private volatile int _reachabilityStatusUnchanged
      Loops the reachability has been unchanged, logging only.
    • _v4IntroducersSelectedOn

      private long _v4IntroducersSelectedOn
      Time the IPv4 introducer set was last chosen.
    • _v6IntroducersSelectedOn

      private long _v6IntroducersSelectedOn
      Time the IPv6 introducer set was last chosen.
    • _lastInboundReceivedOn

      private volatile long _lastInboundReceivedOn
      Time the last inbound packet arrived.
    • _mtu

      private int _mtu
      The MTU in use, in bytes.
    • _mtu_ssu2

      private int _mtu_ssu2
      The SSU2 MTU in use, in bytes.
    • _mtu_ssu2_ipv6

      private int _mtu_ssu2_ipv6
      The SSU2 IPv6 MTU in use, in bytes.
    • _defaultMTU

      private final int _defaultMTU
      The MTU configured at startup, in bytes.
    • _mismatchLogged

      private boolean _mismatchLogged
      True once the MTU mismatch has been logged.
    • _networkID

      private final int _networkID
      Network id of the packets we accept.
    • _haveIPv6Address

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

      private volatile long _lastInboundIPv6
      Time the last inbound IPv6 packet arrived.
    • _min_peers

      private final int _min_peers
      Fewest peers to keep connected.
    • _min_v6_peers

      private final int _min_v6_peers
      Fewest IPv6-capable peers to keep connected.
    • _needsRebuild

      private volatile boolean _needsRebuild
      Flag indicating whether the router's external address needs to be rebuilt. This is typically set after significant network changes or reachability updates.
    • _rebuildLock

      private final Object _rebuildLock
      Lock serializing external-address rebuilds.
    • _introKey

      private SessionKey _introKey
      Introduction key.
    • _dropList

      private final Set<RemoteHostId> _dropList
      List of RemoteHostId for peers whose packets we want to drop outright This is only for old network IDs (pre-0.6.1.10), so it isn't really used now.
    • _expireTimeout

      private volatile long _expireTimeout
      Idle time at which a peer is expired, in ms.
    • _lastFromv4

      private Hash _lastFromv4
      Last report from a peer of our IP.
    • _lastFromv6

      private Hash _lastFromv6
      Hash of the last peer reached over IPv6.
    • _lastFromIPv4

      private byte[] _lastFromIPv4
      Source of the last inbound IPv4 packet.
    • _lastFromIPv6

      private byte[] _lastFromIPv6
      Source of the last inbound IPv6 packet.
    • _lastOurIPv4

      private byte[] _lastOurIPv4
      Local address the last outbound IPv4 packet left.
    • _lastOurIPv6

      private byte[] _lastOurIPv6
      Local address the last outbound IPv6 packet left.
    • _lastOurPortv4

      private int _lastOurPortv4
      Local port the last outbound IPv4 packet left.
    • _lastOurPortv6

      private int _lastOurPortv6
      Local port the last outbound IPv6 packet left.
    • _haveUPnP

      private boolean _haveUPnP
      True once a UPnP port mapping exists.
    • _currentOurV4Address

      private RouterAddress _currentOurV4Address
      We don't publish our IP/port if introduced, so we need to store it somewhere.
    • _currentOurV6Address

      private RouterAddress _currentOurV6Address
      Our current IPv6 endpoint as a router address.
    • _tuner

      private final Tuner _tuner
      Adaptive tuner.
    • STYLE2

      public static final String STYLE2
      Style identifier for the SSU2 protocol variant. Value sourced from Transport.STYLE_SSU2.
      See Also:
    • SSU2_INT_VERSION

      static final int SSU2_INT_VERSION
      SSU2 protocol version.
      See Also:
    • SSU2_VERSION

      static final String SSU2_VERSION
      "2".
    • SSU2_VERSION_ALT

      static final String SSU2_VERSION_ALT
      "2,".
    • _packetBuilder2

      private final PacketBuilder2 _packetBuilder2
      Builds the SSU2 packets we send.
    • _xdhFactory

      private final X25519KeyFactory _xdhFactory
      Shared X25519 factory for the handshakes.
    • _ssu2StaticPubKey

      private final byte[] _ssu2StaticPubKey
      Our SSU2 static public key.
    • _ssu2StaticPrivKey

      private final byte[] _ssu2StaticPrivKey
      Our SSU2 static private key.
    • _ssu2StaticIntroKey

      private final byte[] _ssu2StaticIntroKey
      Our SSU2 introducer-only static key.
    • _ssu2B64StaticPubKey

      private final String _ssu2B64StaticPubKey
      The static public key, base64, for the router info.
    • _ssu2B64StaticIntroKey

      private final String _ssu2B64StaticIntroKey
      The introducer key, base64, for the router info.
    • PROP_SSU2_SP

      public static final String PROP_SSU2_SP
      Config key for the base-64 SSU2 static private key. Value sourced from Transport.PROP_SSU2_SP.
      See Also:
    • PROP_SSU2_IKEY

      public static final String PROP_SSU2_IKEY
      Config key for the base-64 SSU2 static IV. Value sourced from Transport.PROP_SSU2_IKEY.
      See Also:
    • MIN_DOWNTIME_TO_REKEY_HIDDEN

      private static final long MIN_DOWNTIME_TO_REKEY_HIDDEN
      Hidden routers re-key after 24 hours of downtime.
      See Also:
    • DROPLIST_PERIOD

      private static final int DROPLIST_PERIOD
      Stale drop-list entries are removed every 10 minutes.
      See Also:
    • STYLE

      public static final String STYLE
      Style identifier for the SSU transport. Value sourced from Transport.STYLE_SSU.
      See Also:
    • PROP_INTERNAL_PORT

      public static final String PROP_INTERNAL_PORT
      Config key for the SSU internal listening port. Value sourced from Transport.PROP_INTERNAL_PORT.
      See Also:
    • PROP_EXTERNAL_HOST

      public static final String PROP_EXTERNAL_HOST
      Config key to force advertising a fixed external IP address. Value sourced from Transport.PROP_EXTERNAL_HOST.
      See Also:
    • PROP_EXTERNAL_PORT

      public static final String PROP_EXTERNAL_PORT
      Config key to force advertising a fixed external port. Value sourced from Transport.PROP_EXTERNAL_PORT.
      See Also:
    • PROP_PREFER_UDP

      public static final String PROP_PREFER_UDP
      Config key to prefer UDP transport.
      See Also:
    • DEFAULT_PREFER_UDP

      private static final String DEFAULT_PREFER_UDP
      Default for preferring UDP over NTCP.
      See Also:
    • PROP_FIXED_PORT

      public static final String PROP_FIXED_PORT
      Override whether we will change our advertised port no matter what our peers tell us. See getIsPortFixed(boolean) for default behaviour. Value sourced from Transport.PROP_FIXED_PORT.
      See Also:
    • PROP_SOURCES

      public static final String PROP_SOURCES
      Allowed sources of address updates. Value sourced from Transport.PROP_SOURCES.
      See Also:
    • DEFAULT_SOURCES

      public static final String DEFAULT_SOURCES
      Default address sources. Value sourced from Transport.DEFAULT_SOURCES.
    • PROP_IP

      public static final String PROP_IP
      Remember IP changes across restarts. Value sourced from Transport.PROP_IP.
      See Also:
    • PROP_IP_CHANGE

      public static final String PROP_IP_CHANGE
      Config key tracking when the last IP address change occurred.
      See Also:
    • PROP_LAPTOP_MODE

      public static final String PROP_LAPTOP_MODE
      Config key for laptop power-saving mode. Value sourced from Transport.PROP_LAPTOP_MODE.
      See Also:
    • PROP_IPV6

      public static final String PROP_IPV6
      Last IPv6 config. Value sourced from Transport.PROP_IPV6.
      See Also:
    • PROP_FORCE_INTRODUCERS

      public static final String PROP_FORCE_INTRODUCERS
      Do we require introducers, regardless of our status? Value sourced from Transport.PROP_FORCE_INTRODUCERS.
      See Also:
    • PROP_ALLOW_DIRECT

      public static final String PROP_ALLOW_DIRECT
      Do we allow direct SSU connections, sans introducers?
      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:
    • PROP_DEFAULT_MTU

      private static final String PROP_DEFAULT_MTU
      Override the "large" (max) MTU, default is PeerState.LARGE_MTU.
      See Also:
    • PROP_INTRO_KEY

      public static final String PROP_INTRO_KEY
      Config key for the SSU introducer key published in hidden-mode RouterInfos. Value sourced from Transport.PROP_INTRO_KEY.
      See Also:
    • CAP_TESTING

      private static final String CAP_TESTING
      Capacity letter for a peer under testing.
    • CAP_TESTING_INTRO

      private static final String CAP_TESTING_INTRO
      Capacity letters for a testing introducer.
    • CAP_TESTING_4

      private static final String CAP_TESTING_4
      Capacity letters for a testing IPv4 peer.
    • CAP_TESTING_6

      private static final String CAP_TESTING_6
      Capacity letters for a testing IPv6 peer.
    • PUBLIC_RELAY_COUNT

      public static final int PUBLIC_RELAY_COUNT
      How many relays offered to us will we use at a time?
      See Also:
    • MAX_CONSECUTIVE_FAILED

      private static final int MAX_CONSECUTIVE_FAILED
      Consecutive send failures before considering a peer for drop (requires inactivity too).
      See Also:
    • DEFAULT_COST

      public static final int DEFAULT_COST
      Default cost value for SSU peer selection.
      See Also:
    • SSU_OUTBOUND_COST

      private static final int SSU_OUTBOUND_COST
      Relative cost of sending via SSU, against NTCP's 10.
      See Also:
    • RATES

      static final long[] RATES
      Short-term rate limits for SSU.
    • MIN_PEERS

      private static final int MIN_PEERS
      Minimum active peers to maintain IP detection, etc.
      See Also:
    • MIN_PEERS_IF_HAVE_V6

      private static final int MIN_PEERS_IF_HAVE_V6
      Peer target once we are reachable over IPv6.
      See Also:
    • MIN_INTRODUCER_POOL

      private static final int MIN_INTRODUCER_POOL
      Minimum peers volunteering to be introducers if we need that.
      See Also:
    • INTRODUCER_EXPIRATION_MARGIN

      static final long INTRODUCER_EXPIRATION_MARGIN
      Default introducer expiration in ms.
      See Also:
    • MIN_DOWNTIME_TO_REKEY

      private static final long MIN_DOWNTIME_TO_REKEY
      We re-key after 7 days of downtime.
      See Also:
    • BID_VALUES

      private static final int[] BID_VALUES
      Bid values for each peer class, worst last.
    • FAST_PREFERRED_BID

      private static final int FAST_PREFERRED_BID
      Bid index for a fast peer we prefer.
      See Also:
    • SLOW_PREFERRED_BID

      private static final int SLOW_PREFERRED_BID
      Bid index for a slow peer we prefer.
      See Also:
    • FAST_BID

      private static final int FAST_BID
      Bid index for a fast peer.
      See Also:
    • SLOW_BID

      private static final int SLOW_BID
      Bid index for a slow peer.
      See Also:
    • SLOWEST_BID

      private static final int SLOWEST_BID
      Bid index for the slowest tier.
      See Also:
    • SLOWEST_COST_BID

      private static final int SLOWEST_COST_BID
      Bid index for the slowest tier by cost.
      See Also:
    • NEAR_CAPACITY_BID

      private static final int NEAR_CAPACITY_BID
      Bid index for a peer near its capacity.
      See Also:
    • NEAR_CAPACITY_COST_BID

      private static final int NEAR_CAPACITY_COST_BID
      Bid index for a peer near capacity by cost.
      See Also:
    • TRANSIENT_FAIL_BID

      private static final int TRANSIENT_FAIL_BID
      Bid index for a peer with a recent failure.
      See Also:
    • _cachedBid

      private final TransportBid[] _cachedBid
      Precomputed bids, indexed by the constants above.
    • MIN_SIGTYPE_VERSION

      private static final String MIN_SIGTYPE_VERSION
      RI sigtypes supported in 0.9.16, but due to a bug in InboundEstablishState fixed in 0.9.17, we cannot connect out to routers before that version.
      See Also:
    • MIN_PEER_TEST_VERSION

      private static final String MIN_PEER_TEST_VERSION
      Oldest version whose SSU2 peer tests are trusted, SSU2 having become stable then.
      See Also:
    • STATUS_IPV4_UNK

      private static final Set<CommSystemFacade.Status> STATUS_IPV4_UNK
      Statuses in which our IPv4 reachability is unknown.
    • STATUS_IPV6_UNK

      private static final Set<CommSystemFacade.Status> STATUS_IPV6_UNK
      Statuses in which our IPv6 reachability is unknown.
    • STATUS_IPV4_FW

      private static final Set<CommSystemFacade.Status> STATUS_IPV4_FW
      Statuses in which our IPv4 is firewalled.
    • STATUS_IPV6_FW

      private static final Set<CommSystemFacade.Status> STATUS_IPV6_FW
      Statuses in which our IPv6 is firewalled.
    • STATUS_FW

      private static final Set<CommSystemFacade.Status> STATUS_FW
      Statuses in which either family is firewalled.
    • STATUS_IPV6_FW_2

      private static final Set<CommSystemFacade.Status> STATUS_IPV6_FW_2
      Statuses treating IPv6 as firewalled, ambiguous ones included.
    • STATUS_IPV6_OK

      private static final Set<CommSystemFacade.Status> STATUS_IPV6_OK
      Statuses in which our IPv6 is reachable.
    • STATUS_OK

      private static final Set<CommSystemFacade.Status> STATUS_OK
      Statuses in which our IPv4 is reachable.
    • STATUS_IPV4_SYMNAT

      private static final Set<CommSystemFacade.Status> STATUS_IPV4_SYMNAT
      Statuses in which IPv4 sits behind a symmetric NAT.
    • STATUS_IPV4_NO_TEST

      private static final Set<CommSystemFacade.Status> STATUS_IPV4_NO_TEST
      Statuses in which we cannot be a v4 Charlie.
    • STATUS_IPV6_NO_TEST

      private static final Set<CommSystemFacade.Status> STATUS_IPV6_NO_TEST
      Statuses in which we cannot be a v6 Charlie.
    • ALLOW_IP_CHANGE_INTERVAL

      private static final int ALLOW_IP_CHANGE_INTERVAL
      If we have received an inbound connection in the last 2 minutes, don't allow our IP to change.
      See Also:
    • gotIPv4Addr

      private boolean gotIPv4Addr
      True once the IPv4 address has been reported, to stop repeats.
    • gotIPv6Addr

      private boolean gotIPv6Addr
      True once the IPv6 address has been reported, to stop repeats.
    • EXPIRE_TIMEOUT

      public static final int EXPIRE_TIMEOUT
      Default introducer expiration in ms.
      See Also:
    • MAX_IDLE_TIME

      private static final int MAX_IDLE_TIME
      Idle time past which a peer is disconnected.
      See Also:
    • MIN_EXPIRE_TIMEOUT

      public static final int MIN_EXPIRE_TIMEOUT
      Minimum introducer expiration in ms.
      See Also:
    • PING_FIREWALL_TIME

      private static final long PING_FIREWALL_TIME
      Time past which a ping keeps the firewall open, 30 seconds; firewalls have been seen to change ports after 40.
      See Also:
    • PING_FIREWALL_CUTOFF

      private static final long PING_FIREWALL_CUTOFF
      Half of that, the time by which the ping must be sent.
      See Also:
    • SLICES

      private static final int SLICES
      Peer slices pinged one per loop.
      See Also:
    • SHORT_LOOP_TIME

      private static final long SHORT_LOOP_TIME
      Loop interval while pings are due.
      See Also:
    • LONG_LOOP_TIME

      private static final long LONG_LOOP_TIME
      Loop interval while no pings are due.
      See Also:
    • EXPIRE_INCREMENT

      private static final long EXPIRE_INCREMENT
      Amount the expire timeout grows per adjustment.
      See Also:
    • EXPIRE_DECREMENT

      private static final long EXPIRE_DECREMENT
      Amount the expire timeout shrinks per adjustment.
      See Also:
    • MAY_DISCON_TIMEOUT

      private static final long MAY_DISCON_TIMEOUT
      Idle time past which a peer may be disconnected.
      See Also:
    • RI_STORE_INTERVAL

      private static final long RI_STORE_INTERVAL
      The router info is re-stored every 29 minutes.
      See Also:
    • PROP_REACHABILITY_STATUS_OVERRIDE

      private static final String PROP_REACHABILITY_STATUS_OVERRIDE
      Property overriding the measured reachability.
      See Also:
  • Constructor Details

    • UDPTransport

      public UDPTransport(RouterContext ctx, X25519KeyFactory xdh)
      Create the UDP transport for the given router context and SSU2 XDH factory.
      Parameters:
      ctx - the router context
      xdh - non-null
  • Method Details

    • getTuner

      public Tuner getTuner()
      The transport tuner.
      Returns:
      adaptive tuner for transport parameters
    • getMaxObEstablishTime

      public static long getMaxObEstablishTime()
      The outbound establish timeout in ms.
      Returns:
      the timeout, in ms
    • setMaxObEstablishTime

      public static void setMaxObEstablishTime(long ms)
      Outbound establish timeout.
      Parameters:
      ms - the outbound establish timeout, bounded 1500-5000ms
    • getMaxIbEstablishTime

      public static long getMaxIbEstablishTime()
      The inbound establish timeout in ms.
      Returns:
      the timeout, in ms
    • setMaxIbEstablishTime

      public static void setMaxIbEstablishTime(long ms)
      Inbound establish timeout.
      Parameters:
      ms - the inbound establish timeout, bounded 1500-5000ms
    • getDataMessageTimeout

      public static long getDataMessageTimeout()
      The data message timeout in ms.
      Returns:
      the timeout, in ms
    • setDataMessageTimeout

      public static void setDataMessageTimeout(long ms)
      Data message timeout.
      Parameters:
      ms - the data message timeout, bounded 15000-120000ms
    • getOMF

      The OutboundMessageFragments instance.
      Returns:
      the instance of OutboundMessageFragments
    • setupPort

      private void setupPort()
      Pick a port if not previously configured, so that TransportManager may call getRequestedPort() before we've started to get a best-guess of what our port is going to be, and pass that to NTCP.
    • startup

      private void startup()
      Starts up the SSU transport listener, configuring and binding UDP endpoints, initializing components, and setting reachability status. This method is synchronized to prevent concurrent startup attempts.
    • shutdownComponents

      private void shutdownComponents()
      Shutdown components and clear endpoints safely.
    • resolveBindAddresses

      private Set<InetAddress> resolveBindAddresses()
      Resolves bind addresses from configuration properties, expanding hostnames if necessary.
      Returns:
      set of InetAddress to bind to, empty if none specified
    • expandExternalHostToBind

      private String expandExternalHostToBind()
      Expands the PROP_EXTERNAL_HOST configuration into a comma-separated string of IP addresses that are local and allowed.
      Returns:
      expanded bind string or null if no resolved addresses
    • determinePort

      private int determinePort(Set<InetAddress> bindToAddrs)
      Determines the port to bind to based on internal, bind, or external port properties.
      Parameters:
      bindToAddrs - set of addresses to bind; used for logging
      Returns:
      the port to bind to
    • setupEndpoints

      private void setupEndpoints(Set<InetAddress> bindToAddrs, int port)
      Create UDP endpoints for the given bind addresses and port.
      Parameters:
      bindToAddrs - addresses to bind, empty means wildcard
      port - port to bind endpoints on
    • initializeManagers

      private void initializeManagers()
      Initializes establishment and handler managers if missing.
    • startEndpointsAndGetPort

      private int startEndpointsAndGetPort()
      Starts all endpoints, returns the listen port of the first IPv4 endpoint started or -1 if none.
      Returns:
      new port that endpoints are listening on or -1
    • updatePortsInConfig

      private void updatePortsInConfig(int port, int newPort)
      Updates internal and external port config after successful endpoint startup.
      Parameters:
      port - previously requested port
      newPort - actual port endpoints listen on
    • startupComponentServices

      private void startupComponentServices()
      Starts fragment and packet components.
    • configureExternalAddressesAndStatus

      private void configureExternalAddressesAndStatus(int newPort, Set<InetAddress> bindToAddrs)
      Configures external addresses and sets reachability status based on current state.
      Parameters:
      newPort - port that endpoints are listening on
      bindToAddrs - bind addresses provided
    • adjustReachabilityForFirewalled

      private void adjustReachabilityForFirewalled()
      Adjusts reachability status when IPv4 is firewalled.
    • shutdown

      public void shutdown()
      Stop all UDP endpoints, handlers, and background threads.
    • fail

      public void fail(UDPEndpoint endpoint)
      The endpoint has failed. Remove it.
      Parameters:
      endpoint - the failed endpoint; dropping it rebuilds the external address advertisement
    • isAlive

      private boolean isAlive()
      Check if inbound fragment handler is alive.
      Returns:
      true if the inbound fragment handler job is still running
    • getIntroKey

      SessionKey getIntroKey()
      Introduction key that people should use to contact us, or null if SSU1 disabled.
      Returns:
      the SSU1 introduction key, or null if SSU1 is disabled
    • getSSU2StaticIntroKey

      byte[] getSSU2StaticIntroKey()
      The static Intro key.
      Returns:
      null if not configured for SSU2
    • getSSU2StaticPubKey

      byte[] getSSU2StaticPubKey()
      The static pub key.
      Returns:
      null if not configured for SSU2
    • getSSU2StaticPrivKey

      byte[] getSSU2StaticPrivKey()
      The static priv key.
      Returns:
      null if not configured for SSU2
    • getSSUVersion

      int getSSUVersion(RouterAddress addr)
      Valid SSU version of Bob's SSU address for our outbound connections as Alice.
      Parameters:
      addr - the remote RouterAddress, whose transport style selects the version
      Returns:
      the valid version 1 or 2, or 0 if unusable
    • addSSU2Options

      private void addSSU2Options(Properties props)
      Add the required options to the properties for a SSU2 address. Host/port must already be set in props if they are going to be. Must only be called if SSU2 is enabled.
      Parameters:
      props - the address options to add the SSU2 intro key, static key and version entries to
    • getExternalPort

      int getExternalPort(boolean ipv6)
      Published or requested port.
      Parameters:
      ipv6 - true for the IPv6 socket
      Returns:
      the published port, else the requested port
    • getExternalIP

      byte[] getExternalIP()
      Published IP, IPv4 only.

      Reads the cached IPv4 address rather than scanning _currentAddresses, so this does not take the address-list monitor. For the per-packet comparison, prefer TransportImpl.isCurrentIPv4(byte[]) over copying the array.

      Returns:
      a copy of the IP, or null if we have no IPv4 address
    • hasIPv6Address

      boolean hasIPv6Address()
      For PeerTestManager.
      Returns:
      true if we have a published IPv6 address
    • isTooClose

      boolean isTooClose(byte[] ip)
      Is this IP too close to ours to trust it for things like relaying?
      Parameters:
      ip - IPv4 or IPv6
      Returns:
      true if it shares our subnet prefix (2 bytes IPv4, 4 bytes IPv6)
    • getListenPort

      private int getListenPort(boolean ipv6)
      The current port of the first matching endpoint. To be enhanced to handle multiple endpoints of the same type.
      Parameters:
      ipv6 - true to match an IPv6 endpoint, false for IPv4
      Returns:
      port or -1
    • getRequestedPort

      public int getRequestedPort()
      The current or configured internal IPv4 port. UDPEndpoint should always be instantiated (and a random port picked if not configured) before this is called, so the returned value should be > 0 unless the endpoint failed to bind.
      Specified by:
      getRequestedPort in interface Transport
      Overrides:
      getRequestedPort in class TransportImpl
      Returns:
      the requested port
    • getRequestedPort

      private int getRequestedPort(boolean ipv6)
      The current or configured internal port. UDPEndpoint should always be instantiated (and a random port picked if not configured) before this is called, so the returned value should be > 0 unless the endpoint failed to bind.
      Parameters:
      ipv6 - true to return the IPv6 port, false for IPv4
      Returns:
      the requested port
    • setMTU

      private int setMTU(InetAddress addr)
      MTU for the socket interface at addr.
      Parameters:
      addr - null ok
      Returns:
      the MTU in bytes
    • getMTU

      public int getMTU(boolean ipv6)
      The MTU for the socket interface. To be used as the "large" MTU.
      Parameters:
      ipv6 - true for IPv6, false for IPv4
      Returns:
      limited to range PeerState.MIN_MTU to PeerState.LARGE_MTU.
    • getSSU2MTU

      public int getSSU2MTU(boolean ipv6)
      The SSU2 MTU for the socket interface. To be used as the "large" MTU.
      Parameters:
      ipv6 - true for IPv6, false for IPv4
      Returns:
      limited to range PeerState2.MIN_MTU to PeerState2.LARGE_MTU, or 0 if unavailable
    • inboundConnectionReceived

      void inboundConnectionReceived(boolean isIPv6)
      Inbound connection received, which locks our IP against changing for ALLOW_IP_CHANGE_INTERVAL.
      Parameters:
      isIPv6 - true for the IPv6 socket
    • externalAddressReceived

      public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port)
      From config, UPnP, local i/f, ... Not for info received from peers - see externalAddressReceived(Hash, ip, port).
      Specified by:
      externalAddressReceived in interface Transport
      Specified by:
      externalAddressReceived in class TransportImpl
      Parameters:
      source - as defined in Transport.SOURCE_xxx
      ip - publicly routable IPv4 or IPv6, null ok
      port - 0 if unknown
    • forwardPortStatus

      public void forwardPortStatus(byte[] ip, int port, int externalPort, boolean success, String reason)
      Callback from UPnP. If we we have an IP address and UPnP claims success, believe it. If this is wrong, the peer test will figure it out and change the status. Don't do anything if UPnP claims failure.
      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
    • externalAddressReceived

      void externalAddressReceived(Hash from, byte[] hisIP, byte[] ourIP, int ourPort)
      Someone we tried to contact gave us what they think our IP address is. Right now, we just blindly trust them, changing our IP and port on a whim. this is not good ;)

      Slight enhancement - require two different peers in a row to agree

      Todo: - Much better tracking of troublemakers - Disable if we have good local address or UPnP - This gets harder if and when we publish multiple addresses, or IPv6.

      Parameters:
      from - Hash of inbound destination
      hisIP - the IP of the peer telling us
      ourIP - publicly routable IPv4 or IPv6 only, non-null
      ourPort - >= 1024
    • changeAddress

      private boolean changeAddress(byte[] ourIP, int ourPort)
      Updates the external IP address and/or port based on feedback from a peer. This is used when a peer reports our external address, or when we detect a change.
      Parameters:
      ourIP - the new IP address (IPv4 or IPv6)
      ourPort - the new port number, or 0 to keep the current port
      Returns:
      true if the address was successfully updated
    • shouldOverrideReportedPort

      static boolean shouldOverrideReportedPort(boolean fixedPort, int externalListenPort, int reportedPort)
      Whether the reported (peer-observed) port should be discarded in favour of the currently configured external listen port.

      The port is pinned when the operator fixed it (fixedPort with a known listen port) or when the peer reported no port at all.

      Parameters:
      fixedPort - true if the transport runs with a fixed port
      externalListenPort - current external listen port
      reportedPort - port reported by the peer (may be <= 0)
      Returns:
      true if reportedPort must be discarded
    • isAddressChange

      static boolean isAddressChange(byte[] externalListenHost, int externalListenPort, byte[] ourIP, int ourPort)
      Whether the peer-reported address differs from the current external address and is worth acting on. A reported port of 0 means "keep the current port", so a zero port is never an address change.
      Parameters:
      externalListenHost - current external host, may be null
      externalListenPort - current external port
      ourIP - reported host (IPv4 or IPv6)
      ourPort - reported port, 0 = keep current
      Returns:
      true if the address pair should be updated
    • isIPChange

      static boolean isIPChange(byte[] externalListenHost, byte[] ourIP)
      Whether the reported host differs from the current external host.
      Parameters:
      externalListenHost - current external host, may be null
      ourIP - host address the peer reported for us
      Returns:
      true if the host differs
    • shouldSaveExternalPort

      static boolean shouldSaveExternalPort(int externalListenPort, int ourPort, int configuredExternalPort)
      Whether a peer-reported external port change should be persisted to the configuration. The configured external port (explicit operator setting) takes precedence over any report and is never overwritten.
      Parameters:
      externalListenPort - current external listen port
      ourPort - port the peer reported for us
      configuredExternalPort - externally configured port, 0 if none
      Returns:
      true if the reported port must be persisted
    • shouldRestartForLaptopMode

      static boolean shouldRestartForLaptopMode(String oldIP, boolean hasWrapper, boolean laptopMode, long lastChanged, long now, long uptime)
      Whether the configured IP change rate and startup window require a hard restart with a fresh identity (laptop mode).
      Parameters:
      oldIP - the previously configured IP, null if never set
      hasWrapper - true if running under the service wrapper
      laptopMode - true if the i2np.laptopMode property is set
      lastChanged - ms of the previous IP change, 0 if unknown
      now - current time ms
      uptime - router uptime ms
      Returns:
      true if the router should restart with a new identity
    • parseLastAddressChange

      static long parseLastAddressChange(String value)
      Parse the stored last-IP-change timestamp, tolerating garbage.
      Parameters:
      value - the property value, may be null or non-numeric
      Returns:
      the timestamp in ms, or 0 when unset or unparsable
    • isLocalAddress

      static boolean isLocalAddress(byte[] ip)
      Whether the given IP is one of this host's local addresses.
      Parameters:
      ip - absolute IPv4 or IPv6 address bytes, may be null
      Returns:
      true if it matches a local interface address
    • eq

      private static final boolean eq(byte[] laddr, int lport, byte[] raddr, int rport)
      Compare two address and port pairs for equality; either address may be null.
      Parameters:
      laddr - local address, may be null
      lport - local port, 0-65535
      raddr - remote address, may be null
      rport - remote port, 0-65535
      Returns:
      true if the ports are equal and the addresses are equal, with null addresses equal only when both are null
    • isValid

      public final 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 if valid
    • getIsPortFixed

      private boolean getIsPortFixed(boolean isIPv6)
      Was true before 0.9.2 Now false if we need introducers (as perhaps that's why we need them, our firewall is changing our port), unless overridden by the property. We must have an accurate external port when firewalled, or else our signature of the SessionCreated packet will be invalid.

      As of 0.9.58, returns false if status is UNKNOWN.

      Parameters:
      isIPv6 - true to evaluate the IPv6 reachability status, false for IPv4
      Returns:
      true if our port is fixed and stable, false if we are firewalled or the status for that family is unknown
    • getPeerState

      PeerState getPeerState(RemoteHostId hostInfo)
      Retrieves the current connection state for a peer identified by their remote host and port.
      Parameters:
      hostInfo - the remote host and port of the peer
      Returns:
      the peer state, or null if not found
    • getPeerState

      PeerState getPeerState(Hash remotePeer)
      The peer state for the peer with the given ident, or null if no state exists.
      Parameters:
      remotePeer - the router identity hash
      Returns:
      the peer state, or null if none exists
    • getEstimatedRTT

      public int getEstimatedRTT(Hash peer)
      Measured round trip time to a peer over SSU.

      PeerState seeds its RTT at 0 and only assigns a real value from an observed round trip, so 0 here means the session has not measured yet. Callers treat that as unknown, not as an impossibly good peer.

      Parameters:
      peer - the peer to measure
      Returns:
      the measured RTT in ms, or 0 if there is no session or none measured
    • getEstimatedRTTTime

      public long getEstimatedRTTTime(Hash peer)
      When getEstimatedRTT(Hash) was measured, on the router clock.

      Always Transport.RTT_TIME_CURRENT: SSU refreshes a session's RTT on every acknowledgement, so whatever this returns was measured by traffic the session is carrying now. There is no reading here that can go stale while a session is alive, which is the property NTCP2 lacks.

      Parameters:
      peer - the peer to report on
      Returns:
      Transport.RTT_TIME_CURRENT, always
    • getPeerState

      PeerState2 getPeerState(long rcvConnID)
      Peer state by SSU2 connection ID.
      Parameters:
      rcvConnID - the receive connection ID of the session
      Returns:
      the peer state, or null if none exists
    • getRecentlyClosed

      PeerStateDestroyed getRecentlyClosed(long rcvConnID)
      Was the state for this SSU2 receive connection ID recently closed? Lock-free single ConcurrentHashMap read. Hits the per-packet receive path on a connection-ID miss (attacker-triggerable), so the shared add/drop lock must not be taken here.
      Parameters:
      rcvConnID - the receive connection ID of the closed session
      Returns:
      the destroyed state, or null if the ID is not in the recent list
    • addRecentlyClosed

      void addRecentlyClosed(PeerStateDestroyed peer)
      Start listening for packets on a destroyed connection.
      Parameters:
      peer - the destroyed session to keep reachable
    • removeRecentlyClosed

      void removeRecentlyClosed(PeerStateDestroyed peer)
      Stop listening for packets on a destroyed connection.
      Parameters:
      peer - the destroyed session to stop tracking
    • getPeers

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

      public List<Hash> getEstablished()
      Identities of all currently established peers.
      Returns:
      list of established peer hashes, may be unmodifiable
    • changePeerPort

      void changePeerPort(PeerState peer, int newPort)
      Remove and add to peersByRemoteHost map.
      Parameters:
      peer - the peer whose port changed
      newPort - the peer's new port
    • changePeerAddress

      void changePeerAddress(PeerState2 peer, RemoteHostId newAddress)
      Remove and add to peersByRemoteHost map.
      Parameters:
      peer - the peer whose address changed
      newAddress - the peer's new IP and port
    • getEstablisher

      EstablishmentManager getEstablisher()
      For IntroductionManager.
      Returns:
      may be null if not started
    • addRemotePeerState

      boolean addRemotePeerState(PeerState peer)
      Adds a new peer state or replaces an existing one if the peer identity or address changes. This method ensures thread-safe updates to internal peer tracking maps.
      Parameters:
      peer - the peer state to add or update
      Returns:
      true if the peer was successfully added or updated
    • locked_addRemotePeerState

      private boolean locked_addRemotePeerState(PeerState peer)
      Adds a connected peer under the add/drop lock.
      Parameters:
      peer - the peer to add
      Returns:
      true if it was added
    • alreadyConnectedLine

      static String alreadyConnectedLine(String kind, String oldPeer, String peer)
      The entry for a peer replaced while establishing a second session with the same router. The tag says which map held the previous peer - PBID for the remote router hash, PBRH for the remote host id. Each peer goes on its own continuation line so the entry stays readable.
      Parameters:
      kind - PBID or PBRH
      oldPeer - the peer being replaced, as its own short string
      peer - the peer taking its place, as its own short string
      Returns:
      the log entry, never null
    • messageReceived

      public void messageReceived(I2NPMessage inMsg, RouterIdentity remoteIdent, Hash remoteIdentHash, long msToReceive, int bytesReceived)
      Handle incoming message from transport layer.
      Overrides:
      messageReceived in class TransportImpl
      Parameters:
      inMsg - non-null
      remoteIdent - may be null
      remoteIdentHash - may be null, calculated from remoteIdent if null
      msToReceive - milliseconds the read took, for the debug log
      bytesReceived - how many bytes of the message arrived, for the debug log
    • isInDropList

      boolean isInDropList(RemoteHostId peer)
      Is in drop list.
      Parameters:
      peer - the peer to look for
      Returns:
      true if a delayed drop is still pending for the peer
    • dropPeer

      void dropPeer(Hash peer, boolean shouldBanlist, String why)
      This does not send a session destroy, caller must do that if desired.
      Parameters:
      peer - the router identity hash of the peer to drop
      shouldBanlist - doesn't really, only sets unreachable
      why - cause, for the debug log only, may be null
    • dropPeer

      void dropPeer(PeerState peer, boolean shouldBanlist, String why)
      This does not send a session destroy, caller must do that if desired.
      Parameters:
      peer - the session to drop, recursing if another session shares its ident or host
      shouldBanlist - doesn't really, only sets unreachable
      why - cause, for the debug log only, may be null
    • locked_dropPeer

      private void locked_dropPeer(PeerState peer, boolean shouldBanlist, String why)
      This does not send a session destroy, caller must do that if desired.
      Parameters:
      peer - the peer state to remove from all peer maps and drop
      shouldBanlist - doesn't really, only sets unreachable
      why - unused, the reason for the drop given at the call site
    • send

      void send(UDPPacket packet)
      This sends it directly out, bypassing OutboundMessageFragments. The only queueing is for the bandwidth limiter. BLOCKING if OB queue is full.
      Parameters:
      packet - already built, addressed, and encrypted
    • sendDestroy

      void sendDestroy(PeerState peer, int reasonCode)
      Send a session destroy message, bypassing OMF and PacketPusher. BLOCKING if OB queue is full.
      Parameters:
      peer - the session to tear down, SSU1 peers are ignored
      reasonCode - SSU2 only, ignored for SSU1
    • destroyAll

      private void destroyAll()
      Send a session destroy message to everybody. BLOCKING for at least 1 sec per 1K peers, more if BW is very low or if OB queue is full.
    • bid

      public TransportBid bid(RouterInfo toAddress, int dataSize)
      Bid on a message to the given router.
      Parameters:
      toAddress - target router info
      dataSize - message size in bytes
      Returns:
      the bid, or null if we can't (or shouldn't) send via UDP
    • isTooLarge

      static boolean isTooLarge(int dataSize)
      Not-a-note: the message is too large for SSU to carry at all.
      Parameters:
      dataSize - message size in bytes
      Returns:
      true if the message exceeds the maximum SSU message size
    • isDifferentNetwork

      static boolean isDifferentNetwork(int nid, int ourNetworkId)
      Whether the target router belongs to a different network than ours.
      Parameters:
      nid - the target router's network id
      ourNetworkId - this router's network id
      Returns:
      true when the network ids differ
    • rejectCppBug

      static boolean rejectCppBug(int cost, String version)
      Reject known c++ SSU disconnect bugs (through 0.9.52), which drop inbound sessions shortly after establishment.
      Parameters:
      cost - the target's address cost (10 = SSU1, 9 = SSU2)
      version - the target's router software version
      Returns:
      true when the target may exhibit the disconnect bug
    • sigTypeUnsupported

      static boolean sigTypeUnsupported(SigType type)
      Whether the target identity uses a signature type we cannot verify.
      Parameters:
      type - the target identity's signature type
      Returns:
      true when the type is missing or unsupported by this build
    • needsMinimumSigTypeVersion

      static boolean needsMinimumSigTypeVersion(SigType ourSigType, String theirVersion)
      Whether we need a minimum software version on the target because we are not DSA-signed: non-DSA routers cannot be reached by pre-0.9.17 builds that do not understand their signature types.
      Parameters:
      ourSigType - this router's signature type
      theirVersion - the target's router software version
      Returns:
      true when our non-DSA signature requires a 0.9.17+ target
    • rejectFloodfill

      private boolean rejectFloodfill(Hash to, RouterInfo toAddress)
      Reject a floodfill router that we have no history with, or that has rejected tunnel creation far more often than it has agreed.

      Be less aggressive about rejecting floodfills when firewalled, as we need more peers. Temporary - let NTCP2 deal with them (prop. 165).

      Parameters:
      to - target identity hash
      toAddress - target router info
      Returns:
      true to skip bidding on this router
    • isFirewalled

      private boolean isFirewalled()
      Are we behind a firewall, with no way to accept incoming UDP?
      Returns:
      true if any firewall state is active
    • selectBid

      private TransportBid selectBid(RouterAddress addr, int cost, boolean weAreFirewalled)
      Select the bid tier for a message to an unestablished peer.

      Try to maintain at least 5 peers (30 for v6) so we can determine our IP address and we have a selection to run peer tests with. If we are firewalled, and we don't have enough peers that volunteered to also introduce us, also bid aggressively so we are preferred over NTCP - otherwise we only talk UDP to those that are firewalled, and we will never get any introducers.

      Parameters:
      addr - validated target SSU address
      cost - the target's address cost
      weAreFirewalled - status computed by isFirewalled()
      Returns:
      the bid to send, higher values being preferred by the peer
    • getTargetAddress

      RouterAddress getTargetAddress(RouterInfo target)
      First available address of the target that we can use.
      Parameters:
      target - the remote RouterInfo whose addresses are scanned in order
      Returns:
      address or null
    • preferUDP

      private boolean preferUDP()
      Whether the config prefers UDP over NTCP.
      Returns:
      true to prefer UDP
    • alwaysPreferUDP

      private boolean alwaysPreferUDP()
      Whether UDP is preferred in every situation.
      Returns:
      true to always prefer UDP
    • getStyle

      public String getStyle()
      Transport style string "SSU".
      Returns:
      unique transport style identifier
    • getAltStyle

      public String getAltStyle()
      An alternate supported style, or null.
      Overrides:
      getAltStyle in class TransportImpl
      Returns:
      the alt style, always "SSU2"
    • getPublishStyle

      private String getPublishStyle()
      The publish style.
      Returns:
      "SSU" unless SSU1 disabled, then "SSU2"
    • isIdleEstablished

      static boolean isIdleEstablished(long now, long lastSend, long lastRecv, long maxIdleTime)
      Is an established peer idle past the threshold in both directions, and so due for teardown and re-establishment rather than continued selection?

      Pure decision, extracted from send(OutNetMessage) so the truth table can be pinned in a test without a router.

      This predicate is deliberately time-only, where the code it replaces also required getConsecutiveFailedSends() > 2. That counter is incremented from exactly one place, failed(OutboundMessageState, boolean), and only once a message has exhausted its retransmits or expired. A half-open session therefore never accumulates it — the peer still ACKs enough traffic to keep messages alive, or we stop sending and never reach failed() at all. Either way the session stays in _peersByIdent indefinitely and keeps answering isEstablished(Hash) true, so peer selection keeps choosing peers we have not heard from in days. Of the hop records on expired builds, 85% had this shape and only 15% had been heard from within 3 seconds.

      The slack is intentional. MAX_IDLE_TIME is EXPIRE_TIMEOUT, 20 minutes, which already governed this drop and which the consecutive-failure path relaxes toward. A peer silent in both directions for twenty minutes is not carrying traffic, and a false positive costs one re-establishment, not a lost session.

      Parameters:
      now - current time in ms
      lastSend - time of the last fully sent message, or 0 if never
      lastRecv - time of the last receive, or 0 if never
      maxIdleTime - idle threshold in ms
      Returns:
      true if the session is idle in both directions past the threshold
    • isIdleEstablished

      boolean isIdleEstablished(PeerState peer, long now, long maxIdleTime)
      Is the peer idle in both directions past the threshold, disregarding send failures.
      Parameters:
      peer - the peer state, may be null
      now - current time in ms
      maxIdleTime - idle threshold in ms
      Returns:
      true if the peer should be dropped and re-established
    • send

      public void send(OutNetMessage msg)
      Description copied from class: TransportImpl
      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). If the send fails, queue up any msg.getOnFailedSendJob

      Only used by NTCP. SSU overrides.

      Non-blocking: uses priority eviction when the pool is full. Higher-priority messages (client data) evict lower-priority (transit).

      Specified by:
      send in interface Transport
      Overrides:
      send in class TransportImpl
      Parameters:
      msg - the message to send, containing destination, payload, and callbacks
    • sendIfEstablished

      void sendIfEstablished(OutNetMessage msg)
      Send only if established, otherwise fail immediately. Never queue with the establisher.
      Parameters:
      msg - the message to send, which must have an established peer
    • send

      void send(I2NPMessage msg, PeerState peer)
      "injected" message from the EstablishmentManager. If you have multiple messages, use the list variant, so the messages may be bundled efficiently.
      Parameters:
      msg - the message to send, which must have an established peer
      peer - the message MUST be going to this peer
    • send

      void send(I2NPMessage msg, List<OutNetMessage> msgs, PeerState peer)
      "injected" message from the EstablishmentManager, plus pending messages to send, so the messages may be bundled efficiently. Called at end of outbound establishment.
      Parameters:
      msg - may be null if nothing to inject
      msgs - pending messages to bundle with msg, non-null, may be empty
      peer - all messages MUST be going to this peer
    • send

      void send(List<I2NPMessage> msgs, PeerState peer)
      "injected" messages from the EstablishmentManager. Called at end of inbound establishment.
      Parameters:
      msgs - the messages to bundle, non-null, may be empty
      peer - all messages MUST be going to this peer
    • outboundMessageReady

      protected void outboundMessageReady()
      Not used for UDP, which does its own queueing.
      Specified by:
      outboundMessageReady in class TransportImpl
    • startListening

      public void startListening()
      Start the transport listener.
    • stopListening

      public void stopListening()
      Stop listening.
    • explicitAddressSpecified

      private boolean explicitAddressSpecified()
      Whether the config pins our external address.
      Returns:
      true if a host or port is configured
    • updateAddress

      public List<RouterAddress> updateAddress()
      Rebuild to get updated cost and introducers. IPv4 only, unless configured as IPv6 only. Do not tell the router (he is the one calling this).
      Specified by:
      updateAddress in interface Transport
      Overrides:
      updateAddress in class TransportImpl
      Returns:
      the current router addresses
    • rebuildExternalAddress

      private RouterAddress rebuildExternalAddress(boolean ipv6)
      Rebuilds the external router address for either IPv4 or IPv6. This is called when the router needs to update its published address, typically after a reachability change or IP update.
      Parameters:
      ipv6 - true to rebuild the IPv6 address, false for IPv4
      Returns:
      the new router address if changed, otherwise null
    • rebuildExternalAddress

      private RouterAddress rebuildExternalAddress(boolean allowRebuildRouterInfo, boolean ipv6)
      Update our IPv4 address and optionally tell the router to rebuild and republish the router info.

      If PROP_EXTERNAL_HOST is set, use those addresses (comma/space separated). If a hostname is configured in that property, use it. As of 0.9.32, a hostname is resolved here into one or more addresses and the IPs are published, to implement proposal 141.

      A max of one v4 and one v6 address will be set. Significant changes both here and in NTCP would be required to publish multiple v4 or v6 addresses.

      Parameters:
      allowRebuildRouterInfo - whether to tell the router
      ipv6 - true to rebuild the IPv6 address, false for IPv4
      Returns:
      the new address if changed, else null
    • rebuildExternalAddress

      private RouterAddress rebuildExternalAddress(byte[] ip, int port, boolean allowRebuildRouterInfo)
      Update our IPv4 or IPv6 address and optionally tell the router to rebuild and republish the router info.
      Parameters:
      ip - new ip valid IPv4 or IPv6 or null
      port - new valid port or -1
      allowRebuildRouterInfo - whether to tell the router
      Returns:
      the new address if changed, else null
    • rebuildExternalAddress

      private RouterAddress rebuildExternalAddress(String host, int port, boolean allowRebuildRouterInfo)
      Rebuilds the router address for our external endpoint.
      Parameters:
      host - the external host
      port - the external port
      allowRebuildRouterInfo - true to publish the change
      Returns:
      the new address, null if unchanged
    • locked_rebuildExternalAddress

      private RouterAddress locked_rebuildExternalAddress(String host, int port, boolean allowRebuildRouterInfo)
      Rebuild the external address from the given validated host; caller must hold the rebuild lock.
      Parameters:
      host - new validated IPv4 or IPv6 or DNS hostname or null or ":" to force IPv6 introducer rebuild
      port - the port to publish, 0 or less if unknown
      allowRebuildRouterInfo - whether to rebuild and republish the router info
      Returns:
      the new RouterAddress, or null if it equals the current one
    • rebuildHiddenExternalAddress

      private RouterAddress rebuildHiddenExternalAddress(String host, int port, boolean allowRebuildRouterInfo, boolean isIPv6)
      Rebuild the external address of a hidden router: nothing is published, so only an address with 4/6 caps is made.
      Parameters:
      host - new validated host or null
      port - new validated port or 0/-1
      allowRebuildRouterInfo - whether to tell the router
      isIPv6 - true for an IPv6 address
      Returns:
      the new address if changed, else null
    • selectIntroducers

      private boolean selectIntroducers(boolean isIPv6, RouterAddress current, OrderedProperties options)
      Pick inbound introducers for the address options. The intro manager now sorts introducers, so deepEquals() will not fail even with the same introducers (was only a problem when we had very very few peers to pick from).
      Parameters:
      isIPv6 - true for an IPv6 address
      current - current address, used as the introducer pool source
      options - address options to fill in
      Returns:
      true if introducers were selected
    • selectCapacity

      private String selectCapacity(boolean isIPv6, boolean directIncluded, boolean introducersRequired)
      Select the address capacity string for the given state.
      Parameters:
      isIPv6 - true for an IPv6 address
      directIncluded - whether a direct address is in the options
      introducersRequired - whether this address must have introducers
      Returns:
      the capacity string
    • rebuildPublishedAddress

      private RouterAddress rebuildPublishedAddress(String host, int port, boolean allowRebuildRouterInfo, boolean isIPv6, boolean directIncluded, boolean introducersIncluded, int mtu, OrderedProperties options)
      Publish the fully populated address (direct and/or introducers).
      Parameters:
      host - new validated host or null
      port - new validated port or 0/-1
      allowRebuildRouterInfo - whether to tell the router
      isIPv6 - true for an IPv6 address
      directIncluded - whether a direct address is in the options
      introducersIncluded - whether introducers are in the options
      mtu - the MTU for this address
      options - address options (host, port, caps, mtu, introducers)
      Returns:
      the new address if changed, else null
    • rebuildEmptyAddress

      private RouterAddress rebuildEmptyAddress(String host, int port, boolean allowRebuildRouterInfo, boolean isIPv6, boolean introducersRequired, int mtu)
      No direct address and no introducers available; publish an empty "4" or "6" address so peers know the address exists, and retry later.
      Parameters:
      host - new validated host or null
      port - new validated port or 0/-1
      allowRebuildRouterInfo - whether to tell the router
      isIPv6 - true for an IPv6 address
      introducersRequired - whether this address must have introducers
      mtu - the MTU for this address
      Returns:
      the new address if changed, else null
    • replaceCurrentExternalAddress

      private void replaceCurrentExternalAddress(RouterAddress ra, boolean isIPv6)
      Simple storage of IP and port, since we don't put them in the real, published RouterAddress anymore if we are firewalled.

      Side effect: Sets our MTU

      Caller must sync on _rebuildLock.

      Parameters:
      ra - the new external address to store, with host and port options
      isIPv6 - true to store it as the current IPv6 address, false for IPv4
    • rebuildRouterInfo

      private void rebuildRouterInfo()
      Avoid deadlocks part 999.
    • getCurrentExternalAddress

      public RouterAddress getCurrentExternalAddress(boolean isIPv6)
      Simple fetch of stored IP and port, since we don't put them in the real, published RouterAddress anymore if we are firewalled.
      Parameters:
      isIPv6 - true for IPv6, false for IPv4
      Returns:
      the external address or null
    • replaceAddress

      protected void replaceAddress(RouterAddress address)
      Replace then tell NTCP that we changed.
      Overrides:
      replaceAddress in class TransportImpl
      Parameters:
      address - the new address or null to remove all
    • removeAddress

      protected void removeAddress(RouterAddress address)
      Remove then tell NTCP that we changed.
      Overrides:
      removeAddress in class TransportImpl
      Parameters:
      address - the address to remove
    • removeAddress

      protected void removeAddress(boolean ipv6)
      Remove then tell NTCP that we changed.
      Overrides:
      removeAddress in class TransportImpl
      Parameters:
      ipv6 - true to remove the IPv6 address, false for IPv4
    • introducersRequired

      private boolean introducersRequired(boolean ipv6)
      Do we require introducers?
      Parameters:
      ipv6 - true to test the IPv6 side of our reachability, false for IPv4
      Returns:
      true if we cannot accept unsolicited UDP packets on that side, or direct connections are disallowed, so outbound introducers are needed
    • introducersMaybeRequired

      boolean introducersMaybeRequired(boolean ipv6)
      MIGHT we require introducers? This is like introducersRequired, but if we aren't sure, this returns true. Used only by EstablishmentManager.
      Parameters:
      ipv6 - true to test the IPv6 side of our reachability
      Returns:
      true if introducers may be required
    • canIntroduce

      boolean canIntroduce(boolean ipv6)
      For EstablishmentManager.
      Parameters:
      ipv6 - true to test the IPv6 side of our reachability
      Returns:
      true if we are eligible to offer relay introductions
    • allowDirectUDP

      private boolean allowDirectUDP()
      Whether direct UDP connections to other routers are allowed; defaults to true.
      Returns:
      false only if i2np.udp.allowDirect is explicitly set to false
    • getPacketHandlerStatus

      String getPacketHandlerStatus()
      Packet handler status.
      Returns:
      the handler's status string, or empty if not yet started
    • getPacketHandler

      PacketHandler getPacketHandler()
      The packet handler.
      Returns:
      the handler, or null if not yet started
    • failed

      public void failed(OutboundMessageState msg)
      Handle a failed outbound message.
      Parameters:
      msg - the outbound message
    • failed

      void failed(OutboundMessageState msg, boolean allowPeerFailure)
      Handle a failed outbound message, blaming the peer only after MAX_CONSECUTIVE_FAILED failures with no recent activity.
      Parameters:
      msg - the outbound message
      allowPeerFailure - false to count the failure without blaming the peer
    • failed

      public void failed(OutNetMessage msg, String reason)
      Handle a failed outbound network message.
      Parameters:
      msg - the outbound network message
      reason - the failure reason
    • succeeded

      public void succeeded(OutboundMessageState msg)
      Handle a successful outbound message.
      Parameters:
      msg - the outbound message
    • countPeers

      public int countPeers()
      Count peers.
      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.
      Returns:
      8-byte array with peer counts: version 1: [ipv4_in, ipv4_out, ipv6_in, ipv6_out, 0, 0, 0, 0] version 2: [ipv4_in, ipv4_out, ipv6_in, ipv6_out, 0, 0, 0, 0]
    • countActivePeers

      public int countActivePeers()
      Active peers.
      Specified by:
      countActivePeers in interface Transport
      Specified by:
      countActivePeers in class TransportImpl
      Returns:
      the number of such peers
    • countActiveSendPeers

      public int countActiveSendPeers()
      Active send peers.
      Returns:
      active send peer count
    • 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
    • isBacklogged

      public boolean isBacklogged(Hash dest)
      Whether the peer for the given destination is backlogged.
      Specified by:
      isBacklogged in interface Transport
      Overrides:
      isBacklogged in class TransportImpl
      Parameters:
      dest - hash of the peer to check
      Returns:
      true if messages are queued for the peer, awaiting responses
    • isConnecting

      public boolean isConnecting(Hash dest)
      Description copied from class: TransportImpl
      Check if a connection attempt is in progress for the given peer. Default returns false. NTCP2 and SSU2 transports that have an async handshake phase should override to report in-progress connections.
      Specified by:
      isConnecting in interface Transport
      Overrides:
      isConnecting in class TransportImpl
      Parameters:
      dest - hash of the peer to check
      Returns:
      true if a connection attempt is in progress but not yet established
    • 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 - the peer to consider
    • forceDisconnect

      public void forceDisconnect(Hash peer)
      Force disconnect a peer.
      Parameters:
      peer - hash of the peer to forcefully disconnect from
    • forceDisconnect

      public void forceDisconnect(Hash peer, String reason)
      Force disconnect with reason.
      Parameters:
      peer - hash of the peer to forcefully disconnect from
      reason - reason for disconnection (for logging)
    • allowConnection

      public boolean allowConnection()
      Whether a new connection is allowed.
      Returns:
      true if connection is allowed
    • getClockSkews

      public List<Long> getClockSkews()
      Return our 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
    • getXDHFactory

      X25519KeyFactory getXDHFactory()
      XDH key factory for SSU2, or null if not configured for SSU2.
      Returns:
      null if not configured for SSU2
    • getBuilder2

      PacketBuilder2 getBuilder2()
      Packet builder for SSU2, or null if not configured for SSU2.
      Returns:
      null if not configured for SSU2
    • getIntroManager

      IntroductionManager getIntroManager()
      The introduction manager.
      Returns:
      the manager, or null if not started
    • getPeerTestManager

      PeerTestManager getPeerTestManager()
      The peer test manager.
      Returns:
      the manager, or null if not started
    • getInboundFragments

      InboundMessageFragments getInboundFragments()
      The inbound fragment reassembler.
      Returns:
      the reassembler, or null if not started
    • isFirewalled

      static boolean isFirewalled(CommSystemFacade.Status status)
      Whether a comm-system reachability status means we are firewalled for at least one address family.
      Parameters:
      status - the current comm-system status
      Returns:
      true for any of the six firewalled statuses
    • adjustExpireTimeout

      static long adjustExpireTimeout(long expireTimeout, boolean haveCap, boolean lastLoopShort)
      Adjust the idle-timeout towards the target as a function of spare connection capacity, ramping slowly when the loop is running short.
      Parameters:
      expireTimeout - current idle-expire timeout
      haveCap - true when connection capacity remains
      lastLoopShort - true if the previous loop was a short (fast) pass
      Returns:
      the adjusted timeout, clamped to [MIN_EXPIRE_TIMEOUT, EXPIRE_TIMEOUT]
    • idleHardCutoff

      static long idleHardCutoff(long now, boolean overCapacity)
      Hard-cap idle cutoff: peers idle past this are dropped when the connection maximum is exceeded, otherwise the cutoff is unbounded.
      Parameters:
      now - current time ms
      overCapacity - true when peer count exceeds the connection max
      Returns:
      the idle cutoff (30s before now), or Long.MIN_VALUE when not over capacity
    • inactivityCutoff

      static long inactivityCutoff(long now, long timeout, boolean weAreFirewalled, long firewalledMin)
      Idle cutoff for a peer tier. Firewalled routers keep peers much longer by flooring the cutoff at firewalledMin.
      Parameters:
      now - current time ms
      timeout - idle timeout for this tier, in ms
      weAreFirewalled - true for lenient firewalled behavior
      firewalledMin - minimum timeout when firewalled
      Returns:
      the inactivity cutoff; peers idle before it are expirable
    • reliedOnRecently

      static boolean reliedOnRecently(long weRelayToThemAs, long introducerTime, long pingCutoff)
      Whether we have recently relied on this peer as a relay or introducer, in which case it gets the long inactivity tier.
      Parameters:
      weRelayToThemAs - nonzero when we offer this peer as introducer
      introducerTime - ms since this peer was used as introducer
      pingCutoff - the 2-hour reference cutoff
      Returns:
      true if the peer was relied on recently
    • mayDisconnectLowTraffic

      static boolean mayDisconnectLowTraffic(boolean haveCap, boolean inbound, boolean mayDisconnect, int messagesReceived, int messagesSent)
      Whether an inbound (or capacity-starved) peer with may-disconnect set and near-zero traffic is a stale candidate for the aggressive 15-second cutoff.
      Parameters:
      haveCap - true when connection capacity remains
      inbound - true if the peer connected inbound
      mayDisconnect - peer's may-disconnect flag
      messagesReceived - messages received from the peer
      messagesSent - messages sent to the peer
      Returns:
      true when the peer qualifies for the stale-cutoff tier
    • pickInactivityCutoff

      static long pickInactivityCutoff(boolean reliedOnRecently, boolean mayDisconnectLowTraffic, long longInactivityCutoff, long mayDisconCutoff, long shortInactivityCutoff)
      Select the inactivity tier for a peer.
      Parameters:
      reliedOnRecently - peer acted as relay/introducer recently
      mayDisconnectLowTraffic - peer is stale and may disconnect
      longInactivityCutoff - lenient tier cutoff
      mayDisconCutoff - aggressive stale-peer cutoff
      shortInactivityCutoff - default tier cutoff
      Returns:
      the cutoff to compare both last-send and last-receive against
    • idleSince

      static boolean idleSince(long lastReceive, long lastSend, long cutoff)
      Whether a peer has been idle (no receive and no send) since the given cutoff.
      Parameters:
      lastReceive - last receive time ms
      lastSend - last send time ms
      cutoff - inactivity cutoff ms
      Returns:
      true if both activity stamps precede the cutoff
    • firewallPingSliceMatched

      static boolean firewallPingSliceMatched(int runCount, int peerHash)
      Firewall-keepalive slice gate: roughly one peer in SLICES pings per pass, so pings are spread out over the short loop.
      Parameters:
      runCount - current expire-loop run counter
      peerHash - the peer's hashCode, to place it in a slice
      Returns:
      true if this peer is scheduled for a keepalive ping
    • shouldFirewallPing

      static boolean shouldFirewallPing(boolean shouldPingFirewall, boolean sliceMatched, long lastSendOrPing, long lastReceive, long pingFirewallCutoff)
      Whether a firewall keepalive ping should be sent to this peer: ping mode on, peer in this pass's slice, and no send-or-ping or receive in the PING_FIREWALL_CUTOFF window.
      Parameters:
      shouldPingFirewall - ping mode is active
      sliceMatched - peer selected for this pass
      lastSendOrPing - last send-or-ping time ms
      lastReceive - last receive time ms
      pingFirewallCutoff - ping-due cutoff ms
      Returns:
      true when the keepalive ping should be sent
    • shouldStoreRI

      static boolean shouldStoreRI(long uptime, long loopTime)
      Whether the peer session key is old enough to warrant re-publishing our RouterInfo. Publishes on the first loop at/after each RI_STORE_INTERVAL boundary.
      Parameters:
      uptime - ms since the peer session key was established
      loopTime - ms of the current loop interval
      Returns:
      true when a periodic RouterInfo store is due
    • setReachabilityStatus

      private void setReachabilityStatus(CommSystemFacade.Status status)
      IPv4 only.
      Parameters:
      status - the new IPv4 reachability status
    • setReachabilityStatus

      void setReachabilityStatus(CommSystemFacade.Status status, boolean isIPv6)
      Update the reachability status of this router, optionally for an IPv6 change.
      Parameters:
      status - the merged IPv4/IPv6 reachability status
      isIPv6 - Is the change an IPv6 change?
    • locked_setReachabilityStatus

      private void locked_setReachabilityStatus(CommSystemFacade.Status newStatus, boolean isIPv6)
      1) Merge IPv4 or IPv6 newStatus into the current IPv4+IPv6 status 2a) If current status changed, call rebuildExternalAddress(boolean) 2b) Otherwise, If we need to retest, call PeerTestEvent.forceRunSoon(boolean).
      Parameters:
      newStatus - the new IPv4 or IPv6 status to merge into the combined status
      isIPv6 - Is the change an IPv6 change?
    • shouldRerunStatusTest

      static boolean shouldRerunStatusTest(CommSystemFacade.Status old, boolean isIPv6)
      Whether an UNKNOWN reachability update should reschedule a peer test.

      UNKNOWN is only a click-flag, never stored; any UNKNOWN result against UNKNOWN always repeats the test. States with an unknown IPv6 component also repeat on an IPv6 test (independent of the IPv4 component), while the remaining statuses are unchanged and just bump the counter.

      Parameters:
      old - the current reachability status
      isIPv6 - true if the update concerns IPv6
      Returns:
      true if a peer test should be run immediately
    • applyIPv6Only

      static CommSystemFacade.Status applyIPv6Only(CommSystemFacade.Status status, boolean isIPv6Only)
      Collapse a merged status when the transport runs in IPv6-only mode.

      The IPv4 component cannot be tested, so any merged state with an IPv4 UNKNOWN component becomes the matching DISABLED state.

      Parameters:
      status - the merged IPv4+IPv6 status
      isIPv6Only - true if the transport is configured IPv6-only
      Returns:
      the status to store
    • applyNoIPv6Address

      static CommSystemFacade.Status applyNoIPv6Address(CommSystemFacade.Status status, boolean hasIPv6Address)
      Collapse a merged status when the router has no IPv6 address to publish.

      The IPv6 component of the status is dropped and only the IPv4 result matters; in particular a firewalled-or-ok v6 component cannot turn the IPv4 result into a paradox (firewalled->OK->firewalled+OK thrash), so the *_IPV6_OK states map down to the plain IPv4 equivalents.

      Parameters:
      status - the merged IPv4+IPv6 status
      hasIPv6Address - true if the router has an IPv6 address to publish
      Returns:
      the status to store
    • requiresConfirmation

      static boolean requiresConfirmation(CommSystemFacade.Status old, CommSystemFacade.Status status, boolean isIPv6)
      Whether the status transition must be confirmed by a second test before it is committed, to prevent thrashing between OK and firewalled.

      Any jump into, out of, or between the firewalled group is staged as pending confirmation; for IPv4, leaving the IPv4-unknown group is also staged (an IPv6-unrelated UNKNOWN result must not flip IPv4 flapping).

      Parameters:
      old - the current reachability status
      status - the (possibly adjusted) merged new status
      isIPv6 - true if the update concerns IPv6
      Returns:
      true if the new status must be confirmed by a second test
    • decideIPv6Rebuild

      static UDPTransport.IPv6Rebuild decideIPv6Rebuild(CommSystemFacade.Status old, CommSystemFacade.Status status, boolean explicitAddressSpecified)
      The IPv6 external-address rebuild to perform after a committed status change.
      Parameters:
      old - the previous reachability status
      status - the new committed reachability status
      explicitAddressSpecified - true if the operator configured an explicit IPv6 address
      Returns:
      the rebuild action to take
    • getReachabilityStatus

      public CommSystemFacade.Status getReachabilityStatus()
      Current reachability status, possibly overridden by configuration.
      Specified by:
      getReachabilityStatus in interface Transport
      Specified by:
      getReachabilityStatus in class TransportImpl
      Returns:
      the reachability status
    • isSymNatted

      boolean isSymNatted()
      Is IPv4 Symmetric NATted?
      Returns:
      true if the IPv4 status is one of the SYMNAT states
    • canTestAsCharlie

      boolean canTestAsCharlie(boolean ipv6)
      Can we be a Charlie right now?
      Parameters:
      ipv6 - true to test the IPv6 side of our reachability
      Returns:
      true if we can participate
    • pickTestPeer

      PeerState pickTestPeer(PeerTestState.Role peerRole, int version, boolean isIPv6, RemoteHostId dontInclude)
      Pick a Bob (if we are Alice) or a Charlie (if we are Bob).

      For Bob (as called from PeerTestEvent below), returns an established IPv4/v6 peer. While the protocol allows Alice to select an unestablished Bob, we don't support that.

      For Charlie (as called from PeerTestManager), returns an established IPv4 or IPv6 peer. (doesn't matter how Bob and Charlie communicate)

      Any returned peer must advertise an IPv4 address to prove it is IPv4-capable. Ditto for v6.

      Parameters:
      peerRole - The role of the peer we are looking for, BOB or CHARLIE only (NOT our role)
      version - 1 or 2 for role CHARLIE; ignored for role BOB
      isIPv6 - true to get a v6-capable peer back
      dontInclude - may be null
      Returns:
      peer or null
    • getPacketHandlerMaxThreads

      public static int getPacketHandlerMaxThreads()
      The max packet handler threads.
      Returns:
      the current ceiling on SSU2 packet handler threads
    • setPacketHandlerMaxThreads

      public static void setPacketHandlerMaxThreads(int handlers)
      Max packet handler threads.
      Parameters:
      handlers - max packet handler threads
    • adjustPacketHandlerThreads

      public void adjustPacketHandlerThreads()
      Dynamically adjusts PacketHandler thread count to match the target.
    • getMessageReceiverThreads

      public static int getMessageReceiverThreads()
      The current target MessageReceiver thread count.
      Returns:
      message receiver thread count
    • setMessageReceiverThreads

      public static void setMessageReceiverThreads(int threads)
      Target MessageReceiver thread count.
      Parameters:
      threads - message receiver thread count
    • adjustMessageReceiverThreads

      public void adjustMessageReceiverThreads()
      Dynamically adjusts MessageReceiver thread count to match the target.
    • getReceiverQueueSize

      public int getReceiverQueueSize()
      The current queue depth of the MessageReceiver.
      Returns:
      receiver queue size
    • getReceiverQueueCapacity

      public int getReceiverQueueCapacity()
      Returns the maximum capacity of the MessageReceiver queue.
      Returns:
      receiver queue capacity
    • getTotalOutboundQueueDepth

      public int getTotalOutboundQueueDepth()
      Total outbound messages queued across all UDP peers. Unsynchronized — uses ConcurrentHashMap.values which is weakly consistent. For Tuner cross-references on outbound pressure.
      Returns:
      total outbound queue depth
    • getPacketHandlerUtilization

      public double getPacketHandlerUtilization()
      Packet handler pool utilization as a ratio (0.0-1.0). Returns NaN if not started.
      Returns:
      packet handler utilization
    • getMessageReceiverUtilization

      public double getMessageReceiverUtilization()
      Message receiver pool utilization as a ratio (0.0-1.0). Returns NaN if not started.
      Returns:
      message receiver utilization