java.lang.Object
net.i2p.router.transport.TransportImpl
All Implemented Interfaces:
Transport
Direct Known Subclasses:
NTCPTransport, UDPTransport

public abstract class TransportImplextends Object implements Transport
Defines a way to send a message to another peer and start listening for messages.
  • Field Details

    • AFTER_SEND_SUCCESSFUL

      private static final String AFTER_SEND_SUCCESSFUL
      Timestamp labels for afterSend(OutNetMessage, boolean, boolean, long), constants so neither costs an allocation.
      See Also:
    • AFTER_SEND_FAILED

      private static final String AFTER_SEND_FAILED
      Name of the failed send callback.
      See Also:
    • _log

      private final Log _log
      Logger for the transport.
    • _listener

      private TransportEventListener _listener
      Listener notified of the transport events.
    • _currentAddresses

      private final List<RouterAddress> _currentAddresses
      The addresses currently published.
    • _currentIPv4

      private volatile byte[] _currentIPv4
      IP of the current IPv4 address, or null. Maintained by every mutation of _currentAddresses so the per-packet "is this us?" check need not take that list's monitor. Cloned on read and on write, so no array escapes.
    • _sendPool

      private volatile PrioritySendPool _sendPool
      Pool of the messages waiting to be sent, used by NTCP only, see send() below.
    • _context

      protected final RouterContext _context
      The router context, which every subclass reads its configuration from.
    • _unreachableEntries

      private final Map<Hash,Long> _unreachableEntries
      Map from routerIdentHash to timestamp (Long) when the peer was last unreachable.
    • _wasUnreachableEntries

      private final Map<Hash,Long> _wasUnreachableEntries
      Peers recently marked unreachable, by hash.
    • _lastReachablePeer

      private volatile Hash _lastReachablePeer
      The last peer checked for reachability, a one-entry cache.
    • _localAddresses

      private final Set<InetAddress> _localAddresses
      Our local addresses, for loopback checks.
    • _sendPoolEvictedLast

      private volatile int _sendPoolEvictedLast
      Messages evicted from the pool last pass.
    • _sendPoolDroppedLast

      private volatile int _sendPoolDroppedLast
      Messages dropped from the pool last pass.
    • _lastSendPoolStatTime

      private long _lastSendPoolStatTime
      When the pool statistics were last logged.
    • _IPMap

      private static final Map<Hash,byte[]> _IPMap
      Global router ident -> IP map.
    • UNREACHABLE_PERIOD

      private final long UNREACHABLE_PERIOD
      Time a peer counts as unreachable.
    • WAS_UNREACHABLE_PERIOD

      private final long WAS_UNREACHABLE_PERIOD
      Time the unreachable mark is remembered.
    • _cleanupJob

      private volatile TransportImpl.CleanupUnreachable _cleanupJob
      Timer clearing the unreachable entries.
    • CAP_IPV4

      public static final String CAP_IPV4
      Advertised reachability value for a working IPv4 address. @since 0.9.50.
      See Also:
    • CAP_IPV6

      public static final String CAP_IPV6
      Advertised reachability value for a working IPv6 address. @since 0.9.50.
      See Also:
    • CAP_IPV4_IPV6

      public static final String CAP_IPV4_IPV6
      Advertised reachability value for both address families. @since 0.9.50.
      See Also:
    • PROP_IPV6_FIREWALLED

      protected static final String PROP_IPV6_FIREWALLED
      Property recording the result of the last IPv6 firewall test.
      See Also:
    • PROP_BOOST_CONNECTION_LIMITS

      protected static final String PROP_BOOST_CONNECTION_LIMITS
      Property allowing a transport to lift its connection limit.
      See Also:
    • RATES

      private static final long[] RATES
      Rate stat periods for the transport statistics.
    • MAX_CONNECTION_FACTOR

      private static final int MAX_CONNECTION_FACTOR
      50/100/150/250/450/550/700 for BW Tiers K/L/M/N/O/P/X.
      See Also:
    • SEND_POOL_CAPACITY

      private static volatile int SEND_POOL_CAPACITY
      Messages the send pool holds, sized in the constructor.
    • DEFAULT_CAPACITY_PCT

      private static final int DEFAULT_CAPACITY_PCT
      Default share of our capacity we offer.
      See Also:
    • ADJUST_COST

      protected static final boolean ADJUST_COST
      Do we increase the advertised cost when approaching conn limits?
      See Also:
    • CONGESTION_COST_ADJUSTMENT

      protected static final int CONGESTION_COST_ADJUSTMENT
      Adjustment factor for congestion cost.
      See Also:
    • BUNDLE_NAME

      private static final String BUNDLE_NAME
      Bundle holding the translated console strings.
      See Also:
  • Constructor Details

    • TransportImpl

      public TransportImpl(RouterContext context)
      Initialize the new transport.
      Parameters:
      context - the router context supplying the log, statistics and comm system
  • Method Details

    • getSendPoolCapacity

      public static int getSendPoolCapacity()
      Capacity of the NTCP send pool.
      Returns:
      the messages the pool holds
    • getSendPool

      public PrioritySendPool getSendPool()
      The send pool instance, for stat access.
      Returns:
      the pool, null if this is not NTCP
    • setSendPoolCapacity

      public static void setSendPoolCapacity(int capacity)
      The NTCP send pool capacity (called by Tuner). Resizes the pool on NTCP transports, draining old messages.
      Parameters:
      capacity - the number of messages the pool should hold
    • sendPoolCapacityMin

      public static int sendPoolCapacityMin()
      The smallest capacity setSendPoolCapacity(int) accepts.
      Returns:
      half the platform default, in queued messages
    • sendPoolCapacityMax

      public static int sendPoolCapacityMax()
      The largest capacity setSendPoolCapacity(int) accepts.

      Public because the auto-tuner declares a range for this pool and must not propose a value the setter silently rewrites back — that reads as a param that will not take effect.

      Returns:
      the core-scaled ceiling, in queued messages
    • resizeSendPool

      public void resizeSendPool()
      Resize the NTCP send pool if needed. Creates a new pool with the current capacity and drains old messages into it.
    • countPeers

      public abstract int countPeers()
      How many peers are we connected to?
      Specified by:
      countPeers in interface Transport
      Returns:
      the number of peers this transport knows of, established or not
    • countActivePeers

      public abstract int countActivePeers()
      How many peers are we currently connected to, that we have sent a message to or received a message from in the last five minutes.
      Specified by:
      countActivePeers in interface Transport
      Returns:
      the number of such peers
    • getMaxConnections

      public int getMaxConnections()
      Per-transport connection limit.
      Returns:
      the maximum concurrent peer connections for this transport, 0 when the comm system is a test dummy
    • getContext

      public RouterContext getContext()
      The context this transport runs in.
      Returns:
      the context, never null
    • getTransportMaxConnections

      public static int getTransportMaxConnections(RouterContext ctx, String style)
      The transport max connections for the given context and style.
      Parameters:
      ctx - the router context to read the configuration from
      style - the transport style, e.g. "SSU" or "NTCP"
      Returns:
      the transport max connections, 0 when the comm system is a test dummy
    • haveCapacity

      public boolean haveCapacity()
      Can we initiate or accept a connection to another peer, saving some margin.
      Specified by:
      haveCapacity in interface Transport
      Returns:
      true if capacity available
    • haveCapacity

      public boolean haveCapacity(int pct)
      Whether we are under the given capacity level.
      Specified by:
      haveCapacity in interface Transport
      Parameters:
      pct - are we under x% 0-100
      Returns:
      true if capacity available
    • getClockSkews

      public List<Long> getClockSkews()
      Peer clock skews on a transport. List composed of Long, each element representing a peer skew in seconds. Dummy version. Transports override it.
      Specified by:
      getClockSkews in interface Transport
      Returns:
      the clock skews
    • getMostRecentErrorMessages

      public List<String> getMostRecentErrorMessages()
      Recent error messages from this transport.
      Specified by:
      getMostRecentErrorMessages in interface Transport
      Returns:
      the messages, empty if there are none
    • getNextMessage

      protected OutNetMessage getNextMessage()
      Nonblocking call to pull the next outbound message off the queue.

      Only used by NTCP. SSU does not call.

      Returns:
      the next highest-priority message or null if none available
    • afterSend

      protected void afterSend(OutNetMessage msg, boolean sendSuccessful)
      The transport is done sending this message.
      Parameters:
      msg - message in question
      sendSuccessful - true if the peer received it
    • afterSend

      protected void afterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue)
      The transport is done sending this message.
      Parameters:
      msg - message in question
      sendSuccessful - true if the peer received it
      allowRequeue - true if we should try other transports if available
    • afterSend

      protected void afterSend(OutNetMessage msg, boolean sendSuccessful, long msToSend)
      The transport is done sending this message.
      Parameters:
      msg - message in question
      sendSuccessful - true if the peer received it
      msToSend - how long it took to transfer the data to the peer
    • afterSend

      protected void afterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue, long msToSend)
      The transport is done sending this message. This is the method that actually does all of the cleanup - firing off jobs, requeueing, updating stats, etc.
      Parameters:
      msg - message in question
      sendSuccessful - true if the peer received it
      allowRequeue - true if we should try other transports if available
      msToSend - how long it took to transfer the data to the peer
    • addJobIfPresent

      private void addJobIfPresent(Job job)
      Runs the job if the context has a job queue.
      Parameters:
      job - the job to run
    • unregisterAndDiscard

      private void unregisterAndDiscard(OutNetMessage msg)
      Drops a message from the send queue.
      Parameters:
      msg - the message to discard
    • send

      public void send(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). 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
      Parameters:
      msg - the message to send, containing destination, payload, and callbacks
    • outboundMessageReady

      protected abstract void outboundMessageReady()
      This message is called whenever a new message is added to the send pool, and it should not block

      Only used by NTCP. SSU throws UOE.

    • messageReceived

      public void messageReceived(I2NPMessage inMsg, RouterIdentity remoteIdent, Hash remoteIdentHash, long msToReceive, int bytesReceived)
      Message received from the I2NPMessageReader - send it to the listener.
      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
    • getCurrentAddresses

      public List<RouterAddress> getCurrentAddresses()
      What addresses are we currently listening to? Replaces getCurrentAddress(boolean).
      Specified by:
      getCurrentAddresses in interface Transport
      Returns:
      a copy of all addresses, non-null
    • getCurrentAddress

      public RouterAddress getCurrentAddress(boolean ipv6)
      What address are we currently listening to? Replaces getCurrentAddress()

      Note: An address without a host is considered IPv4.

      Specified by:
      getCurrentAddress in interface Transport
      Parameters:
      ipv6 - true for IPv6 only; false for IPv4 only
      Returns:
      first matching address or null
    • refreshCurrentIPv4

      private void refreshCurrentIPv4()
      Recompute the cached IPv4 address. Must be called with _currentAddresses held, after every change to the list, so that isCurrentIPv4(byte[]) tracks exactly what getCurrentAddress(false) would return. Clones the IP so later mutation of the RouterAddress cannot be seen through the cache.
    • isCurrentIPv4

      public boolean isCurrentIPv4(byte[] ip)
      Is the given IP the current external IPv4 address?

      Equivalent to comparing against getCurrentAddress(boolean) with ipv6 false, but without taking the address-list monitor. For the hot inbound path (per-packet "did this come from us?" check).

      Parameters:
      ip - the IP to test, may be null
      Returns:
      true if we currently have an IPv4 address equal to ip
    • getCurrentIPv4

      protected byte[] getCurrentIPv4()
      IP of the current IPv4 address, from the cache maintained by the address mutators. Does not take the address-list monitor.
      Returns:
      a copy of the IP, or null if we have no IPv4 address
    • hasCurrentAddress

      public boolean hasCurrentAddress()
      Do we have any current address?
      Specified by:
      hasCurrentAddress in interface Transport
      Returns:
      whether current address is present
    • updateAddress

      public List<RouterAddress> updateAddress()
      Ask the transport to update its address based on current information and return it Transports should override.
      Specified by:
      updateAddress in interface Transport
      Returns:
      a copy of all addresses, non-null
    • replaceAddress

      protected void replaceAddress(RouterAddress address)
      Replace any existing addresses for the current transport with the same IP length (4 or 16) with the given one. Note: Does not currently allow multiple addresses of the same length. Calls listener.transportAddressChanged() To remove all IPv4 or IPv6 addresses, use removeAddress(boolean).
      Parameters:
      address - null to remove all
    • removeAddress

      protected void removeAddress(RouterAddress address)
      Remove only this address. Calls listener.transportAddressChanged(). To remove all IPv4 or IPv6 addresses, use removeAddress(boolean). To remove all IPv4 and IPv6 addresses, use replaceAddress(null).
      Parameters:
      address - the address to remove from the transport's advertised list
    • removeAddress

      protected void removeAddress(boolean ipv6)
      Remove all existing addresses with the specified IP length (4 or 16). Calls listener.transportAddressChanged(). To remove all IPv4 and IPv6 addresses, use replaceAddress(null).
      Parameters:
      ipv6 - true to remove all IPv6 addresses, false to remove all IPv4 addresses
    • saveLocalAddress

      protected void saveLocalAddress(InetAddress address)
      Save a local address we were notified about before we started.
      Parameters:
      address - the local address we were notified about
    • getSavedLocalAddresses

      protected Collection<InetAddress> getSavedLocalAddresses()
      Return and then clear all saved local addresses.
      Returns:
      the saved local addresses
    • getTargetAddresses

      public List<RouterAddress> getTargetAddresses(RouterInfo target)
      All available addresses we can use, shuffled and then sorted by cost/preference. Lowest cost (most preferred) first.
      Parameters:
      target - the RouterInfo whose addresses are wanted
      Returns:
      non-null, possibly empty
    • externalAddressReceived

      public abstract void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port)
      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 before startListening() to set an initial address, or after the transport is running.

      Specified by:
      externalAddressReceived in interface Transport
      Parameters:
      source - defined in Transport.java
      ip - typ. IPv4 or IPv6 non-local; may be null to indicate IPv4 failure or port info only
      port - 0 for unknown or unchanged
    • externalAddressRemoved

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

      This can be called after the transport is running.

      This implementation does nothing. Transports should override if they want notification.

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

      public void forwardPortStatus(byte[] ip, int port, int externalPort, boolean success, String reason)
      Notify a transport of the results of trying to forward a port.

      This implementation does nothing. Transports should override if they want notification.

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

      public int getRequestedPort()
      What INTERNAL port would the transport like to have forwarded by UPnP. This can't be passed via getCurrentAddress(), as we have to open the port before we can publish the address, and that's the external port anyway.
      Specified by:
      getRequestedPort in interface Transport
      Returns:
      port or -1 for none or 0 for any
    • setListener

      public void setListener(TransportEventListener listener)
      Who to notify on message availability.
      Specified by:
      setListener in interface Transport
      Parameters:
      listener - the event listener to receive transport notifications
    • renderStatusHTML

      public void renderStatusHTML(Writer out) throws IOException
      Make this stuff pretty.
      Parameters:
      out - the writer to render to
      Throws:
      IOException - if writing fails
    • renderStatusHTML

      public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException
      Render the transport status HTML to the given writer.
      Specified by:
      renderStatusHTML in interface Transport
      Parameters:
      out - writer the status HTML is rendered into
      urlBase - base URL for the links embedded in the HTML
      sortFlags - flags controlling sorting and display options
      Throws:
      IOException - if the status HTML cannot be written to the writer
    • getReachabilityStatus

      public abstract CommSystemFacade.Status getReachabilityStatus()
      Previously returned short, now enum as of 0.9.20.
      Specified by:
      getReachabilityStatus in interface Transport
      Returns:
      the reachability status
    • isIPv4Firewalled

      public boolean isIPv4Firewalled()
      This returns true if the force-firewalled setting is configured, false otherwise.
      Specified by:
      isIPv4Firewalled in interface Transport
      Returns:
      whether i pv4 firewalled
    • isIPv6Firewalled

      public boolean isIPv6Firewalled()
      This returns true if the force-firewalled setting is configured, false otherwise.
      Specified by:
      isIPv6Firewalled in interface Transport
      Returns:
      whether IPv6 firewalled
    • isBacklogged

      public boolean isBacklogged(Hash peer)
      Whether the given peer is backlogged.
      Specified by:
      isBacklogged in interface Transport
      Parameters:
      peer - hash of the peer to check
      Returns:
      false; this base class has no notion of backlogs
    • isEstablished

      public boolean isEstablished(Hash peer)
      Whether the given peer is established.
      Specified by:
      isEstablished in interface Transport
      Parameters:
      peer - hash of the peer to check
      Returns:
      false; only a real transport reports established sessions
    • wasFailsafeClosed

      public boolean wasFailsafeClosed(Hash peer, long withinMs)
      Whether this transport closed a session to the peer for idleness recently.

      A peer whose session we closed ourselves is not a peer that went away: it is one we declined to keep talking to. Callers use the distinction to attribute a later loss of connectivity, where guessing is worse than not knowing, so the default is a false rather than an approximation.

      Specified by:
      wasFailsafeClosed in interface Transport
      Parameters:
      peer - the peer to ask about
      withinMs - how far back counts as recent; non-positive means nothing is recent
      Returns:
      true when this transport closed a session to the peer that recently
    • isConnecting

      public boolean isConnecting(Hash peer)
      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
      Parameters:
      peer - 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
      Parameters:
      peer - hash of the peer that may be disconnected
    • isUnreachable

      public boolean isUnreachable(Hash peer)
      Whether the given peer is unreachable.
      Specified by:
      isUnreachable in interface Transport
      Parameters:
      peer - hash of the peer to check
      Returns:
      true if the peer is in the unreachable cache and was not the last peer reached, false if it is reachable
    • markUnreachable

      public void markUnreachable(Hash peer)
      Called when we can't reach a peer.
      Parameters:
      peer - the router hash that did not answer
    • markReachable

      public void markReachable(Hash peer, boolean isInbound)
      Called when we establish a peer connection (outbound or inbound).
      Parameters:
      peer - the router hash that just connected
      isInbound - true if we accepted the connection, false if we dialled out
    • stopCleanupJob

      public void stopCleanupJob()
      Cancel the unreachable-entry cleanup, if one is scheduled.
    • wasUnreachable

      public boolean wasUnreachable(Hash peer)
      Was the peer unreachable (outbound only) the last time we tried it? This is NOT reset if the peer contacts us.
      Specified by:
      wasUnreachable in interface Transport
      Parameters:
      peer - hash of the peer to check reachability for
      Returns:
      true if peer was unreachable on last outbound attempt
    • markWasUnreachable

      private void markWasUnreachable(Hash peer, boolean yes)
      Maintain the WasUnreachable list.
      Parameters:
      peer - the peer to add or remove
      yes - true to add the peer to the list, false to remove it
    • allowLocal

      public boolean allowLocal()
      Are we allowed to connect to local addresses?
      Returns:
      true if i2np.allowLocal is set, false otherwise
    • setIP

      public void setIP(Hash peer, byte[] ip)
      IP of the peer from the last connection (in or out, any transport).
      Parameters:
      peer - the router hash the address was last seen for
      ip - IPv4 or IPv6, non-null
    • getIP

      public static byte[] getIP(Hash peer)
      IP of the peer from the last connection (in or out, any transport).
      Parameters:
      peer - the router hash to look the IP up for
      Returns:
      IPv4 or IPv6 or null
    • formatIPPort

      public static String formatIPPort(byte[] ip, int port)
      Format an IP byte array (4 or 16 bytes) as host:port, for logging.
      Parameters:
      ip - 4 or 16 byte address
      port - port number, may be 0
      Returns:
      "host:port" or "[host]:port", "UNKNOWN" for other lengths
    • getRouterIPPort

      public static String getRouterIPPort(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.
      Parameters:
      router - may be null
      Returns:
      "host:port" or "UNKNOWN"
    • getAltStyle

      public String getAltStyle()
      An alternate supported style, or null.
      Returns:
      null, override to add support
    • clearCaches

      static void clearCaches()
      Drop the cached router-hash to IP mapping, so the next lookup reads it again from the network database.
    • getIPv6Config

      public TransportUtil.IPv6Config getIPv6Config()
      The IPv6 configuration for this transport.
      Specified by:
      getIPv6Config in interface Transport
      Returns:
      the IPv6 config
    • isPubliclyRoutable

      protected boolean isPubliclyRoutable(byte[] addr)
      Allows IPv6 only if the transport is configured for it. Caller must check if we actually have a public IPv6 address.
      Parameters:
      addr - non-null
      Returns:
      whether publicly routable
    • _t

      protected String _t(String s)
      Looks the string up in the web messages bundle, returning s itself if there is no translation.
      Parameters:
      s - the string to be translated
      Returns:
      the translated string, or s itself when there is no translation
    • _t

      protected String _t(String s, Object o)
      Translate and substitute one parameter.
      Parameters:
      s - the string to be translated, containing {0}
      o - the parameter, not translated itself
      Returns:
      the translated string with {0} replaced by o
    • ngettext

      protected String ngettext(String s, String p, int n)
      Translate, choosing between the singular and the plural form.
      Parameters:
      s - the singular string, may contain {0} for the count
      p - the plural string, may contain {0} for the count
      n - the count, used to choose between s and p
      Returns:
      the translated string for that count