java.lang.Object
net.i2p.util.EventDispatcherImpl
net.i2p.i2ptunnel.I2PTunnelTask
net.i2p.i2ptunnel.I2PTunnelClientBase
net.i2p.i2ptunnel.I2PTunnelIRCClient
- All Implemented Interfaces:
Runnable, EventDispatcher
IRC client tunnel with DCC support and filtering.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate classRewrites DCC lines between the local client and I2P.Field Summary
Modifier and TypeFieldDescriptionprivate final List<I2PSocketAddress> List of Destination objects that we point at.private DCCClientManagerOpens outbound DCC connections, if any.private final booleanWhether DCC connections are supported.private I2PTunnelDCCServerServes inbound DCC connections, if any.private static final longHow long a read may wait before the connection is dropped, 10 min; the application should time out its ping before this.(package private) static final intMaximum number of I2P connect attempts per client connection: the initial try plus three exponential-backoff retries.(package private) static final longBackoff floor (ms) for I2P connect retries, doubling per attempt.static final StringClient option key enabling the DCC file transfer manager.protected longRead timeout in milliseconds applied to each client socket, adjustable with setReadTimeout() after the tunnel is built.Fields inherited from class I2PTunnelClientBase
_clientId, _context, _executor, _log, _ownDest, DEFAULT_CONNECT_TIMEOUT, DEFAULT_MAX_CONNECTIONS, DEFAULT_SOCKET_OPEN_TIMEOUT, dest, l, listenerReady, MAX_TIMEOUT_FAILOVER, MIN_CONNECT_LEG_MS, mySockets, NO_DEADLINE, POOL_BUILD_DEADLINE_GRACE_MS, PROP_MAX_CONNECTIONS, PROP_USE_SSL, REQUEST_CONNECT_DEADLINE_MS, sockLock, sockMgr, ssModifier and TypeFieldDescriptionprotected longThis client's ID.protected final I2PAppContextThe application context.protected ThreadPoolExecutorThread pool executor.protected final LogThe logger.protected booleanWhether we own our destination.(package private) static final longDefault connect timeout.static final intDefault cap on concurrently handled client connections.static final longDefault socket open timeout in ms, after whichI2PTunnelClientBase.close(boolean)will proceed even with active sockets.protected DestinationThe destination.protected final LoggingThe logging instance.protected booleanProtected for I2Ping since 0.9.11.(package private) static final intLegacy cap on consecutive connect timeouts before abandoning tunnel failover.(package private) static final longMinimum remaining budget for starting one connect leg.List of active sockets.(package private) static final longDeadline sentinel for callers that have not adopted the shared request budget (SOCKS, IRC, DCC, rawcreateI2PSocket): they keep their original per-call limits because this sentinel never reads as expired and never clamps.(package private) static final longOne-shot deadline extension granted while the outbound tunnel pool is still building (poolState() == 0) when the shared budget runs out.static final StringProperty name: max concurrently active client connections handled by one client tunnel.static final StringProperty turning on SSL between the proxy and the client.(package private) static final longSingle wall-clock budget for establishing one proxied request.protected final ObjectGuards sockMgr and mySockets.protected I2PSocketManagerThe socket manager.protected ServerSocketServer socket.Constructor Summary
ConstructorsConstructorDescriptionI2PTunnelIRCClient(int localPort, String destinations, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) Create an IRC client on the given local port.Method Summary
Modifier and TypeMethodDescriptionprivate voidbuildAddresses(String destinations) Parse the destination list from config.protected voidRelays a new local connection to a configured IRC destination, retrying failures.booleanclose(boolean forced) Unregisters the IRC port mapping, then closes the DCC server and client.(package private) static intdestinationIndexForAttempt(int attempt, int size, int base) Destination-list index for connect attemptattemptwhen rotating round-robin:base + attempt mod size.(package private) static longgetConnectRetryDelayMs(int attempt) Exponential backoff delay (ms) to sleep before the given connect retry.(package private) static booleanWhether a connect failure is transient enough to warrant another attempt.voidoptionsUpdated(I2PTunnel tunnel) Update the dests then call super.private I2PSocketAddresspickDestination(int base, int attempt) Pick the destination to try for attemptattempt, rotating round-robin through all configured targets from a per-connection random start (base).private booleanretryDelay(int failures) Sleep through the exponential backoff preceding a retry, failing fast when the tunnel is being shut down mid-delay.private booleanshouldRetry(int failures, Throwable t) Instance gate for the clientConnectionRun retry loop: applies the static budget, dead-pool and failure-classification rules with the current pool state (I2PTunnelClientBase.poolState()).(package private) static booleanshouldRetryConnect(int failures, int maxAttempts, int poolState, Throwable last) Whether a connect attempt should be retried afterfailuresfailed attempts.voidRegisters the IRC port with the port mapper when the tunnel is open.Methods inherited from class I2PTunnelClientBase
buildSocketManager, buildSocketManager, buildSocketManager, buildSocketManager, clampToDeadlineMs, closeSocket, connectDeadlineFrom, createI2PSocket, createI2PSocket, createI2PSocket, createI2PSocket, destroy, extendDeadlineForBuildingPool, getDefaultOptions, getDefaultOptions, getEffectiveMaxConnections, getListenHost, getLocalPort, getSocketManager, getSocketManager, getSocketOpenTimeout, isConnectTimeout, isDeadlineExpired, legConnectTimeoutMs, manageConnection, poolIsDefinitivelyDown, poolState, resolveEffectiveMaxConnections, resolveMaxConnections, resolveRunnerCeiling, run, shouldContinueFailover, shouldContinueFailover, shouldOuterRetryConnect, shouldOuterRetryConnect, verifySocketManager, writeShedResponseModifier and TypeMethodDescriptionprotected I2PSocketManagerFor NON-SHARED clients (ownDest = true).protected static I2PSocketManagerbuildSocketManager(I2PTunnel tunnel) Create a disconnected socket manager for the tunnel, with no private key file.protected static I2PSocketManagerbuildSocketManager(I2PTunnel tunnel, String pkf) Create a disconnected socket manager for the tunnel, loading the persistent client dest from pkf if it is non-null.protected static I2PSocketManagerbuildSocketManager(I2PTunnel tunnel, String pkf, Logging log) Create a disconnected socket manager for the tunnel, loading the persistent client dest from pkf if it is non-null, and logging any key file error to log.(package private) static longclampToDeadlineMs(long requestedMs, long deadlineMs, long nowMs) Clamp a requested timeout to the time left before a shared deadline.static voidClose a socket silently.(package private) static longconnectDeadlineFrom(long nowMs) Compute the shared connect deadline for a request starting now.createI2PSocket(Destination dest) Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.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.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.(package private) I2PSocketcreateI2PSocket(Destination dest, I2PSocketOptions opt, long deadlineMs) Create a new I2PSocket bounded by a shared request deadline.booleandestroy()Note that the tunnel cannot be reopened after this by calling startRunning(), as it will destroy the underlying socket manager.(package private) static longextendDeadlineForBuildingPool(long deadlineMs, long nowMs, int poolState, boolean alreadyExtended) One-shot deadline extension for a request whose outbound tunnel pool is still building when the shared deadline runs out.protected I2PSocketOptionsCreate the default options (using the default timeout, etc).protected I2PSocketOptionsgetDefaultOptions(Properties overrides) Create the default options (using the default timeout, etc).(package private) intThe effective concurrent-connection cap for this tunnel at the moment the accept loop admits a connection.protected final InetAddressGet the listen host address.final intGet the local port.Returns the I2PSocketManager for this task.protected static I2PSocketManagergetSocketManager(I2PTunnel tunnel, String pkf) This is ONLY for shared clients.longReturns the socket open timeout in ms; close() will proceed after this even with active sockets.(package private) static booleanFor timeout wording.(package private) static booleanisDeadlineExpired(long deadlineMs, long nowMs) Whether a shared connect deadline has passed.(package private) static longlegConnectTimeoutMs(long requestedMs, long deadlineMs, long nowMs) Compute the connect timeout to apply to one failover leg under a shared deadline.protected voidManage the connection just opened on the specified socket.protected booleanAnd none are being built, so further connect retries cannot succeed.protected intRouter-context only, best-effort check of the client outbound tunnel pool.(package private) static intresolveEffectiveMaxConnections(boolean customized, int ownCap, int globalDefault) Pure decision helper forI2PTunnelClientBase.getEffectiveMaxConnections(): pick the per-tunnel override when one was explicitly configured, otherwise the Tuner-managed default cap.(package private) static intresolveMaxConnections(String configured) Resolve the max-concurrent-connections cap from the tunnel's configured value.(package private) static intresolveRunnerCeiling(boolean customized, int effectiveMax) Ceiling to pin on this tunnel's runner pool at creation time.voidrun()Non-final since 0.9.11.(package private) static booleanshouldContinueFailover(int tunnelCount, int attemptsMade, int timeoutFailures, boolean poolDown) Whether another tunnel-failover attempt is worthwhile after a connect failure.(package private) static booleanshouldContinueFailover(int tunnelCount, int attemptsMade, int timeoutFailures, boolean poolDown, boolean poolBuilding) Whether another tunnel-failover attempt is worthwhile after a connect failure.(package private) static booleanshouldOuterRetryConnect(int connectAttempts, int timeoutConnectAttempts, boolean timedOut, boolean poolDown, boolean poolBuilding, boolean browserClosed) Whether the outer HTTP connect loop should retry after a failure.(package private) static booleanshouldOuterRetryConnect(int connectAttempts, int timeoutConnectAttempts, boolean timedOut, int poolState, boolean deadlineExpired) Whether the outer HTTP connect loop should retry after a failure, given the single pool-state snapshot taken for that failure.protected voidCreate the manager if it doesn't exist, AND connect it to the router and build tunnels.protected voidBest-effort shed response on the browser-facing socket, then close it.Methods inherited from class I2PTunnelTask
connected, disconnected, errorOccurred, getBooleanOption, getId, getTunnel, isOpen, reportAbuse, routerDisconnected, setId, setName, setTunnel, toStringModifier and TypeMethodDescriptionvoidconnected(I2PSession session) For tasks that don't callI2PTunnel.addSession(I2PSession)directly.voiddisconnected(I2PSession session) Called when a session is disconnected.voiderrorOccurred(I2PSession session, String message, Throwable error) Does nothing here.protected booleangetBooleanOption(String opt, boolean dflt) Read a boolean client option from the tunnel's properties.intgetId()The id of the client list entry for this task.The I2PTunnel this task runs inside.booleanisOpen()Whether the tunnel is running and accepting connections.voidreportAbuse(I2PSession session, int severity) Does nothing here.protected voidTell the tunnel that the router connection has dropped.voidsetId(int id) Record the client list entry id for this task.protected voidRecord the display name for this task.voidRebind this task to a different tunnel.toString()The display name given to this task when it was constructed.Methods inherited from class EventDispatcherImpl
attachEventDispatcher, detachEventDispatcher, getEventDispatcher, getEvents, getEventValue, ignoreEvents, notifyEvent, unIgnoreEvents, waitEventValueModifier and TypeMethodDescriptionvoidAttach an EventDispatcher object to the events dispatching chain.voidDetach the specified EventDispatcher object from the events dispatching chain.Object to be used to deliver events (usuallythis, but YMMV).Retrieve the names of all the events that have been received.getEventValue(String name) Retrieve the value currently associated with the specified event value.voidIgnore further event notifications.voidnotifyEvent(String eventName, Object args) Deliver an event.voidAlmost like the method above :-).waitEventValue(String name) Wait until the given event has received a value.
Field Details
_addrs
List of Destination objects that we point at.DEFAULT_READ_TIMEOUT
private static final long DEFAULT_READ_TIMEOUTHow long a read may wait before the connection is dropped, 10 min; the application should time out its ping before this.- See Also:
readTimeout
protected long readTimeoutRead timeout in milliseconds applied to each client socket, adjustable with setReadTimeout() after the tunnel is built._dccEnabled
private final boolean _dccEnabledWhether DCC connections are supported._DCCServer
Serves inbound DCC connections, if any._DCCClientManager
Opens outbound DCC connections, if any.PROP_DCC
Client option key enabling the DCC file transfer manager.- See Also:
IRC_CONNECT_MAX_ATTEMPTS
static final int IRC_CONNECT_MAX_ATTEMPTSMaximum number of I2P connect attempts per client connection: the initial try plus three exponential-backoff retries. Once the budget is exhausted the tunnel gives up and sends the 499 error reply.- See Also:
IRC_CONNECT_RETRY_BASE_DELAY
static final long IRC_CONNECT_RETRY_BASE_DELAYBackoff floor (ms) for I2P connect retries, doubling per attempt.- See Also:
Constructor Details
I2PTunnelIRCClient
public I2PTunnelIRCClient(int localPort, String destinations, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) throws IllegalArgumentException Create an IRC client on the given local port.Since 0.9.20 this is fast, and does NOT connect the manager to the router, or open the local socket. You MUST call
startRunning()for that.- Parameters:
localPort- if 0, use any port, get actual port selected with getLocalPort()destinations- peers we target, comma- or space-separated. Since 0.9.9, each dest may be appended with :portl- the logging instanceownDest- whether to use an owned destinationnotifyThis- the event dispatcher for notificationstunnel- the I2PTunnel instancepkf- path to the private key file, or null to generate a transient key- Throws:
IllegalArgumentException- if the I2PTunnel does not contain valid config to contact the router
Method Details
buildAddresses
Parse the destination list from config.- Parameters:
destinations- comma-separated destination list, null for none
clientConnectionRun
Relays a new local connection to a configured IRC destination, retrying failures.- Specified by:
clientConnectionRunin classI2PTunnelClientBase- Parameters:
s- the socket to manage
getConnectRetryDelayMs
static long getConnectRetryDelayMs(int attempt) Exponential backoff delay (ms) to sleep before the given connect retry. The first retry waitsIRC_CONNECT_RETRY_BASE_DELAY(1s), doubling per attempt up to a hard cap of 8s. During a tunnel-pool stall the cap lets the pool recover instead of hammering it, and the loop still fails fast onceI2PTunnelClientBase.poolState()reports a provably dead pool. Pure decision - no context access, safe for unit tests.- Parameters:
attempt- the 1-based connect failure count (how many failures so far)- Returns:
- delay in ms: 0 for attempt <= 0, else 1000 << (attempt-1) bounded to 8000
shouldRetryConnect
Whether a connect attempt should be retried afterfailuresfailed attempts. Three independent conditions must all hold:- the attempt budget is not exhausted (
failures < maxAttempts), - the client outbound pool is not provably dead (
poolState != -1; a-2"unknown" result from standalone clients does NOT fail fast, matchingshouldStopEmptyReconnect()), - the failure is retryable per
isRetryableConnectFailure(Throwable).
- Parameters:
failures- the 1-based number of failed attempts so farmaxAttempts- the total attempt budget, 1-basedpoolState- theI2PTunnelClientBase.poolState()value from the last failed attemptlast- the throwable from the last failed attempt- Returns:
- true if another attempt should be scheduled
- the attempt budget is not exhausted (
isRetryableConnectFailure
Whether a connect failure is transient enough to warrant another attempt.- Not retryable:
ConnectException(an explicit refusal is a hard answer from the peer that a new attempt cannot change), anInterruptedIOException(local cancellation - the tunnel is closing), ornull. - Retryable: everything else -
NoRouteToHostExceptionconnect timeouts,UnknownHostExceptionfor a b32 destination whose LeaseSet may become available by the next attempt,I2PExceptiontunnel build failures (incl.TooManyStreamsException), and generic I/O errors.
- Parameters:
t- the throwable from the failed connect- Returns:
- true if a retry is worthwhile
- Not retryable:
shouldRetry
Instance gate for the clientConnectionRun retry loop: applies the static budget, dead-pool and failure-classification rules with the current pool state (I2PTunnelClientBase.poolState()).- Parameters:
failures- the 1-based number of failed attempts so fart- the throwable from the last failed attempt- Returns:
- true if another connect attempt should be scheduled
retryDelay
private boolean retryDelay(int failures) Sleep through the exponential backoff preceding a retry, failing fast when the tunnel is being shut down mid-delay.- Parameters:
failures- the 1-based number of failed attempts so far- Returns:
- true if the delay elapsed, false if the thread was interrupted
pickDestination
Pick the destination to try for attemptattempt, rotating round-robin through all configured targets from a per-connection random start (base). Reverses the historical behavior of retrying the same randomly-chosen target repeatedly, which wasted the whole retry budget on one dead destination while the alternate targets went untried.- Parameters:
base- per-connection random start index, in [0, size)attempt- 0-based attempt number within this connection- Returns:
- the address to try, or null if no targets are configured
destinationIndexForAttempt
static int destinationIndexForAttempt(int attempt, int size, int base) Destination-list index for connect attemptattemptwhen rotating round-robin:base + attempt mod size. Attempt 0 uses the per-connection random start. Each later attempt advances one slot, so consecutive attempts always hit different targets (for size > 1). Pure decision - no context access, safe for unit tests.- Parameters:
attempt- 0-based attempt number within this connectionsize- number of configured destinationsbase- per-connection random start index, in [0, size)- Returns:
- index into the destination list, in [0, size), or 0 for size <= 1
optionsUpdated
Update the dests then call super.- Overrides:
optionsUpdatedin classI2PTunnelClientBase- Parameters:
tunnel- the tunnel whose client options were updated
startRunning
public void startRunning()Registers the IRC port with the port mapper when the tunnel is open.- Overrides:
startRunningin classI2PTunnelClientBase
close
public boolean close(boolean forced) Unregisters the IRC port mapping, then closes the DCC server and client.- Overrides:
closein classI2PTunnelClientBase- Parameters:
forced- true to interrupt an in-progress build, false to close gracefully- Returns:
- true if the tunnel is closed, or false if connections were still active and the close was refused