diff --git a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java index 43e1d1314..57e44203e 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java @@ -21,6 +21,65 @@ import net.i2p.util.SimpleTimer; * Handle fragments at the endpoint of a tunnel, peeling off fully completed * I2NPMessages when they arrive, and dropping fragments if they take too long * to arrive. + * + * From tunnel-alt.html: + +

When the gateway wants to deliver data through the tunnel, it first +gathers zero or more I2NP messages, selects how much padding will be used, +fragments it across the necessary number of 1KB tunnel messages, and decides how +each I2NP message should be handled by the tunnel endpoint, encoding that +data into the raw tunnel payload:

+ + +

The instructions are encoded with a single control byte, followed by any +necessary additional information. The first bit in that control byte determines +how the remainder of the header is interpreted - if it is not set, the message +is either not fragmented or this is the first fragment in the message. If it is +set, this is a follow on fragment.

+ +

With the first bit being 0, the instructions are:

+ + +

If the first bit being 1, the instructions are:

+ + +

The I2NP message is encoded in its standard form, and the +preprocessed payload must be padded to a multiple of 16 bytes.

+ * */ public class FragmentHandler { @@ -165,21 +224,19 @@ public class FragmentHandler { _log.debug("endpoint IV: " + Base64.encode(preV, validLength - HopProcessor.IV_LENGTH, HopProcessor.IV_LENGTH)); Hash v = _context.sha().calculateHash(preV, 0, validLength); + _validateCache.release(ba); - //Hash v = _context.sha().calculateHash(preV, 0, validLength); boolean eq = DataHelper.eq(v.getData(), 0, preprocessed, offset + HopProcessor.IV_LENGTH, 4); if (!eq) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Corrupt tunnel message - verification fails: \n" + Base64.encode(preprocessed, offset+HopProcessor.IV_LENGTH, 4) - + "\n" + Base64.encode(v.getData(), 0, 4)); - if (_log.shouldLog(Log.WARN)) - _log.warn("nomatching endpoint: # pad bytes: " + (paddingEnd-(HopProcessor.IV_LENGTH+4)-1) + "\n" + if (_log.shouldLog(Log.WARN)) { + _log.warn("Corrupt tunnel message - verification fails: " + Base64.encode(preprocessed, offset+HopProcessor.IV_LENGTH, 4) + + " != " + Base64.encode(v.getData(), 0, 4)); + _log.warn("No matching endpoint: # pad bytes: " + (paddingEnd-(HopProcessor.IV_LENGTH+4)-1) + " offset=" + offset + " length=" + length + " paddingEnd=" + paddingEnd + Base64.encode(preprocessed, offset, length)); + } } - _validateCache.release(ba); - if (eq) { int excessPadding = paddingEnd - (HopProcessor.IV_LENGTH + 4 + 1); if (excessPadding > 0) // suboptimal fragmentation