Class I2PSessionImpl

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

public abstract class I2PSessionImpl extends Object implements I2PSession, I2CPMessageReader.I2CPMessageEventListener
Implementation of an I2P session running over TCP. This class is NOT thread safe - only one thread should send messages at any given time Public only for clearCache(). Except for methods defined in I2PSession and I2CPMessageEventListener, not maintained as a public API, not for external use. Use I2PClientFactory to get an I2PClient and then createSession().
Author:
jrandom
  • Field Details

    • _log

      protected final Log _log
    • _leaseSet

      protected volatile LeaseSet _leaseSet
      currently granted lease set, or null
    • _transientSigningPublicKey

      protected SigningPublicKey _transientSigningPublicKey
    • _hostname

      protected final String _hostname
      hostname of router - will be null if in RouterContext
    • _portNum

      protected final int _portNum
      port num to router - will be 0 if in RouterContext
    • _socket

      protected Socket _socket
      socket for comm
    • _reader

      protected I2CPMessageReader _reader
      reader that always searches for messages
    • _writer

      protected ClientWriterRunner _writer
      writer message queue
    • _queue

      protected I2CPMessageQueue _queue
      Used for internal connections to the router. If this is set, _socket and _writer will be null.
      Since:
      0.8.3
    • _sessionListener

      protected I2PSessionListener _sessionListener
      who we send events to
    • _producer

      protected final I2CPMessageProducer _producer
      class that generates new messages
    • _availableMessages

      protected Map<Long,MessagePayloadMessage> _availableMessages
      map of Long --> MessagePayloadMessage
    • _pendingLookups

      protected final LinkedBlockingQueue<net.i2p.client.impl.I2PSessionImpl.LookupWaiter> _pendingLookups
      hashes of lookups we are waiting for
    • _bwReceivedLock

      protected final Object _bwReceivedLock
    • _bwLimits

      protected volatile int[] _bwLimits
    • _handlerMap

      protected final I2PClientMessageHandlerMap _handlerMap
    • _context

      protected final I2PAppContext _context
      used to separate things out so we can get rid of singletons
    • _leaseSetWait

      protected final Object _leaseSetWait
      monitor for waiting until a lease set has been granted
    • _state

      protected I2PSessionImpl.State _state
    • _stateLock

      protected final Object _stateLock
    • _availabilityNotifier

      protected I2PSessionImpl.AvailabilityNotifier _availabilityNotifier
      thread that we tell when new messages are available who then tells us to fetch them. The point of this is so that the fetch doesn't block the reading of other messages (in turn, potentially leading to deadlock)
    • CACHE_MAX_SIZE

      protected static final int CACHE_MAX_SIZE
    • PROP_DOMAIN_SOCKET

      protected static final String PROP_DOMAIN_SOCKET
      Use Unix domain socket (or similar) to connect to a router
      Since:
      0.9.14
      See Also:
    • LISTEN_PORT

      public static final int LISTEN_PORT
      See Also:
  • Constructor Details

    • I2PSessionImpl

      protected I2PSessionImpl(I2PAppContext context, Properties options, I2PClientMessageHandlerMap handlerMap)
      for extension by SimpleSession (no dest)
    • I2PSessionImpl

      protected I2PSessionImpl(I2PSessionImpl primary, InputStream destKeyStream, Properties options) throws I2PSessionException
      Throws:
      I2PSessionException
    • I2PSessionImpl

      public I2PSessionImpl(I2PAppContext context, InputStream destKeyStream, Properties options) throws I2PSessionException
      Create a new session, reading the Destination, PrivateKey, and SigningPrivateKey from the destKeyStream, and using the specified options to connect to the router As of 0.9.19, defaults in options are honored. This does NOT validate consistency of the destKeyStream, e.g. pubkey/privkey match or valid offline sig. The router does that.
      Parameters:
      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
  • Method Details

    • dateUpdated

      void dateUpdated(String routerVersion)
      Parameters:
      routerVersion - as rcvd in the SetDateMessage, may be null for very old routers
    • addSubsession

      public I2PSession addSubsession(InputStream privateKeyStream, Properties opts) throws I2PSessionException
      Router must be connected or was connected... for now.
      Specified by:
      addSubsession in interface I2PSession
      Parameters:
      privateKeyStream - null for transient, if non-null must have same encryption keys as primary session and different signing keys
      opts - subsession options if any, may be null
      Returns:
      a new subsession, non-null
      Throws:
      I2PSessionException
      Since:
      0.9.21
    • removeSubsession

      public void removeSubsession(I2PSession session)
      Specified by:
      removeSubsession in interface I2PSession
      Since:
      0.9.21
    • getSubsessions

      public List<I2PSession> getSubsessions()
      Specified by:
      getSubsessions in interface I2PSession
      Returns:
      a list of subsessions, non-null, does not include the primary session
      Since:
      0.9.21
    • updateOptions

      public void updateOptions(Properties options)
      Update the tunnel and bandwidth settings
      Specified by:
      updateOptions in interface I2PSession
      Parameters:
      options - non-null
      Since:
      0.8.4
    • getFastReceive

      public boolean getFastReceive()
      Since:
      0.9.4
    • supportsLS2

      public boolean supportsLS2()
      Since:
      0.9.38
    • setLeaseSet

      void setLeaseSet(LeaseSet ls)
    • getLeaseSet

      LeaseSet getLeaseSet()
    • changeState

      protected void changeState(I2PSessionImpl.State state)
    • isOffline

      public boolean isOffline()
      Does this session have offline and transient keys?
      Specified by:
      isOffline in interface I2PSession
      Since:
      0.9.38
    • getOfflineExpiration

      public long getOfflineExpiration()
      Description copied from interface: I2PSession
      Get the offline expiration
      Specified by:
      getOfflineExpiration in interface I2PSession
      Returns:
      Java time (ms) or 0 if not initialized or does not have offline keys
      Since:
      0.9.38
    • getOfflineSignature

      public Signature getOfflineSignature()
      Specified by:
      getOfflineSignature in interface I2PSession
      Returns:
      null on error or if not initialized or does not have offline keys
      Since:
      0.9.38
    • getTransientSigningPublicKey

      public SigningPublicKey getTransientSigningPublicKey()
      Specified by:
      getTransientSigningPublicKey in interface I2PSession
      Returns:
      null on error or if not initialized or does not have offline keys
      Since:
      0.9.38
    • connect

      public void connect() throws I2PSessionException
      Connect to the router and establish a session. This call blocks until a session is granted. Should be threadsafe, other threads will block until complete. Disconnect / destroy from another thread may be called simultaneously and will (should?) interrupt the connect. Connecting a primary session will not automatically connect subsessions. Connecting a subsession will automatically connect the primary session if not previously connected.
      Specified by:
      connect in interface I2PSession
      Throws:
      I2PSessionException - if there is a configuration error or the router is not reachable
    • waitForDate

      protected void waitForDate() throws InterruptedException, IOException
      Throws:
      InterruptedException
      IOException
      Since:
      0.9.11 moved from connect()
    • receiveMessage

      public byte[] receiveMessage(int msgId) throws I2PSessionException
      Pull the unencrypted data from the message that we've already prefetched and notified the user that its available.
      Specified by:
      receiveMessage in interface I2PSession
      Parameters:
      msgId - message to fetch
      Returns:
      unencrypted body of the message, or null if not found
      Throws:
      I2PSessionException
    • reportAbuse

      public void reportAbuse(int msgId, int severity) throws I2PSessionException
      Report abuse with regards to the given messageId
      Specified by:
      reportAbuse in interface I2PSession
      Parameters:
      msgId - message that was abusive (or -1 for not message related)
      severity - how abusive
      Throws:
      I2PSessionException
    • receiveStatus

      public abstract void receiveStatus(int msgId, long nonce, int status)
    • addNewMessage

      public void addNewMessage(MessagePayloadMessage msg)
      Recieve a payload message and let the app know its available
    • startVerifyUsage

      protected void startVerifyUsage()
      Fire up a periodic task to check for unclaimed messages
      Since:
      0.9.1
    • messageReceived

      public void messageReceived(I2CPMessageReader reader, I2CPMessage message)
      The I2CPMessageEventListener callback. Recieve notification of some I2CP message and handle it if possible. We route the message based on message type AND session ID. The following types never contain a session ID and are not routable to a subsession: BandwidthLimitsMessage, DestReplyMessage The following types may not contain a valid session ID even when intended for a subsession, so we must take special care: SessionStatusMessage
      Specified by:
      messageReceived in interface I2CPMessageReader.I2CPMessageEventListener
      Parameters:
      reader - unused
      message - the I2CPMessage
    • readError

      public void readError(I2CPMessageReader reader, Exception error)
      The I2CPMessageEventListener callback. Recieve notifiation of an error reading the I2CP stream. As of 0.9.41, does NOT call sessionlistener.disconnected(), the I2CPMessageReader will call disconnected() also.
      Specified by:
      readError in interface I2CPMessageReader.I2CPMessageEventListener
      Parameters:
      reader - unused
      error - non-null
    • getMyDestination

      public Destination getMyDestination()
      Retrieve the destination of the session
      Specified by:
      getMyDestination in interface I2PSession
    • getDecryptionKey

      public PrivateKey getDecryptionKey()
      Retrieve the decryption PrivateKey
      Specified by:
      getDecryptionKey in interface I2PSession
    • getPrivateKey

      public SigningPrivateKey getPrivateKey()
      Retrieve the signing SigningPrivateKey. As of 0.9.38, this will be the transient key if offline signed.
      Specified by:
      getPrivateKey in interface I2PSession
    • getProducer

      I2CPMessageProducer getProducer()
      Retrieve the helper that generates I2CP messages
    • getHandlerMap

      For Subsessions
      Since:
      0.9.21
    • getContext

      I2PAppContext getContext()
      For Subsessions
      Since:
      0.9.21
    • getOptions

      Properties getOptions()
      Retrieve the configuration options, filtered. All defaults passed in via constructor have been promoted to the primary map.
      Returns:
      non-null, if instantiated with null options, this will be the System properties.
    • getSessionId

      SessionId getSessionId()
      Retrieve the session's ID
    • setSessionId

      void setSessionId(SessionId id)
    • setSessionListener

      public void setSessionListener(I2PSessionListener lsnr)
      configure the listener
      Specified by:
      setSessionListener in interface I2PSession
      Parameters:
      lsnr - listener to retrieve events
    • isClosed

      public boolean isClosed()
      Has the session been closed (or not yet connected)? False when open and during transitions. Synchronized.
      Specified by:
      isClosed in interface I2PSession
      Returns:
      true if the session is closed, OR connect() has not been called yet
    • verifyOpen

      protected void verifyOpen() throws I2PSessionException
      Throws I2PSessionException if uninitialized, closed or closing. Blocks if opening.
      Throws:
      I2PSessionException
      Since:
      0.9.23
    • sendMessage

      void sendMessage(I2CPMessage message) throws I2PSessionException
      Deliver an I2CP message to the router As of 0.9.3, may block for several seconds if the write queue to the router is full
      Throws:
      I2PSessionException - if the message is malformed or there is an error writing it out
    • sendMessage_unchecked

      void sendMessage_unchecked(I2CPMessage message) throws I2PSessionException
      Deliver an I2CP message to the router. Does NOT check state. Call only from connect() or other methods that need to send messages when not in OPEN state.
      Throws:
      I2PSessionException - if the message is malformed or there is an error writing it out
      Since:
      0.9.23
    • propogateError

      void propogateError(String msg, Throwable error)
      Pass off the error to the listener Misspelled, oh well. Calls sessionlistener.errorOccurred()
      Parameters:
      error - non-null
    • destroySession

      public void destroySession()
      Tear down the session, and do NOT reconnect. Blocks if session has not been fully started.
      Specified by:
      destroySession in interface I2PSession
    • destroySession

      public void destroySession(boolean sendDisconnect)
      Tear down the session, and do NOT reconnect. Will interrupt an open in progress. Calls sessionlistener.disconnected()
    • disconnected

      public void disconnected(I2CPMessageReader reader)
      The I2CPMessageEventListener callback. Recieve notification that the I2CP connection was disconnected. Calls sessionlistener.disconnected()
      Specified by:
      disconnected in interface I2CPMessageReader.I2CPMessageEventListener
      Parameters:
      reader - unused
    • disconnect

      protected void disconnect()
      Will interrupt a connect in progress. Calls sessionlistener.disconnected()
    • shouldReconnect

      protected boolean shouldReconnect()
    • reconnect

      protected boolean reconnect()
    • getPrefix

      protected String getPrefix()
      try hard to make a decent identifier as this will appear in error logs
    • getName

      protected String getName()
      Since:
      0.9.46
    • destReceived

      void destReceived(Destination d)
      Called by the message handler on reception of DestReplyMessage
      Parameters:
      d - non-null
    • destLookupFailed

      void destLookupFailed(Hash h)
      Called by the message handler on reception of DestReplyMessage
      Parameters:
      h - non-null
    • destReceived

      void destReceived(long nonce, Destination d)
      Called by the message handler on reception of HostReplyMessage
      Parameters:
      d - non-null
      Since:
      0.9.11
    • destLookupFailed

      void destLookupFailed(long nonce, int code)
      Called by the message handler on reception of HostReplyMessage
      Since:
      0.9.11
    • bwReceived

      void bwReceived(int[] i)
      called by the message handler
    • clearCache

      public static void clearCache()
      Since:
      0.9.20
    • lookupDest

      public Destination lookupDest(Hash h) throws I2PSessionException
      Blocking. Waits a max of 10 seconds by default. See lookupDest with maxWait parameter to change. Implemented in 0.8.3 in I2PSessionImpl; previously was available only in I2PSimpleSession. Multiple outstanding lookups are now allowed.
      Specified by:
      lookupDest in interface I2PSession
      Returns:
      null on failure
      Throws:
      I2PSessionException
    • lookupDest

      public Destination lookupDest(Hash h, long maxWait) throws I2PSessionException
      Blocking.
      Specified by:
      lookupDest in interface I2PSession
      Parameters:
      maxWait - ms
      Returns:
      null on failure
      Throws:
      I2PSessionException
      Since:
      0.8.3
    • lookupDest

      public Destination lookupDest(String name) throws I2PSessionException
      Ask the router to lookup a Destination by hostname. Blocking. Waits a max of 10 seconds by default. This only makes sense for a b32 hostname, OR outside router context. Inside router context, just query the naming service. Outside router context, this does NOT query the context naming service. Do that first if you expect a local addressbook. This will log a warning for non-b32 in router context. See interface for suggested implementation. Requires router side to be 0.9.11 or higher. If the router is older, this will return null immediately.
      Specified by:
      lookupDest in interface I2PSession
      Throws:
      I2PSessionException
      Since:
      0.9.11
    • lookupDest

      public Destination lookupDest(String name, long maxWait) throws I2PSessionException
      Ask the router to lookup a Destination by hostname. Blocking. See above for details.
      Specified by:
      lookupDest in interface I2PSession
      Parameters:
      maxWait - ms
      Returns:
      null on failure
      Throws:
      I2PSessionException
      Since:
      0.9.11
    • lookupDest2

      public LookupResult lookupDest2(String name, long maxWait) throws I2PSessionException
      Ask the router to lookup a Destination by hostname. Blocking. See above for details. Same as lookupDest() but with a failure code in the return value
      Specified by:
      lookupDest2 in interface I2PSession
      Parameters:
      maxWait - ms
      Returns:
      non-null
      Throws:
      I2PSessionException
      Since:
      0.9.43
    • bandwidthLimits

      public int[] bandwidthLimits() throws I2PSessionException
      Blocking. Waits a max of 5 seconds. But shouldn't take long. Implemented in 0.8.3 in I2PSessionImpl; previously was available only in I2PSimpleSession. Multiple outstanding lookups are now allowed.
      Specified by:
      bandwidthLimits in interface I2PSession
      Returns:
      null on failure
      Throws:
      I2PSessionException
    • sendBlindingInfo

      public void sendBlindingInfo(BlindData bd) throws I2PSessionException
      Specified by:
      sendBlindingInfo in interface I2PSession
      Throws:
      I2PSessionException
      Since:
      0.9.43
    • getRouterVersion

      public String getRouterVersion()
      Always valid in RouterContext. Returns null if not yet connected in I2PAppContext.
      Specified by:
      getRouterVersion in interface I2PSession
      Returns:
      null if unknown
      Since:
      0.9.46
    • updateActivity

      protected void updateActivity()
    • lastActivity

      public long lastActivity()
    • setReduced

      public void setReduced()
    • toString

      public String toString()
      Overrides:
      toString in class Object