- All Implemented Interfaces:
Service
For each type of tunnel, it creates a chain of handlers, as follows:
Following tunnels are created by us:
Outbound Gateway > 0 hops:
PumpedTunnelGateway
BatchedRouterPreprocessor -> OutboundSender -> OutboundReceiver -> OutNetMessagePool
Outbound zero-hop Gateway+Endpoint:
TunnelGatewayZeroHop
OutboundMessageDistributor -> OutNetMessagePool
Inbound Endpoint > 0 hops:
TunnelParticipant
FragmentHandler -> InboundEndpointProcessor -> InboundMessageDistributor -> InNetMessagePool
Inbound zero-hop Gateway+Endpoint:
TunnelGatewayZeroHop
InboundMessageDistributor -> InNetMessagePool
Following tunnels are NOT created by us:
Participant (not gateway or endpoint)
TunnelParticipant
HopProcessor -> OutNetMessagePool
Outbound Endpoint > 0 hops:
OutboundTunnelEndpoint
FragmentHandler -> HopProcessor -> OutboundMessageDistributor -> OutNetMessagePool
Inbound Gateway > 0 hops:
ThrottledPumpedTunnelGateway
BatchedRouterPreprocessor -> InboundSender -> InboundGatewayReceiver -> OutNetMessagePool
Nested Class Summary
Modifier and TypeClassDescriptionprivate classJob removing hops from a tunnel.static enumLocation in the tunnel for RED (Random Early Discard) logic.private classPeriodic cleanup task to remove expired tunnels from all maps.Field Summary
FieldsModifier and TypeFieldDescriptionprivate final AtomicIntegerTotal bandwidth allocated for participating tunnels.Configs currently being removed - prevents duplicate removal calls.private final RouterContextThe router context.private final RateStatStat for messages we process as a tunnel participant.private final RateStatStat for messages we process as a tunnel endpoint.private final RateStatCached handles for the three per-transit-message counters reported bydispatch(TunnelDataMessage, Hash)anddispatch(TunnelGatewayMessage).private final AtomicLongTunnel expirations since the last stats log.private final ConcurrentHashMap<TunnelId, TunnelGateway> Map of inbound gateways (IBGW or zero-hop tunnels).private floatThrottle applied to inbound transit bandwidth.private final ObjectLock used when joining tunnels as participant, endpoint, or gateway.private final AtomicLongTunnel joins since the last stats log, a transit pool trend counter.private longTimestamp of the last expiration of a participating tunnel.private final TunnelDispatcher.LeaveTunnelJob to expire tunnels we are participating in.private final LogLogger for the tunnel dispatcher.private final ConcurrentHashMap<TunnelId, OutboundTunnelEndpoint> Map of outbound endpoints we joined.private final ConcurrentHashMap<TunnelId, TunnelGateway> Map of outbound gateways we created.private final ConcurrentHashMap<TunnelId, TunnelParticipant> Map of tunnel participants (either IBEP or middle hop).private final ConcurrentHashMap<TunnelId, HopConfig> Configurations for tunnels we are participating in but not creating.private final TunnelGatewayPumperPumper used to drive tunnel message processing.private final ConcurrentHashMap<TunnelId, Long> Recently expired tunnel IDs to suppress warnings.private floatCached transit throttle factors, refreshed byupdateThrottleFactors()on the cleanup timer.private static intTuner override for the per tunnel bandwidth divisor.private static floatTuned transit throttle factor, -1.0 = use router config.private BloomFilterIVValidatorValidator used for tunnel IVs.private static final longMax interval for cleanup when few tunnels.private static final longBase interval for periodic cleanup of expired tunnels.private static final intTunnel count thresholds for scaling cleanup interval.private static final intJob queue depth treated as medium stress.private static final longHigh for now, just to prevent long-lived-message attacks.private static final long[]Rate stat periods for the tunnel statistics.private static final longTime window (in ms) for suppressing warnings on recently expired tunnels.private static final longFudge factor for tunnel expiration check - simplifies complex calculation.Constructor Summary
ConstructorsConstructorDescriptionCreates a new instance of TunnelDispatcher.Method Summary
Modifier and TypeMethodDescriptionprivate voidRecords a tunnel id as recently expired.static voidadjustPumperThreads(int value) Change the thread count of the running pumper instance.(package private) intClean up expired tunnels from all dispatcher maps.private TunnelGateway.QueuePreprocessorCreate a preprocessor for an inbound tunnel gateway.private TunnelGateway.QueuePreprocessorCreate a preprocessor for an outbound tunnel gateway.voiddispatch(TunnelDataMessage msg, Hash recvFrom) Dispatch a TunnelDataMessage to the appropriate participant or endpoint.voidDispatch a TunnelGatewayMessage to the appropriate gateway.booleandispatchOutbound(I2NPMessage msg, TunnelId outboundTunnel, Hash targetPeer) Dispatch an outbound message through a tunnel.booleandispatchOutbound(I2NPMessage msg, TunnelId outboundTunnel, TunnelId targetTunnel, Hash targetPeer) Dispatch an outbound message through a tunnel.expiredConfigs(Collection<HopConfig> configs, long now) The queued configs whose expiration, plus the expiry fudge, has already passed.private voidfreeBandwidth(int bw) Free allocated bandwidth for a tunnel.intThe total bandwidth allocated for participating tunnels.private longThe cleanup interval scaled to the tunnel count.The tunnel IV validator, so the Tuner can retune its size.longReturns the timestamp of the last participating tunnel expiration.static intThe cap on messages a single inbound pump pass may handle.static intThe cap on messages a single outbound pump pass may handle.(package private) intThe max bandwidth per transit tunnel.A random receive tunnel ID that isn't a duplicate.A random receive tunnel ID that isn't a duplicate (zero hop).A random send tunnel ID that isn't a duplicate.intThe number of participating tunnels.static intThe per-tunnel bandwidth divisor in effect, tuned value if set elserouter.tunnel.perTunnelBweDivisorconfig, else the derived default of min(max tunnels, 100).static intThe cap on how many gateway pumper threads may run.static intThe capacity given to each gateway pumper's queue.static doubleThe pumper pool utilization as a ratio (0.0-1.0).static longThe delay before an idle gateway pumper is requeued.static intThe current bandwidth share in KBps.static floatgetTransitThrottleFactor(RouterContext ctx, float def) The transit throttle factor in effect, tuned value if set else config.booleanWhether an outbound gateway exists for the given TunnelId.private voidInitializes all stats tracked by this class.booleanWe are the inbound endpoint - we created this tunnel.booleanWe are the inbound gateway in this tunnel, and did not create it.booleanWe are the outbound gateway - we created this tunnel.booleanWe are the outbound endpoint in this tunnel, and did not create it.booleanjoinParticipant(HopConfig cfg) We are a participant in this tunnel, but not as the endpoint or gateway.The participating tunnels for console display.private voidPer-minute transit pool summary, so a transition from growth to decline is visible in the log trace without the stats graphing framework.private intSingle pass over the expiration queue that both recomputes_lastParticipatingExpirationand drops entries the maps no longer hold.(package private) static voidDeclare the rate stats emitted byFragmentHandleron the endpoint side.voidRemove a tunnel we're participating in.voidRemove a tunnel we created.voidrenderStatusHTML(Writer out) Required byService; status rendering moved to routerconsole.static voidresizePumperQueue(int value) Apply a new capacity to the running pumper instance's queue.voidrestart()Restart the TunnelDispatcher.static voidsetMaxIbMsgsPerPump(int val) The cap on messages a single inbound pump pass may handle.static voidsetMaxObMsgsPerPump(int val) The cap on messages a single outbound pump pass may handle.static voidsetPerTunnelBweDivisor(int div) Set the per-tunnel bandwidth divisor (called by Tuner).static voidsetPumperMaxThreads(int value) The cap on how many gateway pumper threads may run.static voidsetPumperQueueCapacity(int value) The capacity given to each gateway pumper's queue.static voidsetRequeueTime(long ms) The delay before an idle gateway pumper is requeued.static voidsetTransitThrottleFactor(float f) Set the transit throttle factor (called by Tuner).(package private) booleanshouldDropParticipatingInboundMessage(TunnelDispatcher.Location loc, int type, int length, SyntheticREDQueue bwe) Check if we should drop an inbound participating tunnel message.(package private) booleanshouldDropParticipatingMessage(TunnelDispatcher.Location loc, int type, int length, SyntheticREDQueue bwe) Implement RED (Random Early Discard) to enforce bandwidth limits.voidshutdown()Shut down TunnelDispatcher.voidstartup()Start up the TunnelDispatcher.private voidUpdate the last participating expiration to reflect the maximum expiration of all tunnels in the queue.voidupdateParticipatingStats(int ms) Update stats for participating tunnels.(package private) voidUpdate cached transit throttle factors from router properties.
Field Details
_context
The router context._log
Logger for the tunnel dispatcher._outboundGateways
Map of outbound gateways we created._outboundEndpoints
Map of outbound endpoints we joined._participants
Map of tunnel participants (either IBEP or middle hop)._inboundGateways
Map of inbound gateways (IBGW or zero-hop tunnels)._participatingConfig
Configurations for tunnels we are participating in but not creating._lastParticipatingExpiration
private volatile long _lastParticipatingExpirationTimestamp of the last expiration of a participating tunnel._transitThrottleFactor
private volatile float _transitThrottleFactorCached transit throttle factors, refreshed byupdateThrottleFactors()on the cleanup timer._inboundTransitThrottleFactor
private volatile float _inboundTransitThrottleFactorThrottle applied to inbound transit bandwidth._tunedTransitThrottleFactor
private static volatile float _tunedTransitThrottleFactorTuned transit throttle factor, -1.0 = use router config. Set by the Tuner when autotuningrouter.transitThrottleFactor._tunedPerTunnelBweDivisor
private static volatile int _tunedPerTunnelBweDivisorTuner override for the per tunnel bandwidth divisor._validator
Validator used for tunnel IVs._dispatchParticipantStat
Cached handles for the three per-transit-message counters reported bydispatch(TunnelDataMessage, Hash)anddispatch(TunnelGatewayMessage).These cannot be batched: N calls of
addRateData(name, 1)give a period total of N and an event count of N, and both are read —GraphListenerstores the count when total equals count, and the Tuner readsRate.getLastEventCount()directly. Batching would keep the plotted value right and drop the count to one per flush.What they do not need is the string-keyed map lookup and log-level check on every call. Resolved after
initializeStats()so the handles can only ever alias an already-registered stat._dispatchEndpointStat
Stat for messages we process as a tunnel participant.- See Also:
_dispatchInboundStat
Stat for messages we process as a tunnel endpoint.- See Also:
_leaveJob
Job to expire tunnels we are participating in._pumper
Pumper used to drive tunnel message processing._recentlyExpired
Recently expired tunnel IDs to suppress warnings.RECENT_EXPIRY_WINDOW_MS
private static final long RECENT_EXPIRY_WINDOW_MSTime window (in ms) for suppressing warnings on recently expired tunnels.- See Also:
CLEANUP_INTERVAL_MIN
private static final long CLEANUP_INTERVAL_MINBase interval for periodic cleanup of expired tunnels.- See Also:
CLEANUP_INTERVAL_MAX
private static final long CLEANUP_INTERVAL_MAXMax interval for cleanup when few tunnels.- See Also:
CLEANUP_THRESHOLD_HIGH
private static final int CLEANUP_THRESHOLD_HIGHTunnel count thresholds for scaling cleanup interval.- See Also:
CLEANUP_THRESHOLD_MED
private static final int CLEANUP_THRESHOLD_MEDJob queue depth treated as medium stress.- See Also:
TUNNEL_EXPIRY_FUDGE
private static final long TUNNEL_EXPIRY_FUDGEFudge factor for tunnel expiration check - simplifies complex calculation.- See Also:
_configsBeingRemoved
RATES
private static final long[] RATESRate stat periods for the tunnel statistics._joinParticipantLock
Lock used when joining tunnels as participant, endpoint, or gateway._allocatedBW
Total bandwidth allocated for participating tunnels.MAX_FUTURE_EXPIRATION
private static final long MAX_FUTURE_EXPIRATIONHigh for now, just to prevent long-lived-message attacks.- See Also:
_joinsSinceLast
Tunnel joins since the last stats log, a transit pool trend counter._expiresSinceLast
Tunnel expirations since the last stats log.
Constructor Details
TunnelDispatcher
Creates a new instance of TunnelDispatcher.- Parameters:
ctx- the router context
Method Details
hasOutboundGateway
Whether an outbound gateway exists for the given TunnelId. Lets callers avoid dispatching to a tunnel that is not ready yet.- Parameters:
tid- the tunnel ID- Returns:
- true if we currently have an outbound gateway for the given TunnelId.
setTransitThrottleFactor
public static void setTransitThrottleFactor(float f) Set the transit throttle factor (called by Tuner).- Parameters:
f- the transit throttle factor
getTransitThrottleFactor
The transit throttle factor in effect, tuned value if set else config.- Parameters:
ctx- the router contextdef- fallback when neither tuned nor configured (0.95f outbound, 0.0f inbound)- Returns:
- the transit throttle factor
setPerTunnelBweDivisor
public static void setPerTunnelBweDivisor(int div) Set the per-tunnel bandwidth divisor (called by Tuner).- Parameters:
div- the per-tunnel bandwidth divisor
getPerTunnelBweDivisor
The per-tunnel bandwidth divisor in effect, tuned value if set elserouter.tunnel.perTunnelBweDivisorconfig, else the derived default of min(max tunnels, 100).- Parameters:
ctx- the router context- Returns:
- the per-tunnel bandwidth divisor
getIVValidator
The tunnel IV validator, so the Tuner can retune its size. Null before setup and after shutdown.- Returns:
- the validator, or null
getCleanupInterval
private long getCleanupInterval()The cleanup interval scaled to the tunnel count. More tunnels = more frequent cleanup.- Returns:
- cleanup interval in milliseconds
logTransitSummary
private void logTransitSummary()Per-minute transit pool summary, so a transition from growth to decline is visible in the log trace without the stats graphing framework.cleanupExpiredTunnels
int cleanupExpiredTunnels()Clean up expired tunnels from all dispatcher maps. This is a defensive measure to remove tunnels that may have been orphaned due to race conditions or missed expirations.Package-visible for tests, so the sweep can be driven without waiting on the periodic timer.
- Returns:
- number of tunnels cleaned up
pruneExpirationQueue
private int pruneExpirationQueue()Single pass over the expiration queue that both recomputes_lastParticipatingExpirationand drops entries the maps no longer hold.Ordering is deliberate: the running maximum is folded in before the orphan test, so a pruned entry still contributes to the maximum and
remove(HopConfig)still compares against the same value it always did.- Returns:
- number of orphaned entries pruned
initializeStats
private void initializeStats()Initializes all stats tracked by this class.registerFragmentStats
Declare the rate stats emitted byFragmentHandleron the endpoint side. They must be declared as required:createRateStatis a no-op unlessstat.fullis set, and StatManager discardsaddRateDatafor an unregistered stat, so these failure and abuse signals would silently never appear in the default configuration.Package-visible and static so a unit test can assert the registration without standing up a whole router.
- Parameters:
sm- the stat manager to declare into
createPreprocessor
Create a preprocessor for an inbound tunnel gateway.- Parameters:
cfg- the hop configuration for the inbound gateway- Returns:
- a preprocessor batching the gateway's outbound sends
createPreprocessor
Create a preprocessor for an outbound tunnel gateway.- Parameters:
cfg- the tunnel creator configuration for the outbound gateway- Returns:
- a preprocessor batching the gateway's outbound sends
getLastParticipatingExpiration
public long getLastParticipatingExpiration()Returns the timestamp of the last participating tunnel expiration.- Returns:
- last expiration in milliseconds since epoch, or -1 if none
updateLastParticipatingExpiration
private void updateLastParticipatingExpiration()Update the last participating expiration to reflect the maximum expiration of all tunnels in the queue.joinOutbound
We are the outbound gateway - we created this tunnel.- Parameters:
cfg- config for the outbound tunnel we created- Returns:
- true if successful, false if tunnel ID is a duplicate
joinInbound
We are the inbound endpoint - we created this tunnel.- Parameters:
cfg- config for the inbound tunnel we created- Returns:
- true if successful, false if tunnel ID is a duplicate
joinParticipant
We are a participant in this tunnel, but not as the endpoint or gateway.- Parameters:
cfg- config for the tunnel we're joining as participant- Returns:
- true if successful, false if tunnel ID is a duplicate
joinOutboundEndpoint
We are the outbound endpoint in this tunnel, and did not create it.- Parameters:
cfg- config for the tunnel we're joining as outbound endpoint- Returns:
- true if successful, false if tunnel ID is a duplicate
joinInboundGateway
We are the inbound gateway in this tunnel, and did not create it.- Parameters:
cfg- config for the tunnel we're joining as inbound gateway- Returns:
- true if successful, false if tunnel ID is a duplicate
getAllocatedBW
public int getAllocatedBW()The total bandwidth allocated for participating tunnels.- Returns:
- the allocated b w
getParticipatingCount
public int getParticipatingCount()The number of participating tunnels.- Returns:
- the participating count
getNewOBGWID
A random send tunnel ID that isn't a duplicate.- Returns:
- the new o b g w i d
getNewIBEPID
A random receive tunnel ID that isn't a duplicate.- Returns:
- the new i b e p i d
getNewIBZeroHopID
A random receive tunnel ID that isn't a duplicate (zero hop).- Returns:
- the new i b zero hop i d
remove
Remove a tunnel we created.- Parameters:
cfg- the tunnel being dropped, whose direction picks the outbound gateway or inbound participant map it is removed from, and whose message and failure counts are recorded in the stats
remove
Remove a tunnel we're participating in.- Parameters:
cfg- the tunnel being dropped, identified by its receive tunnel; releases its allocated bandwidth, null is ignored, and a second removal of the same config is a no-op
addRecentlyExpired
Records a tunnel id as recently expired.- Parameters:
id- the tunnel that expired
freeBandwidth
private void freeBandwidth(int bw) Free allocated bandwidth for a tunnel.Only remove() may decrement this counter. A second decrement path let IdleTunnelMonitor double-free and drift the transit total negative.
- Parameters:
bw- the bandwidth in bytes to release; zero or negative is ignored
dispatch
Dispatch a TunnelDataMessage to the appropriate participant or endpoint.- Parameters:
msg- transit message to deliver, routed by its tunnel IDrecvFrom- hash of the peer that sent it, recorded in the dispatch log and passed on for profile accounting
dispatch
Dispatch a TunnelGatewayMessage to the appropriate gateway.- Parameters:
msg- gateway message wrapping the I2NP message to forward; both its own and the wrapped expiration must fall within -CLOCK_FUDGE_FACTOR and +MAX_FUTURE_EXPIRATION of now
dispatchOutbound
Dispatch an outbound message through a tunnel.- Parameters:
msg- message to send; an already expired one is dropped, and a short expiration is extended to at least 20s for transitoutboundTunnel- send tunnel to hand the message to, which must exist or the message is droppedtargetPeer- hash of the eventual destination, passed to the gateway for per-peer limits and message history- Returns:
- true if the message was accepted by the tunnel gateway, false if dropped
dispatchOutbound
public boolean dispatchOutbound(I2NPMessage msg, TunnelId outboundTunnel, TunnelId targetTunnel, Hash targetPeer) Dispatch an outbound message through a tunnel.- Parameters:
msg- message to send; an already expired one is dropped, and a short expiration is extended to at least 20s for transitoutboundTunnel- send tunnel to hand the message to, which must exist or the message is droppedtargetTunnel- tunnel of a target that is itself reachable, or null for an ordinary peer destination; a non-null value also marks the dispatch as tunnel-targeted in the statstargetPeer- hash of the eventual destination, passed to the gateway for per-peer limits and message history- Returns:
- true if the message was accepted by the tunnel gateway, false if dropped
listParticipatingTunnels
updateParticipatingStats
public void updateParticipatingStats(int ms) Update stats for participating tunnels.- Parameters:
ms- length in ms of the coalescing interval the counters cover; also the averaging period applied to the message rates, so the per-tunnel average is scaled to a 10 minute figure
updateThrottleFactors
void updateThrottleFactors()Update cached transit throttle factors from router properties.shouldDropParticipatingMessage
boolean shouldDropParticipatingMessage(TunnelDispatcher.Location loc, int type, int length, SyntheticREDQueue bwe) Implement RED (Random Early Discard) to enforce bandwidth limits. Only active when queue size > minThreshold (congestion). When queue > maxThreshold, ALL messages are dropped (regardless of factor).- Parameters:
loc- role of the sender in the tunnel, used for logging onlytype- message type, used for logging onlylength- message size in bytes; 0 or less is never droppedbwe- per-tunnel estimator consulted before the global limit, may be null to skip the per-tunnel check- Returns:
- true to drop, false to accept
shouldDropParticipatingInboundMessage
boolean shouldDropParticipatingInboundMessage(TunnelDispatcher.Location loc, int type, int length, SyntheticREDQueue bwe) Check if we should drop an inbound participating tunnel message. Implements symmetric throttling: both inbound and outbound transit traffic should be throttled equally to prevent inbound traffic from overwhelming outbound capacity.- Parameters:
loc- location in tunnel (IBGP, PARTICIPANT, OBEP)type- I2NP message type, reported in the drop log onlylength- message size in bytesbwe- per-tunnel bandwidth estimator (may be null)- Returns:
- true to drop, false to accept
getMaxPerTunnelBandwidth
The max bandwidth per transit tunnel. Scales with allocation: higher share = higher per-tunnel cap. Uses outbound bandwidth only. On floodfill routers inbound is far smaller than outbound and would create an artificial bottleneck.- Parameters:
loc- role in the tunnel, currently unused; the cap depends only on the outbound rate and our share percentage- Returns:
- cap in bytes per second, floored at 10KB (30KB or 50KB for the larger allocation tiers) once the computed value exceeds 256KB
startup
shutdown
restart
renderStatusHTML
Required byService; status rendering moved to routerconsole.- Specified by:
renderStatusHTMLin interfaceService- Parameters:
out- the writer to write to- Throws:
IOException- if an error occurs writing
expiredConfigs
The queued configs whose expiration, plus the expiry fudge, has already passed.The whole queue is scanned. It is filled in join order, so an entry that is still live can sit in front of entries that expired long ago; stopping at the first live entry left those behind, holding a tunnel ID and transit bandwidth until the head itself expired.
- Parameters:
configs- the queued participating tunnelsnow- current time, already allowing for the clock fudge- Returns:
- the expired configs, in queue order; an empty list if none
getRequeueTime
public static long getRequeueTime()The delay before an idle gateway pumper is requeued.- Returns:
- the requeue delay in ms
setRequeueTime
public static void setRequeueTime(long ms) The delay before an idle gateway pumper is requeued.- Parameters:
ms- delay in ms, clamped to [10, 200]
getMaxObMsgsPerPump
public static int getMaxObMsgsPerPump()The cap on messages a single outbound pump pass may handle.- Returns:
- the max outbound messages per pump
getPumperQueueCapacity
public static int getPumperQueueCapacity()The capacity given to each gateway pumper's queue.- Returns:
- the per-pumper queue capacity
setPumperQueueCapacity
public static void setPumperQueueCapacity(int value) The capacity given to each gateway pumper's queue.- Parameters:
value- capacity, clamped to [64, 4096]; takes effect on the next pumper, existing queues are untouched
resizePumperQueue
public static void resizePumperQueue(int value) Apply a new capacity to the running pumper instance's queue.- Parameters:
value- capacity to resize to
getPumperMaxThreads
public static int getPumperMaxThreads()The cap on how many gateway pumper threads may run.- Returns:
- the max pumper threads
getPumperUtilization
public static double getPumperUtilization()The pumper pool utilization as a ratio (0.0-1.0). Returns NaN if not started.- Returns:
- the pumper utilization
setPumperMaxThreads
public static void setPumperMaxThreads(int value) The cap on how many gateway pumper threads may run.- Parameters:
value- thread count, clamped to [2, 16]
adjustPumperThreads
public static void adjustPumperThreads(int value) Change the thread count of the running pumper instance.- Parameters:
value- desired thread count, applied to the live instance
setMaxObMsgsPerPump
public static void setMaxObMsgsPerPump(int val) The cap on messages a single outbound pump pass may handle.- Parameters:
val- messages per pump, clamped to [8, 1024]
getMaxIbMsgsPerPump
public static int getMaxIbMsgsPerPump()The cap on messages a single inbound pump pass may handle.- Returns:
- the max inbound messages per pump
setMaxIbMsgsPerPump
public static void setMaxIbMsgsPerPump(int val) The cap on messages a single inbound pump pass may handle.- Parameters:
val- messages per pump, clamped to [8, 1024]