java.lang.Object
net.i2p.client.impl.I2PSessionImpl
net.i2p.client.impl.I2PSessionImpl2
All Implemented Interfaces:
I2PSession, I2CPMessageReader.I2CPMessageEventListener
Direct Known Subclasses:
I2PSessionMuxedImpl, I2PSimpleSession

class I2PSessionImpl2extends I2PSessionImpl
Thread safe implementation of an I2P session running over TCP.

Unused directly, see I2PSessionMuxedImpl extension.

  • Field Details

    • _sendingStates

      protected final Map<Long, MessageState> _sendingStates
      One MessageState object per message in the process of being sent.
    • _sendMessageNonce

      protected final AtomicLong _sendMessageNonce
      Source of the per-message replay nonces sent to the router.
    • SEND_TIMEOUT

      private static final long SEND_TIMEOUT
      Max # seconds to wait for confirmation of the message send.
      See Also:
    • SHOULD_COMPRESS

      private static final boolean SHOULD_COMPRESS
      Should we gzip each payload prior to sending it?
      See Also:
    • SHOULD_DECOMPRESS

      private static final boolean SHOULD_DECOMPRESS
      Whether the router may send compressed lease sets.
      See Also:
    • _noEffort

      protected boolean _noEffort
      Don't expect any MSMs from the router for outbound traffic.
    • REMOVE_EXPIRED_TIME

      private static final long REMOVE_EXPIRED_TIME
      How often expired leases are dropped - every 63 seconds.
      See Also:
    • _tunnelManagerMethod

      private static Method _tunnelManagerMethod
      Reflected accessor for the tunnel manager.
    • DONT_COMPRESS_SIZE

      private static final int DONT_COMPRESS_SIZE
      Don't bother if really small. Three 66-byte messages will fit in one tunnel message. Four messages don't fit no matter how small. So below 66 it isn't worth it. See ConnectionOptions.java in the streaming lib for similar calculations.

      Since we still have to pass it through gzip -0 the CPU savings is trivial but it's the best we can do for now. See below. i2cp.gzip defaults to SHOULD_COMPRESS = true.

      Perhaps the http server (which does its own compression) and P2P apps (with generally uncompressible data) should set to false.

      See Also:
    • _currentTunnelPair

      private volatile I2PSession.TunnelPair _currentTunnelPair
      The tunnels carrying this session now.
  • Constructor Details

    • I2PSessionImpl2

      protected I2PSessionImpl2(I2PAppContext context, Properties options, I2PClientMessageHandlerMap handlerMap)
      For extension by SimpleSession (no dest).
      Parameters:
      context - the app context whose router client the session sends through
      options - router connection options, or null to use the System properties
      handlerMap - the map the session registers its incoming-message handlers in
    • I2PSessionImpl2

      protected I2PSessionImpl2(I2PAppContext ctx, InputStream destKeyStream, Properties options) throws I2PSessionException
      For extension by I2PSessionMuxedImpl

      Create a new session, reading the Destination, PrivateKey, and SigningPrivateKey from the destKeyStream, and using the specified options to connect to the router.

      Parameters:
      ctx - the app context whose router client the session sends through
      destKeyStream - stream containing the private key data, format is specified in PrivateKeyFile
      options - set of options to configure the router with, if null will use System properties
      Throws:
      I2PSessionException - if there is a problem loading the private keys
    • I2PSessionImpl2

      protected I2PSessionImpl2(I2PSessionImpl primary, InputStream destKeyStream, Properties options) throws I2PSessionException
      For extension by SubSession via I2PSessionMuxedImpl

      Create a new session, reading the Destination, PrivateKey, and SigningPrivateKey from the destKeyStream, and using the specified options to connect to the router.

      Parameters:
      primary - the muxed session whose context, handlers and producer are shared
      destKeyStream - stream containing the private key data, format is specified in PrivateKeyFile
      options - set of options to configure the router with, if null will use System properties
      Throws:
      I2PSessionException - if the destination key stream cannot be read or parsed
  • Method Details

    • startVerifyUsage

      protected void startVerifyUsage()
      Fire up a periodic task to check for unclaimed messages.
      Overrides:
      startVerifyUsage in class I2PSessionImpl
    • getTimeout

      protected long getTimeout()
      Wait this long for the router to accept a sent message, in ms.
      Returns:
      milliseconds to wait for the router to accept the message
    • destroySession

      public void destroySession(boolean sendDisconnect)
      Destroy the I2P session, after clearing the message send states.
      Overrides:
      destroySession in class I2PSessionImpl
      Parameters:
      sendDisconnect - if true, send a disconnect message to the router
    • shouldCompress

      protected boolean shouldCompress(int size)
      Return whether compression should be used.
      Parameters:
      size - the uncompressed message size in bytes, compared to 66
      Returns:
      true if the message should be compressed before sending
    • addSessionListener

      public void addSessionListener(I2PSessionListener lsnr, int proto, int port)
      Register a session listener. Not supported by this implementation - use I2PSessionMuxedImpl, which demultiplexes by protocol and port.
      Parameters:
      lsnr - the listener
      proto - ignored - this implementation registers no listeners
      port - ignored - this implementation registers no listeners
      Throws:
      UnsupportedOperationException - always, as listeners are unsupported here
    • addMuxedSessionListener

      public void addMuxedSessionListener(I2PSessionMuxedListener l, int proto, int port)
      Register a muxed session listener. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      l - the listener
      proto - ignored - this implementation registers no listeners
      port - ignored - this implementation registers no listeners
      Throws:
      UnsupportedOperationException - always, as listeners are unsupported here
    • removeListener

      public void removeListener(int proto, int port)
      Remove a registered listener. Not supported by this implementation - nothing is ever registered here.
      Parameters:
      proto - ignored - nothing is ever registered here
      port - ignored - nothing is ever registered here
      Throws:
      UnsupportedOperationException - always, as no listener is ever registered
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int proto, int fromport, int toport) throws I2PSessionException
      Send an I2CP message. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      proto - 1-254, or 0 for unset; 255 disallowed
      fromport - source port, 1-65535 or 0 for unset
      toport - destination port, 1-65535 or 0 for unset
      Returns:
      false always
      Throws:
      UnsupportedOperationException - always, as muxed sends are unsupported here
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set<SessionTag> tagsSent, int proto, int fromport, int toport) throws I2PSessionException
      Send an I2CP message. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      keyUsed - UNUSED, IGNORED, as end-to-end crypto is disabled
      tagsSent - UNUSED, IGNORED, as end-to-end crypto is disabled
      proto - 1-254 or 0 for unset; recommended: I2PSession.PROTO_UNSPECIFIED I2PSession.PROTO_STREAMING I2PSession.PROTO_DATAGRAM 255 disallowed
      fromport - 1-65535 or 0 for unset
      toport - 1-65535 or 0 for unset
      Returns:
      false always
      Throws:
      UnsupportedOperationException - always, as muxed sends are unsupported here
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set<SessionTag> tagsSent, long expire, int proto, int fromport, int toport) throws I2PSessionException
      Send an I2CP message. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      keyUsed - UNUSED, IGNORED, as end-to-end crypto is disabled
      tagsSent - UNUSED, IGNORED, as end-to-end crypto is disabled
      expire - absolute expiration timestamp, NOT interval from now
      proto - 1-254 or 0 for unset; recommended: I2PSession.PROTO_UNSPECIFIED I2PSession.PROTO_STREAMING I2PSession.PROTO_DATAGRAM 255 disallowed
      fromport - 1-65535 or 0 for unset
      toport - 1-65535 or 0 for unset
      Returns:
      false always
      Throws:
      UnsupportedOperationException - always, as muxed sends are unsupported here
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set<SessionTag> tagsSent, long expire, int proto, int fromport, int toport, int flags) throws I2PSessionException
      Send an I2CP message. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      keyUsed - UNUSED, IGNORED, as end-to-end crypto is disabled
      tagsSent - UNUSED, IGNORED, as end-to-end crypto is disabled
      expire - absolute expiration timestamp, NOT interval from now
      proto - 1-254 or 0 for unset; recommended: I2PSession.PROTO_UNSPECIFIED I2PSession.PROTO_STREAMING I2PSession.PROTO_DATAGRAM 255 disallowed
      fromport - 1-65535 or 0 for unset
      toport - 1-65535 or 0 for unset
      flags - packed SendMessageOptions bits to send with the message
      Returns:
      false always
      Throws:
      UnsupportedOperationException - always, as muxed sends are unsupported here
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, int proto, int fromport, int toport, SendMessageOptions options) throws I2PSessionException
      Send an I2CP message. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      proto - 1-254 or 0 for unset; recommended: I2PSession.PROTO_UNSPECIFIED I2PSession.PROTO_STREAMING I2PSession.PROTO_DATAGRAM 255 disallowed
      fromport - 1-65535 or 0 for unset
      toport - 1-65535 or 0 for unset
      options - to be passed to the router
      Returns:
      false always
      Throws:
      UnsupportedOperationException - always, as muxed sends are unsupported here
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public long sendMessage(Destination dest, byte[] payload, int offset, int size, int proto, int fromport, int toport, SendMessageOptions options, SendMessageStatusListener listener) throws I2PSessionException
      Send an I2CP message. Not supported by this implementation - use I2PSessionMuxedImpl.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      proto - 1-254 or 0 for unset; recommended: I2PSession.PROTO_UNSPECIFIED I2PSession.PROTO_STREAMING I2PSession.PROTO_DATAGRAM 255 disallowed
      fromport - 1-65535 or 0 for unset
      toport - 1-65535 or 0 for unset
      options - to be passed to the router
      listener - for delivery status notification
      Returns:
      -1 always
      Throws:
      UnsupportedOperationException - always, as muxed sends are unsupported here
      I2PSessionException - on all errors
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload) throws I2PSessionException
      Unused, see MuxedImpl override.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      Returns:
      whether it was accepted by the router for delivery or not
      Throws:
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size) throws I2PSessionException
      Send an I2CP message. No end-to-end crypto is done, so any key or tags are ignored; this delegates to the no-effort/best-effort send below.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      Returns:
      whether the router accepted the message for delivery
      Throws:
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed, Set<SessionTag> tagsSent) throws I2PSessionException
      Send a message with session key and tags.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      keyUsed - unused - no end-to-end crypto
      tagsSent - unused - no end-to-end crypto
      Returns:
      whether the router accepted the message for delivery
      Throws:
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set<SessionTag> tagsSent) throws I2PSessionException
      Send a message with session key and tags.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      keyUsed - unused - no end-to-end crypto
      tagsSent - unused - no end-to-end crypto
      Returns:
      whether the router accepted the message for delivery
      Throws:
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • sendMessage

      public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set<SessionTag> tagsSent, long expires) throws I2PSessionException
      Unused? See the MuxedImpl override.
      Parameters:
      dest - location to send the message
      payload - body of the message to be sent (unencrypted)
      offset - offset into the payload
      size - number of bytes to send
      keyUsed - unused - no end-to-end crypto
      tagsSent - unused - no end-to-end crypto
      expires - absolute expiration timestamp, NOT interval from now
      Returns:
      whether the router accepted the message for delivery
      Throws:
      I2PSessionException - if the session is not open or closed, or the write queue stays full
    • receiveMessage

      public byte[] receiveMessage(int msgId) throws I2PSessionException
      Receive a message from the router, decompressing it unless it was sent uncompressed.
      Specified by:
      receiveMessage in interface I2PSession
      Overrides:
      receiveMessage in class I2PSessionImpl
      Parameters:
      msgId - the message ID
      Returns:
      the data, or null on error
      Throws:
      I2PSessionException - declared but never thrown; failures return null instead
    • sendBestEffort

      protected boolean sendBestEffort(Destination dest, byte[] payload, SessionKey keyUsed, Set<SessionTag> tagsSent, long expires) throws I2PSessionException
      Send a message with best effort delivery.
      Parameters:
      dest - the remote destination to send to
      payload - the message bytes to deliver
      keyUsed - unused - no end-to-end crypto
      tagsSent - unused - no end-to-end crypto
      expires - expiration time in ms since the epoch, 0 for the router default
      Returns:
      whether the router accepted the message for delivery
      Throws:
      I2PSessionException - if the wait for the router's status update is interrupted
    • sendBestEffort

      protected boolean sendBestEffort(Destination dest, byte[] payload, long expires, int flags) throws I2PSessionException
      Send a best-effort message with the given flags.
      Parameters:
      dest - the remote destination to send to
      payload - the message bytes to deliver
      expires - expiration time in ms since the epoch, 0 for the router default
      flags - to be passed to the router
      Returns:
      whether the router accepted the message for delivery
      Throws:
      I2PSessionException - if the wait for the router's status update is interrupted
    • sendNoEffort

      protected boolean sendNoEffort(Destination dest, byte[] payload, long expires, int flags) throws I2PSessionException
      Same as sendBestEffort(Destination, byte[], SessionKey, Set, long), except we do not expect any MessageStatusMessage responses - not for accepted, or success, or failure. So we don't create a MessageState and save it on the _sendingStates HashSet.
      Parameters:
      dest - the remote destination to send to
      payload - the message bytes
      expires - expiration time in ms since the epoch, 0 for the router default
      flags - to be passed to the router
      Returns:
      true always
      Throws:
      I2PSessionException - if the router rejects the send
    • receiveStatus

      public void receiveStatus(int msgId, long nonce, int status)
      Only call this with nonzero status, i.e. for outbound messages whose MessageState may be queued on _sendingStates.

      Even when using sendBestEffort(), this is a waste, because the MessageState is removed from _sendingStates immediately and so the lookup here fails.

      This is now pretty much avoided since streaming now sets i2cp.messageReliability = none, which forces sendNoEffort() instead of sendBestEffort(), so the router won't send us any MSM's for outbound traffic.

      Specified by:
      receiveStatus in class I2PSessionImpl
      Parameters:
      msgId - the message ID
      nonce - the nonce identifying the send
      status - != 0
    • reconnect

      protected boolean reconnect()
      Reconnect the I2CP session. Called by the superclass whenever it wants to reconnect; overridden to also clear out the message state.
      Overrides:
      reconnect in class I2PSessionImpl
      Returns:
      whether the session was reconnected
    • clearStates

      private void clearStates()
      Clear all pending message states.
    • getTunnelManager

      private Object getTunnelManager()
      Cached reflection access to RouterContext.tunnelManager(). Method is looked up once and reused to avoid repeated getMethod() overhead.
      Returns:
      the tunnel manager
    • addTunnelStatusListener

      public void addTunnelStatusListener(TunnelStatusListener lsnr)
      Register a tunnel status listener. In a router context the listener is also registered with the TunnelPoolManager, if there is one.
      Parameters:
      lsnr - the listener
    • removeTunnelStatusListener

      public void removeTunnelStatusListener(TunnelStatusListener lsnr)
      Remove a tunnel status listener.
      Parameters:
      lsnr - the listener
    • switchToNewTunnel

      public boolean switchToNewTunnel()
      Switch to the new tunnel set. Not supported by this implementation.
      Returns:
      false always
    • setCurrentTunnelPair

      public void setCurrentTunnelPair(I2PSession.TunnelPair pair)
      Current tunnel pair in use.
      Parameters:
      pair - the tunnel pair in use
    • getCurrentTunnelPair

      public I2PSession.TunnelPair getCurrentTunnelPair()
      Return the current tunnel pair.
      Returns:
      the current tunnel pair, or null if none
    • rebuildTunnels

      public void rebuildTunnels()
      Rebuild the tunnel set.
    • notifyTunnelFailed

      protected void notifyTunnelFailed(String poolName, boolean isInbound)
      Notify all tunnel status listeners of a tunnel failure.
      Parameters:
      poolName - the pool the failed tunnel belonged to
      isInbound - true if the tunnel was an inbound one
    • notifyTunnelRemoved

      protected void notifyTunnelRemoved(TunnelRemovalEvent event)
      Notify all tunnel status listeners of a tunnel removal.
      Parameters:
      event - identifies the removed tunnel, its pool, direction and the reason
    • notifyPoolShuttingDown

      protected void notifyPoolShuttingDown(String poolName, boolean isInbound)
      Notify all tunnel status listeners of pool shutdown.
      Parameters:
      poolName - the pool being shut down
      isInbound - true if the pool builds inbound tunnels