diff --git a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java index 962e205fc0b3d56343c2bf41cef7f9fb96d53384..892eb2e66b5d56e07af7a1e3b51fc495fc6b4c39 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java @@ -117,8 +117,9 @@ class FragmentHandler { * sending the resulting I2NPMessages where necessary. The received * fragments are all verified. * + * @return ok (false if corrupt) */ - public void receiveTunnelMessage(byte preprocessed[], int offset, int length) { + public boolean receiveTunnelMessage(byte preprocessed[], int offset, int length) { boolean ok = verifyPreprocessed(preprocessed, offset, length); if (!ok) { if (_log.shouldLog(Log.WARN)) @@ -126,7 +127,7 @@ class FragmentHandler { + preprocessed.length + " off=" +offset + " len=" + length); _cache.release(new ByteArray(preprocessed)); _context.statManager().addRateData("tunnel.corruptMessage", 1); - return; + return false; } offset += HopProcessor.IV_LENGTH; // skip the IV offset += 4; // skip the hash segment @@ -139,7 +140,7 @@ class FragmentHandler { _context.statManager().addRateData("tunnel.corruptMessage", 1); if (_log.shouldWarn()) _log.warn("Corrupt fragment received: off = " + offset); - return; + return false; } padding++; } @@ -155,7 +156,7 @@ class FragmentHandler { _context.statManager().addRateData("tunnel.corruptMessage", 1); if (_log.shouldWarn()) _log.warn("Corrupt fragment received: off = " + off); - return; + return false; } offset = off; } @@ -163,10 +164,12 @@ class FragmentHandler { _context.statManager().addRateData("tunnel.corruptMessage", 1); if (_log.shouldWarn()) _log.warn("Corrupt fragment received: offset = " + offset, aioobe); + return false; } catch (NullPointerException npe) { if (_log.shouldWarn()) _log.warn("Corrupt fragment received: offset = " + offset, npe); _context.statManager().addRateData("tunnel.corruptMessage", 1); + return false; } catch (RuntimeException e) { if (_log.shouldWarn()) _log.warn("Corrupt fragment received: offset = " + offset, e); @@ -183,6 +186,7 @@ class FragmentHandler { // let's limit the damage here and skip the: // .transport.udp.MessageReceiver: b0rked receiving a message.. wazza huzza hmm? //throw e; + return false; } finally { // each of the FragmentedMessages populated make a copy out of the // payload, which they release separately, so we can release @@ -192,6 +196,7 @@ class FragmentHandler { // in order to put it in the pool, but it shouldn't cause any harm. _cache.release(new ByteArray(preprocessed)); } + return true; } public int getCompleteCount() { return _completed.get(); } diff --git a/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java b/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java index b394f514df4e64372f21f9540a2bb7af1e4c1dbb..34bb787950f194a50c2cbdb6a7fd5dcad3a4297b 100644 --- a/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java +++ b/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java @@ -32,7 +32,8 @@ class OutboundTunnelEndpoint { public void dispatch(TunnelDataMessage msg, Hash recvFrom) { _config.incrementProcessedMessages(); - boolean ok = _processor.process(msg.getData(), 0, msg.getData().length, recvFrom); + byte[] data = msg.getData(); + boolean ok = _processor.process(data, 0, data.length, recvFrom); if (!ok) { // invalid IV // If we pass it on to the handler, it will fail @@ -41,7 +42,16 @@ class OutboundTunnelEndpoint { _log.warn("Invalid IV, dropping at OBEP " + _config); return; } - _handler.receiveTunnelMessage(msg.getData(), 0, msg.getData().length); + ok = _handler.receiveTunnelMessage(data, 0, data.length); + if (!ok) { + // blame previous hop + Hash h = _config.getReceiveFrom(); + if (h != null) { + if (_log.shouldLog(Log.WARN)) + _log.warn(toString() + ": Blaming " + h + " 50%"); + _context.profileManager().tunnelFailed(h, 50); + } + } } private class DefragmentedHandler implements FragmentHandler.DefragmentedReceiver { diff --git a/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java b/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java index c27ceecb39f56479fe7cde56cc10923ccf6aa2bc..4741927705e62b9dd0afb99bd300853c64c19453 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java @@ -122,10 +122,26 @@ class TunnelParticipant { new TimeoutJob(_context, msg), MAX_LOOKUP_TIME); } } else { - _inboundEndpointProcessor.getConfig().incrementProcessedMessages(); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Receive fragment: on " + _config + ": " + msg); - _handler.receiveTunnelMessage(data, 0, data.length); + // IBEP + TunnelCreatorConfig cfg = _inboundEndpointProcessor.getConfig(); + cfg.incrementProcessedMessages(); + ok = _handler.receiveTunnelMessage(data, 0, data.length); + if (ok) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Receive fragment: on " + _config + ": " + msg); + } else { + // blame everybody equally + int lenm1 = cfg.getLength() - 1; + if (lenm1 > 0) { + int pct = 100 / (lenm1); + for (int i = 0; i < lenm1; i++) { + Hash h = cfg.getPeer(i); + if (_log.shouldLog(Log.WARN)) + _log.warn(toString() + ": Blaming " + h + ' ' + pct + '%'); + _context.profileManager().tunnelFailed(h, pct); + } + } + } } }