net.i2p.i2ptunnel

## Class I2PTunnelClientBase

- java.lang.Object
- - net.i2p.util.EventDispatcherImpl
  - - net.i2p.i2ptunnel.I2PTunnelTask
    - - net.i2p.i2ptunnel.I2PTunnelClientBase

- All Implemented Interfaces:
    Runnable, EventDispatcher
  Direct Known Subclasses:
    I2Ping, I2PSOCKSTunnel, I2PTunnelClient, I2PTunnelDCCClient, I2PTunnelHTTPClientBase, I2PTunnelIRCClient

      public abstract class I2PTunnelClientBase
      extends I2PTunnelTask
      implements Runnable

  Abstract base class for I2P client tunnels with common functionality.

  Manages I2PSocketManager creation, local server socket setup, connection threading, and framework for shared and non-shared client tunnels. Handles SSL configuration, connection timeouts, and provides abstract methods for connection-specific implementations.

  Extended by specific tunnel types like HTTP clients, SOCKS proxies, and standard TCP tunnels.

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected long` | `_clientId`
    `protected I2PAppContext` | `_context`
    `protected Log` | `_log`
    `protected boolean` | `_ownDest`
    `(package private) static long` | `DEFAULT_CONNECT_TIMEOUT`
    `protected Destination` | `dest`
    `protected Logging` | `l`
    `protected boolean` | `listenerReady` Protected for I2Ping since 0.9.11.
    `protected List<I2PSocket>` | `mySockets`
    `static String` | `PROP_USE_SSL`
    `protected Object` | `sockLock`
    `protected I2PSocketManager` | `sockMgr`
    `protected ServerSocket` | `ss`

    - ### Fields inherited from class net.i2p.i2ptunnel.I2PTunnelTask

      `open, tunnel`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel)` The main constructor.
    `I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel, String pkf)` Use this to build a client with a persistent private key.
    `I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId)` This constructor is used to add a client to an existing socket manager.

  - ### Method Summary

    All Methods Static Methods Instance Methods Abstract Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected I2PSocketManager` | `buildSocketManager()` For NON-SHARED clients (ownDest = true).
    `protected static I2PSocketManager` | `buildSocketManager(I2PTunnel tunnel)` As of 0.9.20 this is fast, and does NOT connect the manager to the router.
    `protected static I2PSocketManager` | `buildSocketManager(I2PTunnel tunnel, String pkf)` As of 0.9.20 this is fast, and does NOT connect the manager to the router.
    `protected static I2PSocketManager` | `buildSocketManager(I2PTunnel tunnel, String pkf, Logging log)` As of 0.9.20 this is fast, and does NOT connect the manager to the router.
    `protected abstract void` | `clientConnectionRun(Socket s)` Manage a connection in a separate thread.
    `boolean` | `close(boolean forced)` Note that the tunnel can be reopened after this by calling startRunning().
    `static void` | `closeSocket(Socket s)`
    `I2PSocket` | `createI2PSocket(Destination dest)` Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.
    `I2PSocket` | `createI2PSocket(Destination dest, I2PSocketOptions opt)` Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.
    `I2PSocket` | `createI2PSocket(Destination dest, int port)` Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.
    `boolean` | `destroy()` Note that the tunnel cannot be reopened after this by calling startRunning(), as it will destroy the underlying socket manager.
    `protected I2PSocketOptions` | `getDefaultOptions()` Create the default options (using the default timeout, etc).
    `protected I2PSocketOptions` | `getDefaultOptions(Properties overrides)` Create the default options (using the default timeout, etc).
    `protected InetAddress` | `getListenHost(Logging l)`
    `int` | `getLocalPort()`
    `protected I2PSocketManager` | `getSocketManager()` This is ONLY for shared clients.
    `protected static I2PSocketManager` | `getSocketManager(I2PTunnel tunnel)` This is ONLY for shared clients.
    `protected static I2PSocketManager` | `getSocketManager(I2PTunnel tunnel, String pkf)` This is ONLY for shared clients.
    `protected static void` | `killSharedClient()` Kill the shared client, so that on restart in android we won't latch onto the old one
    `protected void` | `manageConnection(Socket s)` Manage the connection just opened on the specified socket
    `void` | `optionsUpdated(I2PTunnel tunnel)` Update the I2PSocketManager.
    `void` | `run()` Non-final since 0.9.11.
    `void` | `startRunning()` Actually open the local socket and start working on incoming connections.
    `protected void` | `verifySocketManager()` Create the manager if it doesn't exist, AND connect it to the router and build tunnels.

    - ### Methods inherited from class net.i2p.i2ptunnel.I2PTunnelTask

      `connected, disconnected, errorOccurred, getBooleanOption, getId, getTunnel, isOpen, reportAbuse, routerDisconnected, setId, setName, setTunnel, toString`

    - ### Methods inherited from class net.i2p.util.EventDispatcherImpl

      `attachEventDispatcher, detachEventDispatcher, getEventDispatcher, getEvents, getEventValue, ignoreEvents, notifyEvent, unIgnoreEvents, waitEventValue`

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

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

- - ### Field Detail

    - #### _clientId

          protected long _clientId

    - #### _context

          protected final I2PAppContext _context

    - #### _log

          protected final Log _log

    - #### _ownDest

          protected boolean _ownDest

    - #### DEFAULT_CONNECT_TIMEOUT

          static final long DEFAULT_CONNECT_TIMEOUT

      See Also:
        Constant Field Values

    - #### dest

          protected Destination dest

    - #### l

          protected final Logging l

    - #### listenerReady

          protected boolean listenerReady

      Protected for I2Ping since 0.9.11. Not for use outside package.

    - #### mySockets

          protected final List<I2PSocket> mySockets

    - #### PROP_USE_SSL

          public static final String PROP_USE_SSL

      See Also:
        Constant Field Values

    - #### sockLock

          protected final Object sockLock

    - #### sockMgr

          protected I2PSocketManager sockMgr

    - #### ss

          protected ServerSocket ss

  - ### Constructor Detail

    - #### I2PTunnelClientBase

          public I2PTunnelClientBase(int localPort,
                                     boolean ownDest,
                                     Logging l,
                                     EventDispatcher notifyThis,
                                     String handlerName,
                                     I2PTunnel tunnel)
                              throws IllegalArgumentException

      The main constructor.

      As of 0.9.21 this is fast, and does NOT connect the manager to the router, or open the local socket. You MUST call startRunning() for that.

      (0.9.20 claimed to be fast, but due to a bug it DID connect the manager to the router. It did NOT open the local socket however, so it was still necessary to call startRunning() for that.)

      Parameters:
        `localPort` - if 0, use any port, get actual port selected with getLocalPort()
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we can't create a socketManager

    - #### I2PTunnelClientBase

          public I2PTunnelClientBase(int localPort,
                                     boolean ownDest,
                                     Logging l,
                                     EventDispatcher notifyThis,
                                     String handlerName,
                                     I2PTunnel tunnel,
                                     String pkf)
                              throws IllegalArgumentException

      Use this to build a client with a persistent private key.

      As of 0.9.21 this is fast, and does NOT connect the manager to the router, or open the local socket. You MUST call startRunning() for that.

      (0.9.20 claimed to be fast, but due to a bug it DID connect the manager to the router. It did NOT open the local socket however, so it was still necessary to call startRunning() for that.)

      Parameters:
        `localPort` - if 0, use any port, get actual port selected with getLocalPort()
        `pkf` - Path to the private key file, or null to generate a transient key
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we can't create a socketManager

    - #### I2PTunnelClientBase

          public I2PTunnelClientBase(int localPort,
                                     Logging l,
                                     I2PSocketManager sktMgr,
                                     I2PTunnel tunnel,
                                     EventDispatcher notifyThis,
                                     long clientId)
                              throws IllegalArgumentException

      This constructor is used to add a client to an existing socket manager.

      As of 0.9.21 this does NOT open the local socket. You MUST call `startRunning()` for that. The local socket will be opened immediately (ignoring the `i2cp.delayOpen` option).

      Parameters:
        `localPort` - if 0, use any port, get actual port selected with getLocalPort()
        `sktMgr` - the existing socket manager
      Throws:
        `IllegalArgumentException`

  - ### Method Detail

    - #### buildSocketManager

          protected I2PSocketManager buildSocketManager()

      For NON-SHARED clients (ownDest = true). As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### buildSocketManager

          protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel)

      As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### buildSocketManager

          protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel,
                                                               String pkf)

      As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Parameters:
        `pkf` - absolute path or null
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### buildSocketManager

          protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel,
                                                               String pkf,
                                                               Logging log)

      As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Parameters:
        `pkf` - absolute path or null
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### clientConnectionRun

          protected abstract void clientConnectionRun(Socket s)

      Manage a connection in a separate thread. This only works if you do not override manageConnection(). This is run in a thread from an unlimited-size thread pool, so it may block or run indefinitely.

    - #### close

          public boolean close(boolean forced)

      Note that the tunnel can be reopened after this by calling startRunning(). This may not release all resources. In particular, the I2PSocketManager remains and it may have timer threads that continue running. To release all resources permanently, call destroy(). Does nothing if open is already false. Sets open = false but does not notifyAll().
      Specified by:
        `close` in class `I2PTunnelTask`
      Returns:
        success

    - #### closeSocket

          public static void closeSocket(Socket s)

    - #### createI2PSocket

          public I2PSocket createI2PSocket(Destination dest)
                                    throws I2PException,
                                           ConnectException,
                                           NoRouteToHostException,
                                           InterruptedIOException

      Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.
      Parameters:
        `dest` - The destination to connect to, non-null
      Returns:
        a new I2PSocket
      Throws:
        `I2PException`
        `ConnectException`
        `NoRouteToHostException`
        `InterruptedIOException`

    - #### createI2PSocket

          public I2PSocket createI2PSocket(Destination dest,
                                           I2PSocketOptions opt)
                                    throws I2PException,
                                           ConnectException,
                                           NoRouteToHostException,
                                           InterruptedIOException

      Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.
      Parameters:
        `dest` - The destination to connect to, non-null
        `opt` - Option to be used to open when opening the socket
      Returns:
        a new I2PSocket
      Throws:
        `ConnectException` - if the peer refuses the connection
        `NoRouteToHostException` - if the peer is not found or not reachable
        `InterruptedIOException` - if the connection timeouts
        `I2PException` - if there is some other I2P-related problem

    - #### createI2PSocket

          public I2PSocket createI2PSocket(Destination dest,
                                           int port)
                                    throws I2PException,
                                           ConnectException,
                                           NoRouteToHostException,
                                           InterruptedIOException

      Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.
      Parameters:
        `dest` - The destination to connect to, non-null
        `port` - The destination port to connect to 0 - 65535
      Returns:
        a new I2PSocket
      Throws:
        `I2PException`
        `ConnectException`
        `NoRouteToHostException`
        `InterruptedIOException`

    - #### destroy

          public boolean destroy()

      Note that the tunnel cannot be reopened after this by calling startRunning(), as it will destroy the underlying socket manager. This releases all resources if not a shared client. For shared client, the router will kill all the remaining streaming timers at shutdown.
      Overrides:
        `destroy` in class `I2PTunnelTask`
      Returns:
        success

    - #### getDefaultOptions

          protected I2PSocketOptions getDefaultOptions()

      Create the default options (using the default timeout, etc). Warning, this does not make a copy of I2PTunnel's client options, it modifies them directly.

    - #### getDefaultOptions

          protected I2PSocketOptions getDefaultOptions(Properties overrides)

      Create the default options (using the default timeout, etc). Warning, this does not make a copy of I2PTunnel's client options, it modifies them directly. Do not use overrides for per-socket options.

    - #### getListenHost

          protected final InetAddress getListenHost(Logging l)

    - #### getLocalPort

          public final int getLocalPort()

    - #### getSocketManager

          protected I2PSocketManager getSocketManager()

      This is ONLY for shared clients. As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### getSocketManager

          protected static I2PSocketManager getSocketManager(I2PTunnel tunnel)

      This is ONLY for shared clients. As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### getSocketManager

          protected static I2PSocketManager getSocketManager(I2PTunnel tunnel,
                                                             String pkf)

      This is ONLY for shared clients. As of 0.9.20 this is fast, and does NOT connect the manager to the router. Call verifySocketManager() for that.
      Returns:
        non-null
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager

    - #### killSharedClient

          protected static void killSharedClient()

      Kill the shared client, so that on restart in android we won't latch onto the old one

    - #### manageConnection

          protected void manageConnection(Socket s)

      Manage the connection just opened on the specified socket
      Parameters:
        `s` - Socket to take care of

    - #### optionsUpdated

          public void optionsUpdated(I2PTunnel tunnel)

      Update the I2PSocketManager.
      Overrides:
        `optionsUpdated` in class `I2PTunnelTask`

    - #### run

          public void run()

      Non-final since 0.9.11. open will be true before being called. Any overrides must set listenerReady = true and then notifyAll() if setup is successful, and must call close() and then notifyAll() on failure or termination.
      Specified by:
        `run` in interface `Runnable`

    - #### startRunning

          public void startRunning()

      Actually open the local socket and start working on incoming connections. *Must* be called by derived classes after initialization. (this wasn't actually true until 0.9.20) This will be fast if i2cp.delayOpen is true, but could take a LONG TIME if it is false, as it connects to the router and builds tunnels. Extending classes must check the value of boolean open after calling super.startRunning(), if false then something went wrong.

    - #### verifySocketManager

          protected void verifySocketManager()

      Create the manager if it doesn't exist, AND connect it to the router and build tunnels. Sets the this.sockMgr field if it is null, or if we want a new one. This may take a LONG time if building a new manager. We need a socket manager before getDefaultOptions() and most other things
      Throws:
        `IllegalArgumentException` - if the I2CP configuration is b0rked so badly that we cant create a socketManager