net.i2p.router.client

## Class ClientConnectionRunner

- java.lang.Object
- - net.i2p.router.client.ClientConnectionRunner

- Direct Known Subclasses:
    QueuedClientConnectionRunner

      class ClientConnectionRunner
      extends Object

  Bridge the router and the client - managing state for a client. As of release 0.9.21, multiple sessions are supported on a single I2CP connection. These sessions share tunnels and some configuration.

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected RouterContext` | `_context`
    `protected Log` | `_log`
    `protected ClientManager` | `_manager`
    `protected I2CPMessageReader` | `_reader` thingy that does stuff

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `ClientConnectionRunner(RouterContext context, ClientManager manager, Socket socket)` Create a new runner against the given socket

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `(package private) void` | `ackSendMessage(SessionId sid, MessageId id, long nonce)` Send a notification to the client that their message (id specified) was accepted for delivery (but not necessarily delivered) Doesn't do anything if i2cp.messageReliability = "none" or if the nonce is 0.
    `protected I2CPMessageReader.I2CPMessageEventListener` | `createListener()` Allow override for testing
    `(package private) void` | `disconnectClient(String reason)` Send a DisconnectMessage and log with level Log.ERROR.
    `(package private) void` | `disconnectClient(String reason, int logLevel)`
    `(package private) void` | `disconnected()`
    `(package private) MessageId` | `distributeMessage(SendMessageMessage message)` Distribute the message.
    `(package private) void` | `doSend(I2CPMessage msg)` Actually send the I2CPMessage to the peer through the socket
    `void` | `failLeaseRequest(LeaseRequestState req)`
    `InetAddress` | `getAddress()`
    `String` | `getClientVersion()` The client version.
    `SessionConfig` | `getConfig(Hash h)` Current client's config, will be null if session not found IS subsession aware.
    `SessionConfig` | `getConfig(SessionId id)` Current client's config, will be null if session not found IS subsession aware.
    `Hash` | `getDestHash()` Equivalent to getConfig().getDestination().calculateHash(); will be null before session is established Not subsession aware.
    `Hash` | `getDestHash(SessionId id)` Return the hash for the given ID
    `Destination` | `getDestination(SessionId id)` Return the dest for the given ID
    `(package private) List<Destination>` | `getDestinations()` Subsession aware.
    `FloodfillNetworkDatabaseFacade` | `getFloodfillNetworkDatabaseFacade()` Get the FloodfillNetworkDatabaseFacade for this runner.
    `(package private) boolean` | `getIsDead()`
    `(package private) LeaseRequestState` | `getLeaseRequest(Hash h)` Data for the current leaseRequest, or null if there is no active leaseSet request.
    `LeaseSet` | `getLeaseSet(Hash h)` Currently allocated leaseSet.
    `int` | `getNextMessageId()`
    `(package private) Payload` | `getPayload(MessageId id)` Only call if _dontSendMSMOnReceive is false, otherwise will always be null
    `SessionConfig` | `getPrimaryConfig()` Primary client's config, will be null if session not set up
    `(package private) SessionId` | `getSessionId(Hash h)` Subsession aware.
    `(package private) List<SessionId>` | `getSessionIds()` Subsession aware.
    `SessionKeyManager` | `getSessionKeyManager()` The current client's SessionKeyManager.
    `(package private) boolean` | `isDead()` already closed?
    `(package private) void` | `leaseSetCreated(LeaseSet ls)` called after a new leaseSet is granted by the client, the NetworkDb has been updated.
    `(package private) boolean` | `receiveMessage(Destination toDest, Destination fromDest, Payload payload)` Synchronously deliver the message to the current runner Failure indication is available as of 0.9.29.
    `(package private) boolean` | `receiveMessage(Hash toHash, Destination fromDest, Payload payload)` Synchronously deliver the message to the current runner Failure indication is available as of 0.9.29.
    `boolean` | `registerEncryptedLS(Hash hash)` Call after destinationEstablished(), when an encrypted leaseset is created, so we know it's local.
    `(package private) void` | `removePayload(MessageId id)` Only call if _dontSendMSMOnReceive is false
    `(package private) void` | `removeSession(SessionId id)` Kill the session.
    `void` | `reportAbuse(Destination dest, String reason, int severity)` Send async abuse message to the client
    `(package private) void` | `requestLeaseSet(Hash h, LeaseSet set, long expirationTime, Job onCreateJob, Job onFailedJob)` Request that a particular client authorize the Leases contained in the LeaseSet, after which the onCreateJob is queued up.
    `int` | `sessionEstablished(SessionConfig config)` Caller must send a SessionStatusMessage to the client with the returned code.
    `void` | `setClientVersion(String version)` The client version.
    `(package private) void` | `setPayload(MessageId id, Payload payload)` Only call if _dontSendMSMOnReceive is false
    `(package private) void` | `setSessionId(Hash hash, SessionId id)` To be called only by ClientManager.
    `void` | `startRunning()` Actually run the connection - listen for I2CP messages and respond.
    `void` | `stopRunning()` Die a horrible death.
    `(package private) void` | `updateMessageDeliveryStatus(Destination dest, MessageId id, long messageNonce, int status)` Send a notification to the client that their message (id specified) was delivered (or failed delivery) Note that this sends the Guaranteed status codes, even though we only support best effort.
    `(package private) void` | `writeMessage(I2CPMessage msg)` Not thread-safe.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### _context

          protected final RouterContext _context

    - #### _log

          protected final Log _log

    - #### _manager

          protected final ClientManager _manager

    - #### _reader

          protected I2CPMessageReader _reader

      thingy that does stuff

  - ### Constructor Detail

    - #### ClientConnectionRunner

          public ClientConnectionRunner(RouterContext context,
                                        ClientManager manager,
                                        Socket socket)

      Create a new runner against the given socket

  - ### Method Detail

    - #### ackSendMessage

          void ackSendMessage(SessionId sid,
                              MessageId id,
                              long nonce)

      Send a notification to the client that their message (id specified) was accepted for delivery (but not necessarily delivered) Doesn't do anything if i2cp.messageReliability = "none" or if the nonce is 0.
      Parameters:
        `id` - OUR id for the message
        `nonce` - HIS id for the message

    - #### createListener

          protected I2CPMessageReader.I2CPMessageEventListener createListener()

      Allow override for testing

    - #### disconnectClient

          void disconnectClient(String reason)

      Send a DisconnectMessage and log with level Log.ERROR. This is always bad. See ClientMessageEventListener.handleCreateSession() for why we don't send a SessionStatusMessage when we do this.
      Parameters:
        `reason` - will be truncated to 255 bytes

    - #### disconnectClient

          void disconnectClient(String reason,
                                int logLevel)

      Parameters:
        `reason` - will be truncated to 255 bytes
        `logLevel` - e.g. Log.WARN

    - #### disconnected

          void disconnected()

    - #### distributeMessage

          MessageId distributeMessage(SendMessageMessage message)

      Distribute the message. If the dest is local, it blocks until its passed to the target ClientConnectionRunner (which then fires it into a MessageReceivedJob). If the dest is remote, it blocks until it is added into the ClientMessagePool

    - #### doSend

          void doSend(I2CPMessage msg)
               throws I2CPMessageException

      Actually send the I2CPMessage to the peer through the socket
      Throws:
        `I2CPMessageException`

    - #### failLeaseRequest

          public void failLeaseRequest(LeaseRequestState req)

      Parameters:
        `req` - non-null

    - #### getAddress

          public InetAddress getAddress()

    - #### getClientVersion

          public String getClientVersion()

      The client version.
      Returns:
        null if unknown or less than 0.8.7

    - #### getConfig

          public SessionConfig getConfig(Hash h)

      Current client's config, will be null if session not found IS subsession aware.

    - #### getConfig

          public SessionConfig getConfig(SessionId id)

      Current client's config, will be null if session not found IS subsession aware. Returns null if id is null.

    - #### getDestHash

          public Hash getDestHash()

      Equivalent to getConfig().getDestination().calculateHash(); will be null before session is established Not subsession aware. Returns primary session hash. Don't use if you can help it.
      Returns:
        primary hash or null if not yet set

    - #### getDestHash

          public Hash getDestHash(SessionId id)

      Return the hash for the given ID
      Returns:
        hash or null if unknown

    - #### getDestination

          public Destination getDestination(SessionId id)

      Return the dest for the given ID
      Returns:
        dest or null if unknown

    - #### getDestinations

          List<Destination> getDestinations()

      Subsession aware.
      Returns:
        all current client's destinations, non-null

    - #### getFloodfillNetworkDatabaseFacade

          public FloodfillNetworkDatabaseFacade getFloodfillNetworkDatabaseFacade()

      Get the FloodfillNetworkDatabaseFacade for this runner. This is the client netDb. If a session has not been created yet, it will return null.
      Returns:
        the client netdb or null if no session was created yet

    - #### getIsDead

          boolean getIsDead()

    - #### getLeaseRequest

          LeaseRequestState getLeaseRequest(Hash h)

      Data for the current leaseRequest, or null if there is no active leaseSet request. Not subsession aware. Returns primary ID only.

    - #### getLeaseSet

          public LeaseSet getLeaseSet(Hash h)

      Currently allocated leaseSet. IS subsession aware. Returns primary leaseset only.
      Returns:
        leaseSet or null if not yet set or unknown hash

    - #### getNextMessageId

          public int getNextMessageId()

    - #### getPayload

          Payload getPayload(MessageId id)

      Only call if _dontSendMSMOnReceive is false, otherwise will always be null

    - #### getPrimaryConfig

          public SessionConfig getPrimaryConfig()

      Primary client's config, will be null if session not set up

    - #### getSessionId

          SessionId getSessionId(Hash h)

      Subsession aware.
      Parameters:
        `h` - the local target
      Returns:
        current client's sessionId or null if not yet set or not a valid hash

    - #### getSessionIds

          List<SessionId> getSessionIds()

      Subsession aware.
      Returns:
        all current client's sessionIds, non-null

    - #### getSessionKeyManager

          public SessionKeyManager getSessionKeyManager()

      The current client's SessionKeyManager. As of 0.9.44, returned implementation varies based on supported encryption types.

    - #### isDead

          boolean isDead()

      already closed?

    - #### leaseSetCreated

          void leaseSetCreated(LeaseSet ls)

      called after a new leaseSet is granted by the client, the NetworkDb has been updated. This takes care of all the LeaseRequestState stuff (including firing any jobs)
      Parameters:
        `ls` - if encrypted, the encrypted LS, not the decrypted one

    - #### receiveMessage

          boolean receiveMessage(Destination toDest,
                                 Destination fromDest,
                                 Payload payload)

      Synchronously deliver the message to the current runner Failure indication is available as of 0.9.29. Fails on e.g. queue overflow to client, client dead, etc.
      Parameters:
        `toDest` - non-null
        `fromDest` - generally null when from remote, non-null if from local
      Returns:
        success

    - #### receiveMessage

          boolean receiveMessage(Hash toHash,
                                 Destination fromDest,
                                 Payload payload)

      Synchronously deliver the message to the current runner Failure indication is available as of 0.9.29. Fails on e.g. queue overflow to client, client dead, etc.
      Parameters:
        `toHash` - non-null
        `fromDest` - generally null when from remote, non-null if from local
      Returns:
        success

    - #### registerEncryptedLS

          public boolean registerEncryptedLS(Hash hash)

      Call after destinationEstablished(), when an encrypted leaseset is created, so we know it's local. Add to the clients list. Check for a dup hash. Caller must call runner.disconnectClient() on failure.
      Parameters:
        `hash` - the location of the encrypted LS, will change every day
      Returns:
        success, false on dup

    - #### removePayload

          void removePayload(MessageId id)

      Only call if _dontSendMSMOnReceive is false

    - #### removeSession

          void removeSession(SessionId id)

      Kill the session. Caller must kill runner if none left. If the session is primary and there are subsessions, this removes all subsessions also.

    - #### reportAbuse

          public void reportAbuse(Destination dest,
                                  String reason,
                                  int severity)

      Send async abuse message to the client

    - #### requestLeaseSet

          void requestLeaseSet(Hash h,
                               LeaseSet set,
                               long expirationTime,
                               Job onCreateJob,
                               Job onFailedJob)

      Request that a particular client authorize the Leases contained in the LeaseSet, after which the onCreateJob is queued up. If that doesn't occur within the timeout specified, queue up the onFailedJob. This call does not block. Job args are always null, may need some fixups if we start using them.
      Parameters:
        `h` - the Destination's hash
        `set` - LeaseSet with requested leases - this object must be updated to contain the signed version (as well as any changed/added/removed Leases) The LeaseSet contains Leases only, it is unsigned. Must be unique for this hash, do not reuse for subsessions.
        `expirationTime` - ms to wait before failing
        `onCreateJob` - Job to run after the LeaseSet is authorized, null OK
        `onFailedJob` - Job to run after the timeout passes without receiving authorization, null OK

    - #### sessionEstablished

          public int sessionEstablished(SessionConfig config)

      Caller must send a SessionStatusMessage to the client with the returned code. Caller must call disconnectClient() on failure. Side effect: Sets the session ID.
      Returns:
        SessionStatusMessage return code, 1 for success, != 1 for failure

    - #### setClientVersion

          public void setClientVersion(String version)

      The client version.

    - #### setPayload

          void setPayload(MessageId id,
                          Payload payload)

      Only call if _dontSendMSMOnReceive is false

    - #### setSessionId

          void setSessionId(Hash hash,
                            SessionId id)

      To be called only by ClientManager.
      Parameters:
        `hash` - for the session
      Throws:
        `IllegalStateException` - if already set

    - #### startRunning

          public void startRunning()
                            throws IOException

      Actually run the connection - listen for I2CP messages and respond. This is the main driver for this class, though it gets all its meat from the `I2CPMessageReader`
      Throws:
        `IOException`

    - #### stopRunning

          public void stopRunning()

      Die a horrible death. Cannot be restarted.

    - #### updateMessageDeliveryStatus

          void updateMessageDeliveryStatus(Destination dest,
                                           MessageId id,
                                           long messageNonce,
                                           int status)

      Send a notification to the client that their message (id specified) was delivered (or failed delivery) Note that this sends the Guaranteed status codes, even though we only support best effort. Doesn't do anything if i2cp.messageReliability = "none" Do not use for status = STATUS_SEND_ACCEPTED; use ackSendMessage() for that.
      Parameters:
        `dest` - the client
        `id` - the router's ID for this message
        `messageNonce` - the client's ID for this message, greater than zero
        `status` - see I2CP MessageStatusMessage for success/failure codes

    - #### writeMessage

          void writeMessage(I2CPMessage msg)

      Not thread-safe. Blocking. Only used for external sockets. ClientWriterRunner thread is the only caller. Others must use doSend().