java.lang.Object
net.i2p.router.tunnel.TunnelCreatorConfig
All Implemented Interfaces:
TunnelInfo
Direct Known Subclasses:
PooledTunnelCreatorConfig

public abstract class TunnelCreatorConfigextends Object implements TunnelInfo
Coordinate the info that the tunnel creator keeps track of, including what peers are in the tunnel and what their configuration is

See PooledTunnelCreatorConfig for the non-abstract class.

  • Field Details

    • _context

      protected final RouterContext _context
      The router context.
    • _destination

      private final Hash _destination
      Only necessary for client tunnels.
    • _config

      private final HopConfig[] _config
      Gateway first.
    • _peers

      private final Hash[] _peers
      Gateway first.
    • _expiration

      private volatile long _expiration
      When the tunnel expires.
    • _order

      private List<Integer> _order
      The hop order of the tunnel.
    • _replyMessageId

      private long _replyMessageId
      Message id the build reply arrives on.
    • _isInbound

      private final boolean _isInbound
      True for an inbound tunnel.
    • _messagesProcessed

      private final AtomicInteger _messagesProcessed
      Messages processed on the tunnel.
    • _verifiedBytesTransferred

      private final LongAdder _verifiedBytesTransferred
      Total verified bytes on this tunnel. A LongAdder so the per-fragment delivery path can add without the tunnel monitor; a stale-by-one-add read of a monotonic counter is as good as synchronized.
    • _lastTransferredTime

      private volatile long _lastTransferredTime
      Wall clock (ms) of the last production byte, volatile for the same reason as _verifiedBytesTransferred.
    • _preConnectWindowStart

      private long _preConnectWindowStart
      Start of the current pre-connect retry window, 0 until the first retry. Guarded by this along with _preConnectRetries.
    • _preConnectRetries

      private int _preConnectRetries
      Pre-connect retries already spent in the current window.
    • _creationTime

      private final long _creationTime
      Wall-clock time this config was created, i.e. when its build started. Lets the test cycle give a freshly built tunnel a grace period before its results count against it. A tunnel cannot fairly be judged on a round trip it had no realistic chance to complete. Deliberately not on TunnelInfo: the test cycle is the only reader, and adding a method to a public interface for one caller would break out-of-tree implementors.
    • _failures

      private final AtomicInteger _failures
      Hard failures counted on the tunnel.
    • _softFailures

      private final AtomicInteger _softFailures
      Soft failures counted on the tunnel.
    • _lastSoftFailure

      private volatile long _lastSoftFailure
      Wall-clock time of the most recent soft best-effort timeout, 0 if none. With SOFT_FAILURE_WINDOW_MS this bounds the soft streak at read time: a failure older than the window decays out of the count, so a tunnel that times out once in a while forever is never degraded or rotated out, while a genuine burst still reaches the degraded and removal bars.
    • _firstHopSendFailures

      private final AtomicInteger _firstHopSendFailures
      Raw count of spaced first-hop send failures. Decay and spacing are applied at read time, see recordFirstHopSendFailure().
    • _lastFirstHopSendFailure

      private volatile long _lastFirstHopSendFailure
      Wall-clock time of the most recent counted first-hop send failure, 0 if none. Only stamped when the count actually advances, so a burst cannot keep pushing the spacing deadline forward and never reach the threshold.
    • _firstHopFailed

      private volatile boolean _firstHopFailed
      One-shot escalation latch: once the streak reached FIRST_HOP_FAILURE_THRESHOLD the caller is told exactly once. The send-failure job is shared by every message on the tunnel and is only deduped while queued, so without this a single burst would call tunnelFailedFirstHop() for each failed message.
    • _testStatus

      private volatile TunnelTestStatus _testStatus
      Current test status of the tunnel.
    • _reused

      private volatile boolean _reused
      True if the tunnel was reused for another pool.
    • _priority

      private volatile int _priority
      Priority of the tunnel for bandwidth and builds.
    • _localHopSessionEstablished

      private volatile boolean _localHopSessionEstablished
      Whether a transport session to our local hop existed when this tunnel entered the pool. Recorded once at build time by the pool, then read-only.

      See TunnelInfo.hadLocalHopSession() for why the pool needs the build-time fact rather than the current session state.

    • _localHopMissingSince

      private volatile long _localHopMissingSince
      When the local transport session was first seen missing. Zero when the session is present, which is also the state for a tunnel that never lost it.
    • _peakThroughputCurrentTotal

      private final LongAdder _peakThroughputCurrentTotal
      Bytes verified on this tunnel since the last per-peer profile update. A LongAdder because it is bumped once per 1KB fragment and does not need the monitor guarding _peakThroughputLastCoallesce.
    • _peakThroughputLastCoallesce

      private volatile long _peakThroughputLastCoallesce
      Wall clock (ms) of the last per-peer profile update. Written under the tunnel monitor by coalescePeakThroughput(long) but read without it, so that the per-fragment path can skip the monitor, hence volatile.
    • _blankHash

      private Hash _blankHash
      Blank hash used for the reply keys.
    • _ChaReplyKeys

      private SessionKey[] _ChaReplyKeys
      ChaCha20 reply keys, by hop.
    • _ChaReplyADs

      private byte[][] _ChaReplyADs
      ChaCha20 reply additional data, by hop.
    • _AESReplyKeys

      private final SessionKey[] _AESReplyKeys
      AES reply keys, by hop.
    • _AESReplyIVs

      private final byte[][] _AESReplyIVs
      AES reply IVs, by hop.
    • _garlicReplyKeys

      private MessageWrapper.OneTimeSession _garlicReplyKeys
      Garlic reply keys for the outbound endpoint only.
    • _log

      private Log _log
      Logger for the tunnel.
    • REPLY_IV_LENGTH

      public static final int REPLY_IV_LENGTH
      IV length for getAESReplyIV(int).
      See Also:
    • MAX_CONSECUTIVE_TEST_FAILURES

      public static final int MAX_CONSECUTIVE_TEST_FAILURES
      Maximum consecutive test failures before the tunnel is retired.
      See Also:
    • SOFT_FAILURE_WINDOW_MS

      static final long SOFT_FAILURE_WINDOW_MS
      Window in which soft best-effort send timeouts accumulate into a consecutive streak (status-3 timeouts only. Hard dispatch failures use MAX_CONSECUTIVE_TEST_FAILURES). A soft failure older than this is decayed out of the count, bounding both the degraded bar (TunnelPool.SOFT_DEGRADED_FOR_ENSURE) and the soft removal bar so sparse congestion timeouts over a long tunnel lifetime can never retire a tunnel that carries data when it is sent.
      See Also:
    • MAX_SOFT_FAILURES

      static final int MAX_SOFT_FAILURES
      Ceiling for the soft failure streak. The count exists only to cross the soft removal bar, so saturating well above it costs nothing and stops a retained tunnel that keeps timing out from reporting a streak long enough to be mistaken for a count of independent failures.
      See Also:
    • FIRST_HOP_FAILURE_THRESHOLD

      public static final int FIRST_HOP_FAILURE_THRESHOLD
      Consecutive first-hop send failures before an outbound tunnel is retired. Send failures are not proof the tunnel is dead: most come from local congestion (expired-on-queue, CoDel drops, no-bid replies) and land on a shared job that runs once per failed message, so the bar sits above a single burst. The count is spaced out by FIRST_HOP_FAILURE_SPACING_MS so a local stall collapses to 1 while a genuinely unreachable first hop reaches the bar on its own within FIRST_HOP_FAILURE_WINDOW_MS.
      See Also:
    • FAILURE_COUNT_CEILING

      public static final int FAILURE_COUNT_CEILING
      Ceiling for incrementTestFailures(). Comfortably above the largest removal threshold any caller can compute (degraded mode with a thin pool), so saturation never changes a decision. It only stops the reported count from drifting.
      See Also:
    • FIRST_HOP_FAILURE_SPACING_MS

      public static final long FIRST_HOP_FAILURE_SPACING_MS
      Minimum spacing between first-hop send failures that count towards FIRST_HOP_FAILURE_THRESHOLD. Failures closer together are one event, so a burst of 40 messages failing in the same second records 1, not 40.
      See Also:
    • FIRST_HOP_FAILURE_WINDOW_MS

      public static final long FIRST_HOP_FAILURE_WINDOW_MS
      Window in which spaced first-hop send failures accumulate, mirroring SOFT_FAILURE_WINDOW_MS. A failure older than this is decayed out at read time, so an idle tunnel that finally loses a send never inherits an unbounded streak.
      See Also:
    • PEAK_THROUGHPUT_COALESCE_MS

      private static final long PEAK_THROUGHPUT_COALESCE_MS
      Window over which this tunnel's throughput is totaled before the per-peer profiles are updated, in ms. Matches the window PeerProfile coalesces its own peak throughput on.
      See Also:
    • LATENCY_SAMPLE_SIZE

      private static final int LATENCY_SAMPLE_SIZE
      Latency samples kept per tunnel.
      See Also:
    • _lastLatency

      private volatile int _lastLatency
      Most recent latency sample, in ms, -1 if none.
    • _latencyHistory

      private final int[] _latencyHistory
      Ring of the recent latency samples.
    • _latencyIdx

      private volatile int _latencyIdx
      Write index into the latency ring.
    • _latencyCount

      private volatile int _latencyCount
      Latency samples recorded so far.
    • _needsExpeditedTest

      private volatile boolean _needsExpeditedTest
      True when the tunnel needs an expedited test.
    • _recentTestExemptions

      private volatile int _recentTestExemptions
      Recent-traffic test exemptions used. A tunnel with recent verified data gets a few free passes on test failures (reply-path false negatives), but not unlimited — after one exemption, failures count normally so the tunnel doesn't become immortal.
    • _destinationNickname

      private String _destinationNickname
      Optional pool nickname for log display.
    • _lastRealTraffic

      private volatile long _lastRealTraffic
      When the tunnel last carried real (non-test) traffic, or 0 if never. Updated only at the real traffic delivery sites. Inbound data arrival (InboundEndpointProcessor) and outbound message dispatch (OutboundClientMessageOneShotJob) — never by TestJob, so test traffic cannot pollute the proof that the tunnel works.
    • _lastChanceReason

      private volatile TunnelCreatorConfig.LastChanceReason _lastChanceReason
      Reason the tunnel was given a last chance.
    • _lastChanceDeadline

      private volatile long _lastChanceDeadline
      Deadline of the last chance window.
    • _lastChanceAdmission

      private volatile long _lastChanceAdmission
      When the tunnel entered the last chance window.
  • Constructor Details

    • TunnelCreatorConfig

      public TunnelCreatorConfig(RouterContext ctx, int length, boolean isInbound)
      For exploratory only (null destination).
      Parameters:
      ctx - the router context
      length - 1 minimum (0 hop is length 1)
      isInbound - true to build an inbound tunnel
    • TunnelCreatorConfig

      public TunnelCreatorConfig(RouterContext ctx, int length, boolean isInbound, Hash destination)
      Allocates the hop configs and peer arrays for the given length.
      Parameters:
      ctx - the router context
      length - 1 minimum (0 hop is length 1)
      isInbound - true to build an inbound tunnel
      destination - null for exploratory
  • Method Details

    • setDestinationNickname

      public void setDestinationNickname(String name)
      Optional display nickname for this tunnel (e.g. pool name like I2PSnark).
      Parameters:
      name - the nickname to show in logs
    • getDestinationNickname

      public String getDestinationNickname()
      Pool nickname for this tunnel, or null if not set.
      Returns:
      the pool nickname if set, null otherwise
    • getLength

      public int getLength()
      How many hops are there in the tunnel? INCLUDING US. i.e. one more than the TunnelCreatorConfig length.
      Specified by:
      getLength in interface TunnelInfo
      Returns:
      the number of hops, counting ourselves as one
    • getOptions

      public Properties getOptions()
      The tunnel pool options.
      Returns:
      null, no pool options are supported
    • getConfig

      public HopConfig getConfig(int hop)
      Retrieve the config for the given hop. the gateway is hop 0.
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      the config for that hop, non-null
    • getReceiveTunnelId

      public TunnelId getReceiveTunnelId(int hop)
      Retrieve the tunnelId that the given hop receives messages on. the gateway is hop 0.
      Specified by:
      getReceiveTunnelId in interface TunnelInfo
      Parameters:
      hop - zero-based position in the tunnel, 0 being the gateway
      Returns:
      the receive tunnel id
    • getSendTunnelId

      public TunnelId getSendTunnelId(int hop)
      Retrieve the tunnelId that the given hop sends messages on. the gateway is hop 0.
      Specified by:
      getSendTunnelId in interface TunnelInfo
      Parameters:
      hop - zero-based position in the tunnel, 0 being the gateway
      Returns:
      the send tunnel id
    • getPeer

      public Hash getPeer(int hop)
      Retrieve the peer at the given hop (the gateway is hop 0).
      Specified by:
      getPeer in interface TunnelInfo
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      the peer at that hop
    • setPeer

      public void setPeer(int hop, Hash peer)
      The peer at the given hop.
      Parameters:
      hop - the hop number, gateway is 0
      peer - the peer to use at that hop
    • getGateway

      public Hash getGateway()
      For convenience.
      Specified by:
      getGateway in interface TunnelInfo
      Returns:
      getPeer(0)
    • getEndpoint

      public Hash getEndpoint()
      For convenience.
      Specified by:
      getEndpoint in interface TunnelInfo
      Returns:
      getPeer(getLength() - 1)
    • getFarEnd

      public Hash getFarEnd()
      For convenience.
      Specified by:
      getFarEnd in interface TunnelInfo
      Returns:
      isInbound() ? getGateway() : getEndpoint()
    • isInbound

      public boolean isInbound()
      Is this an inbound tunnel?
      Specified by:
      isInbound in interface TunnelInfo
      Returns:
      true if peers at the far end send to us through this tunnel
    • getDestination

      public Hash getDestination()
      If this is a client tunnel, what destination is it for?
      Specified by:
      getDestination in interface TunnelInfo
      Returns:
      null for exploratory
    • getExpiration

      public long getExpiration()
      The tunnel expiration, in ms since the epoch.
      Specified by:
      getExpiration in interface TunnelInfo
      Returns:
      the time the tunnel expires, in ms since the epoch
    • setExpiration

      public void setExpiration(long when)
      The tunnel expiration, in ms since the epoch.
      Specified by:
      setExpiration in interface TunnelInfo
      Parameters:
      when - expiration time in milliseconds since epoch
    • hadLocalHopSession

      public boolean hadLocalHopSession()
      Whether this tunnel held a transport session to its local hop when it was built. False when never recorded.
      Specified by:
      hadLocalHopSession in interface TunnelInfo
      Returns:
      true when a local-hop session was established at build time
    • setLocalHopSessionEstablished

      public void setLocalHopSessionEstablished(boolean established)
      Record whether a transport session to the local hop existed at build time.
      Specified by:
      setLocalHopSessionEstablished in interface TunnelInfo
      Parameters:
      established - the session state observed when the tunnel entered the pool
    • getLocalHopMissingSince

      public long getLocalHopMissingSince()
      When the local transport session was first seen missing, or 0 when present.
      Specified by:
      getLocalHopMissingSince in interface TunnelInfo
      Returns:
      the time in ms the session was first seen missing, or 0
    • setLocalHopMissingSince

      public void setLocalHopMissingSince(long when)
      Record or clear when the local transport session was first seen missing.
      Specified by:
      setLocalHopMissingSince in interface TunnelInfo
      Parameters:
      when - the time in ms, or 0 to mark the session present
    • getReplyOrder

      public List<Integer> getReplyOrder()
      Component ordering in the new style request.
      Returns:
      the component ordering, never null
    • setReplyOrder

      public void setReplyOrder(List<Integer> order)
      The component ordering for the new style request.
      Parameters:
      order - the components in the order they should be requested
    • getReplyMessageId

      public long getReplyMessageId()
      The message ID for the new style reply.
      Returns:
      the reply message ID, 0 when none has been set
    • setReplyMessageId

      public void setReplyMessageId(long id)
      The message ID for the new style reply.
      Parameters:
      id - the message ID to return to the client
    • incrementProcessedMessages

      public void incrementProcessedMessages()
      Take note of a message being pumped through this tunnel.
    • getProcessedMessagesCount

      public int getProcessedMessagesCount()
      The number of messages pumped through this tunnel.
      Specified by:
      getProcessedMessagesCount in interface TunnelInfo
      Returns:
      the processed messages count
    • incrementVerifiedBytesTransferred

      public void incrementVerifiedBytesTransferred(int bytes)
      Record that bytes moved through this tunnel, counting as real traffic: it also stamps the last-real-traffic clock that getLastTransferred() reports and the data-verified test trust in TestJob keys off. Only the real delivery paths — inbound data arrival and outbound message dispatch — may call this.
      Specified by:
      incrementVerifiedBytesTransferred in interface TunnelInfo
      Parameters:
      bytes - bytes counted against the tunnel
    • incrementVerifiedBytesTransferred

      public void incrementVerifiedBytesTransferred(int bytes, boolean realTraffic)
      Record that bytes moved through this tunnel, optionally counting as real traffic.

      The distinction matters because two things read this state. The throughput profile wants *every* byte, including the 1024 a test round pushes, or the per-peer throughput figures understate a busy tunnel. The data-verified test trust wants *only* real traffic, because it reads getLastTransferred() to decide the tunnel has proven itself in production. When the test round called the unconditional form, a passing test stamped the real-traffic clock on the tunnel under test — which for an outbound test is the tunnel itself — so a tunnel that had never carried a single production byte could grant itself the trust that is meant to mean the opposite.

      Parameters:
      bytes - bytes counted against the tunnel
      realTraffic - true when this is production traffic, false for test or synthetic traffic
    • coalescePeakThroughput

      private void coalescePeakThroughput(long now)
      Periodically push this tunnel's throughput into the per-peer profiles.

      Run once a minute from incrementVerifiedBytesTransferred(int, boolean), crediting both tunnelDataPushed() (raw period bytes) and tunnelDataPushed1m() (that total normalized to a minute): both are pure sums, so bulk crediting equals per-fragment crediting.

      Parameters:
      now - wall clock at the call site, already compared against the coalesce deadline so the fast path never gets here
    • getVerifiedBytesTransferred

      public long getVerifiedBytesTransferred()
      The total verified bytes transferred on this tunnel.
      Specified by:
      getVerifiedBytesTransferred in interface TunnelInfo
      Returns:
      the verified bytes transferred
    • getLastTransferred

      public long getLastTransferred()
      When we last sent or received data on this tunnel.
      Returns:
      the last transferred
    • claimPreConnectRetry

      public boolean claimPreConnectRetry(long now, int maxRetries, long windowMs)
      Claim one of at most maxRetries pre-connect retries for this tunnel, forgetting retries older than windowMs.

      A first hop with no transport session re-dispatches the whole build through BuildRequestor.preConnectFallback(), and each retry costs a full request timeout. Nothing bounded that, so a dead first hop retried forever and kept the tunnel pinned in the pool's in-progress set. The window is what makes the bound fair: a tunnel that fails once every few minutes keeps its retry, while a runaway loop, which retries on every timeout, spends its budget and stops.

      Parameters:
      now - current time in ms
      maxRetries - retries one window may spend, 0 disables retrying
      windowMs - how long a spent retry is remembered
      Returns:
      true if a retry was claimed, false if the budget is already spent
    • getCreationTime

      public long getCreationTime()
      When this tunnel was built, in wall-clock ms. Never zero, so a caller asking "is this young" needs no null or unset case.
      Returns:
      creation time in ms since the epoch
    • recordRealTraffic

      public void recordRealTraffic()
      Record that the tunnel carried real traffic. Real data proves the tunnel works, so any soft best-effort streak accumulated before it is cleared alongside it.

      It also refills the recent-traffic test exemption budget. That budget is spent when a test fails while the tunnel demonstrably carried data — a reply-path false negative rather than evidence against the tunnel — and it used to be refilled only by testSuccessful(int), so a tunnel that could never answer a test but could still carry data got exactly one free pass for its whole lifetime and was then condemned by failures it had no way to clear. Traffic is the stronger proof: the inbound caller only fires after the tunnel's crypto verified, and the outbound caller only fires after the remote peer ACKed.

      Status itself is not touched here — see TunnelPool.clearFailingOnTraffic(), which owns promotion back to GOOD.

      Specified by:
      recordRealTraffic in interface TunnelInfo
    • getLastRealTraffic

      public long getLastRealTraffic()
      When the tunnel last carried real traffic.
      Specified by:
      getLastRealTraffic in interface TunnelInfo
      Returns:
      the timestamp, or 0 if it never carried real traffic
    • tunnelFailed

      public boolean tunnelFailed()
      The tunnel failed a test, so (maybe) stop using it.
      Returns:
      false if we stopped using it, true if still ok
    • incrementTestFailures

      public void incrementTestFailures()
      Increment the failure count without triggering pool removal or reuse flag. Used when a previously GOOD tunnel fails a retest — we want to track the failure for selection deprioritization but keep the tunnel alive for further testing and data delivery.

      The count saturates. Every caller compares the result against a removal threshold, so once that threshold is passed the extra increments change no decision — they only made the counter (and the log line quoting it) grow without bound. A condemned-but-retained tunnel kept retesting reached counts in the hundreds, which made a saturated metric impossible to read and hid the real failure ratio.

      Specified by:
      incrementTestFailures in interface TunnelInfo
    • incrementSoftFailures

      public void incrementSoftFailures()
      Increment the soft best-effort timeout counter only. Soft status-3 must not trip getTunnelFailed() or selection gates that key on the hard/test counter. Congestion is not tunnel death. The streak is time-windowed: a failure that arrives after SOFT_FAILURE_WINDOW_MS without one starts the count over at 1 instead of extending an aging streak forever.
      Specified by:
      incrementSoftFailures in interface TunnelInfo
    • getSoftFailures

      public int getSoftFailures()
      Soft best-effort timeout count, with failures older than SOFT_FAILURE_WINDOW_MS decayed out at read time (the time-windowed form of the streak — no sweep required).
      Specified by:
      getSoftFailures in interface TunnelInfo
      Returns:
      the effective soft failure count
    • clearSoftFailures

      public void clearSoftFailures()
      Reset the soft streak: verified traffic proves the tunnel carries data, so congestion timeouts recorded before it no longer count. Called from recordRealTraffic() and clearTestFailures(), never from testSuccessful(int) — a passing test exercises the test path, not the data path.
    • effectiveSoftFailures

      static int effectiveSoftFailures(int raw, long lastSoftFailure, long now, long windowMs)
      Effective soft-failure streak for a raw count stamped at a point in time. Pure decision helper so the decay rule is unit-testable without waiting out the real window.
      Parameters:
      raw - stored soft failure count, <= 0 means none
      lastSoftFailure - wall-clock time of the most recent soft failure (ms), <= 0 means none
      now - current wall-clock time (ms)
      windowMs - window in which soft failures accumulate (ms)
      Returns:
      the count to act on: 0 once the streak has aged out
    • effectiveFirstHopFailures

      static int effectiveFirstHopFailures(int raw, long lastCounted, long now, long windowMs)
      Effective first-hop send failure streak for a raw count stamped at a point in time. Same time-windowed decay rule as effectiveSoftFailures(int, long, long, long) — both are read-time filters over a raw counter, so no sweep is required.
      Parameters:
      raw - stored first-hop failure count, <= 0 means none
      lastCounted - wall-clock time of the most recent counted failure (ms), <= 0 means none
      now - current wall-clock time (ms)
      windowMs - window in which first-hop failures accumulate (ms)
      Returns:
      the count to act on: 0 once the streak has aged out
    • nextFirstHopFailureCount

      static int nextFirstHopFailureCount(int raw, long lastCounted, long now, long spacingMs, long windowMs)
      Next first-hop failure count for a send failure arriving at now, folding in both the decay window and the spacing rule. Pure decision helper so the burst/stale behaviour is unit-testable without real waits.
      Parameters:
      raw - stored first-hop failure count, <= 0 means none
      lastCounted - wall-clock time of the most recent counted failure (ms), <= 0 means none
      now - current wall-clock time (ms)
      spacingMs - minimum spacing between counted failures (ms)
      windowMs - window in which first-hop failures accumulate (ms)
      Returns:
      the new count (>= 1), or -1 when this failure is a burst duplicate inside the spacing interval and must not be counted
    • recordFirstHopSendFailure

      public int recordFirstHopSendFailure()
      Record a failed send to the first hop of an outbound tunnel.

      Called from the outbound send-failure job, which fires for every non-requeueable send failure (expired on queue, CoDel drop, no-bid reply, dropped message). Most of which are local congestion, not a dead peer. Counting raw would retire the tunnel on one bad second, so the streak is decayed by FIRST_HOP_FAILURE_WINDOW_MS and spaced by FIRST_HOP_FAILURE_SPACING_MS.

      Returns:
      -1 if not applicable (inbound or zero-hop tunnel), 0 if this failure changed nothing (inside the spacing interval, or the threshold was already reached and escalated), otherwise the current streak; a return value of FIRST_HOP_FAILURE_THRESHOLD or more means the caller must fail the tunnel, and it is only handed that signal once until clearFirstHopFailures() re-arms it
    • recordFirstHopSendFailure

      int recordFirstHopSendFailure(long now)
      Timestamped form of recordFirstHopSendFailure(), so spacing, decay and latching are testable without real waits.
      Parameters:
      now - wall-clock time (ms) of this failure
      Returns:
      see recordFirstHopSendFailure()
    • getFirstHopSendFailures

      public int getFirstHopSendFailures()
      Effective first-hop send failure streak, with failures older than FIRST_HOP_FAILURE_WINDOW_MS decayed out at read time.
      Returns:
      the streak count, 0 if none
    • getFirstHopSendFailures

      int getFirstHopSendFailures(long now)
      Timestamped form of getFirstHopSendFailures().
      Parameters:
      now - wall-clock time (ms) to evaluate the decay against
      Returns:
      the streak count, 0 if none
    • clearFirstHopFailures

      public void clearFirstHopFailures()
      Reset the first-hop send failure streak and re-arm the escalation latch. Only a data-carrying send proves the path to the first hop works, so the sole caller is recordRealTraffic().

      A passing test deliberately does not clear the streak: the round trip proves the peer is not dead, but not that it is not flaky, and a first hop that alternates fail/pass/fail/pass would never accumulate to FIRST_HOP_FAILURE_THRESHOLD if every pass reset it. Staleness is handled by the FIRST_HOP_FAILURE_WINDOW_MS read-time decay instead, which ages out a genuinely dead peer's old failures without making accumulation impossible for a merely flaky one.

      This differs from clearSoftFailures(), which likewise is never called from testSuccessful(int) for the same reason.

    • tunnelFailedCompletely

      public void tunnelFailedCompletely()
      The tunnel failed completely, so definitely stop using it.
    • tunnelFailedFirstHop

      public void tunnelFailedFirstHop()
      We failed to contact the first hop for an outbound tunnel, so immediately stop using it. For outbound non-zero-hop tunnels only.

      Base hook: marks the tunnel as failed. Subclasses with a pool (PooledTunnelCreatorConfig) also notify the pool of the failure.

    • firstHopSendFailureStreak

      public void firstHopSendFailureStreak(int streak)
      Hook invoked whenever the first-hop send failure streak advances. Gives subclasses a chance to re-warm the path to the first hop: the failure may be a local stall rather than a dead peer, and a fresh transport session makes the next send likely to land. Not invoked for burst duplicates, so callers see at most one hook per FIRST_HOP_FAILURE_SPACING_MS.

      The caller invokes this before it acts on the threshold, so the streak handed in may equal FIRST_HOP_FAILURE_THRESHOLD; a subclass that only wants to re-warm a tunnel that is still going to be kept alive must filter on the value itself — see PooledTunnelCreatorConfig.shouldPreConnect(int).

      Base config has no pool and nothing to warm; see PooledTunnelCreatorConfig.

      Parameters:
      streak - the current streak, from 1 up to and including FIRST_HOP_FAILURE_THRESHOLD
    • getTunnelFailed

      public boolean getTunnelFailed()
      Has the tunnel failed completely?
      Specified by:
      getTunnelFailed in interface TunnelInfo
      Returns:
      the tunnel failed
    • getTunnelFailures

      public int getTunnelFailures()
      The consecutive failure count.
      Returns:
      the tunnel failures
    • clearTestFailures

      public void clearTestFailures()
      Reset the consecutive failure counter and mark the tunnel as GOOD. Called only on traffic proof. Never by testSuccessful(int), which reaches GOOD by being tested rather than by carrying data — so it also restores the recent-traffic test exemption budget alongside the soft streak: a tunnel promoted back from FAILING/FAILED must resume normal service with a clean slate, not inherit the spend that produced the mark.
    • getRecentTestExemptions

      public int getRecentTestExemptions()
      The number of recent-traffic test exemptions used.
      Returns:
      the recent test exemptions
    • incrementRecentTestExemptions

      public void incrementRecentTestExemptions()
      Increment the recent-traffic test exemption counter.
    • testSuccessful

      public void testSuccessful(int ms)
      Mark the tunnel as GOOD, recording the latency of the successful test. Clears any last-chance admission — the test settled, so the early-expiry gate no longer needs the bypass. Does NOT clear the soft streak: a test exercises the test path, not the data path.

      Does NOT clear the first-hop send-failure streak. A passing test is evidence the peer is not dead, but not evidence it is not flaky — a flaky first hop that alternates fail/pass/fail/pass would never reach the failure threshold if each pass reset the streak. The 60s decay window (FIRST_HOP_FAILURE_WINDOW_MS) already ages the streak naturally, so a genuinely dead peer's old failures expire without making accumulation impossible for a merely flaky one.

      Specified by:
      testSuccessful in interface TunnelInfo
      Parameters:
      ms - the response time in milliseconds
    • wasReused

      public boolean wasReused()
      Did we reuse this tunnel?
      Specified by:
      wasReused in interface TunnelInfo
      Returns:
      true if the tunnel came from an existing pool rather than a fresh build
    • setReused

      public void setReused()
      Note that we reused this tunnel.
      Specified by:
      setReused in interface TunnelInfo
    • getPriority

      public int getPriority()
      Outbound message priority - for outbound tunnels only.
      Returns:
      -25 to +25, default 0
    • setPriority

      public void setPriority(int priority)
      Outbound message priority - for outbound tunnels only.
      Parameters:
      priority - -25 to +25, default 0
    • setAESReplyKeys

      public void setAESReplyKeys(int hop, SessionKey key, byte[] iv)
      Key and IV to encrypt the reply sent for the tunnel creation crypto.
      Parameters:
      hop - the hop number, gateway is 0
      key - the key to encrypt the reply with
      iv - the 16 byte IV
      Throws:
      IllegalArgumentException - if iv not 16 bytes
    • getAESReplyKey

      public SessionKey getAESReplyKey(int hop)
      Key to encrypt the reply sent for the tunnel creation crypto. Null for short build record.
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      key or null
      Throws:
      IllegalArgumentException - if iv not 16 bytes
    • getAESReplyIV

      public byte[] getAESReplyIV(int hop)
      IV used to encrypt the reply sent for the tunnel creation crypto. Null for short build record.
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      16 bytes or null
    • getBlankHash

      public Hash getBlankHash()
      Checksum for blank record.
      Returns:
      the blank hash
    • setBlankHash

      public void setBlankHash(Hash h)
      Checksum for blank record.
      Parameters:
      h - the hash to use for a blank record
    • setLastLatency

      public void setLastLatency(int ms)
      The latency of the last completed test.
      Parameters:
      ms - latency in milliseconds
    • getLastLatency

      public int getLastLatency()
      The last recorded test latency.
      Specified by:
      getLastLatency in interface TunnelInfo
      Returns:
      latency in milliseconds, or -1 if not available
    • addLatencySample

      public void addLatencySample(int ms)
      Add a latency sample from a test result.
      Parameters:
      ms - latency in milliseconds
    • getAverageLatency

      public int getAverageLatency()
      The average latency of the last 3 tests.
      Returns:
      average latency in ms, or -1 if no tests yet
    • hasEnoughLatencyTests

      public boolean hasEnoughLatencyTests()
      Whether at least 3 latency samples have been collected.
      Returns:
      true if we have at least 3 latency samples
    • needsExpeditedTest

      public boolean needsExpeditedTest()
      Whether the tunnel needs an expedited test due to slow detection.
      Returns:
      true if tunnel needs an expedited test due to slow detection
    • clearExpeditedTest

      public void clearExpeditedTest()
      Clear the expedited test flag after running the expedited test.
    • requestExpeditedTest

      public void requestExpeditedTest()
      The tunnel appeared slow, so flag it for an expedited test.
    • getTestStatus

      public TunnelTestStatus getTestStatus()
      The current test status of this tunnel for UI display.
      Specified by:
      getTestStatus in interface TunnelInfo
      Returns:
      the current test status (UNTESTED, TESTING, GOOD, FAILING, or FAILED)
    • setTestStarted

      public void setTestStarted()
      Called when a test is started.
      Specified by:
      setTestStarted in interface TunnelInfo
    • setTestFailed

      public void setTestFailed()
      Called when a test fails. Updates the test status based on consecutive failure count. Only mark as FAILED after MAX_CONSECUTIVE_TEST_FAILURES (3) failures - before that, it's just FAILING and still counts as a valid tunnel.
      Specified by:
      setTestFailed in interface TunnelInfo
    • setTestFailing

      public void setTestFailing()
      Mark the tunnel FAILING regardless of the hard-failure counter. setTestFailed() derives the status from _failures, so it reports GOOD for a tunnel retained on soft send timeouts alone — which would leave the tunnel selectable and hold its slot in the pool's good-tunnel accounting while it keeps timing out.
      Specified by:
      setTestFailing in interface TunnelInfo
    • setTestTooSlow

      public void setTestTooSlow()
      Mark tunnel as scheduled for early expiry (pruned from pool). Revokes any last-chance admission — the pool decided to retire it.
    • setTestOverBudget

      public void setTestOverBudget()
      Mark tunnel as scheduled for early expiry due to pool being over budget. Revokes any last-chance admission — the pool decided to retire it.
    • admitLastChance

      public void admitLastChance(long now, TunnelCreatorConfig.LastChanceReason reason)
      Admit this tunnel for a last-chance test despite its remaining life being inside the early-expiry window. The deadline is snapshotted from the expiration at admission time so later pool state changes cannot extend it. Natural expiry still bounds it.
      Parameters:
      now - current wall-clock time (ms)
      reason - why the tunnel was admitted; null clears
    • isLastChanceAdmitted

      public boolean isLastChanceAdmitted(long now)
      Is a last-chance test admission still valid at now? Only expiration shortens the window. The snapshot deadline prevents a re-read of a later expiration from extending it, and clearLastChanceAdmission() revokes it once the test settles.
      Parameters:
      now - current wall-clock time (ms)
      Returns:
      true if an unexpired admission is in effect
    • getLastChanceReason

      public TunnelCreatorConfig.LastChanceReason getLastChanceReason()
      Why this tunnel was admitted for a last-chance test.
      Returns:
      the reason, never null (TunnelCreatorConfig.LastChanceReason.NONE when absent)
    • getLastChanceDeadline

      public long getLastChanceDeadline()
      When the last-chance admission expires (deadline snapshot).
      Returns:
      the deadline (ms), or 0 if never admitted
    • getLastChanceAdmission

      public long getLastChanceAdmission()
      When the last-chance admission was granted (ms), or 0 if never.
      Returns:
      the admission time in ms, 0 when never admitted
    • clearLastChanceAdmission

      public void clearLastChanceAdmission()
      Revoke the last-chance admission (test settled, or no longer needed).
    • getConsecutiveFailures

      public int getConsecutiveFailures()
      The number of consecutive test failures.
      Specified by:
      getConsecutiveFailures in interface TunnelInfo
      Returns:
      the count of consecutive failures
    • setChaChaReplyKeys

      public void setChaChaReplyKeys(int hop, SessionKey key, byte[] ad)
      The ECIES reply key and associated data for the given hop.
      Parameters:
      hop - the hop number, gateway is 0
      key - the reply key
      ad - the associated data
    • isEC

      public boolean isEC(int hop)
      Is it an ECIES hop?
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      whether e c
    • getChaChaReplyKey

      public SessionKey getChaChaReplyKey(int hop)
      The ECIES reply key for the given hop, or null.
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      the cha cha reply key
    • getChaChaReplyAD

      public byte[] getChaChaReplyAD(int hop)
      The ECIES reply associated data for the given hop, or null.
      Parameters:
      hop - the hop number, gateway is 0
      Returns:
      the cha cha reply a d
    • setGarlicReplyKeys

      public void setGarlicReplyKeys(MessageWrapper.OneTimeSession keys)
      ECIES short OBEP record only.
      Parameters:
      keys - the one time session carrying the short reply keys
    • getGarlicReplyKeys

      public MessageWrapper.OneTimeSession getGarlicReplyKeys()
      ECIES short OBEP record only.
      Returns:
      null for ElGamal or ECIES long record or non-OBEP
    • toString

      public String toString()
      Human-readable description of the tunnel, its peers, and its state.
      Overrides:
      toString in class Object
    • toShortString

      public String toShortString()
      Compact one-line tunnel identifier for log output: role, client or exploratory, nickname and short destination. No hop list, no newlines.
      Returns:
      the role, class, nickname and short destination, on one line
    • toStringFull

      public String toStringFull()
      Render every hop, its peer, and its tunnel IDs, for a full description.

      It ends with the garlic reply key and tag, so DEBUG only - never log the result at INFO or above.

      Returns:
      the multi-line description, never null