From ae41a3f3161fc0f8c274d12b814b96836145beca Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 19 May 2015 14:49:02 +0000 Subject: [PATCH] SSU: Synchronize UDPPacket methods, possible fix for bad packets and UDP stalls caused by cache corruption? Cleanup unused methods and fields --- .../src/net/i2p/router/RouterVersion.java | 2 +- .../router/transport/udp/PacketHandler.java | 12 ++-- .../i2p/router/transport/udp/UDPPacket.java | 60 ++++++++++--------- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 0e04b1445c..33006bcb1f 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 26; + public final static long BUILD = 27; /** for example "-test" */ public final static String EXTRA = "-rc"; diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java index 6c3605174b..29a7b69d8a 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java @@ -357,7 +357,7 @@ class PacketHandler { } else { if (_log.shouldLog(Log.WARN)) _log.warn("Validation with existing con failed, and validation as reestablish failed too. DROP " + packet); - _context.statManager().addRateData("udp.droppedInvalidReestablish", packet.getLifetime(), packet.getExpiration()); + _context.statManager().addRateData("udp.droppedInvalidReestablish", packet.getLifetime()); } return; } @@ -455,7 +455,7 @@ class PacketHandler { if (_log.shouldLog(Log.WARN)) _log.warn("Cannot validate rcvd pkt (path) wasCached? " + alreadyFailed + ": " + packet); - _context.statManager().addRateData("udp.droppedInvalidEstablish", packet.getLifetime(), packet.getExpiration()); + _context.statManager().addRateData("udp.droppedInvalidEstablish", packet.getLifetime()); switch (peerType) { case INBOUND_FALLBACK: _context.statManager().addRateData("udp.droppedInvalidEstablish.inbound", packet.getLifetime(), packet.getTimeSinceReceived()); @@ -532,7 +532,7 @@ class PacketHandler { _state = 34; receivePacket(reader, packet, INBOUND_FALLBACK); } else { - _context.statManager().addRateData("udp.droppedInvalidInboundEstablish", packet.getLifetime(), packet.getExpiration()); + _context.statManager().addRateData("udp.droppedInvalidInboundEstablish", packet.getLifetime()); } } @@ -638,12 +638,12 @@ class PacketHandler { if (skew > GRACE_PERIOD) { if (_log.shouldLog(Log.WARN)) _log.warn("Packet too far in the past: " + new Date(sendOn) + ": " + packet); - _context.statManager().addRateData("udp.droppedInvalidSkew", skew, packet.getExpiration()); + _context.statManager().addRateData("udp.droppedInvalidSkew", skew); return; } else if (skew < 0 - GRACE_PERIOD) { if (_log.shouldLog(Log.WARN)) _log.warn("Packet too far in the future: " + new Date(sendOn) + ": " + packet); - _context.statManager().addRateData("udp.droppedInvalidSkew", 0-skew, packet.getExpiration()); + _context.statManager().addRateData("udp.droppedInvalidSkew", 0-skew); return; } @@ -790,7 +790,7 @@ class PacketHandler { _state = 52; if (_log.shouldLog(Log.WARN)) _log.warn("Dropping type " + type + " auth " + auth + ": " + packet); - _context.statManager().addRateData("udp.droppedInvalidUnknown", packet.getLifetime(), packet.getExpiration()); + _context.statManager().addRateData("udp.droppedInvalidUnknown", packet.getLifetime()); return; } } diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java index 2f8cf4ea31..33eb2d2e67 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java @@ -26,15 +26,15 @@ class UDPPacket implements CDQEntry { private final DatagramPacket _packet; private volatile short _priority; private volatile long _initializeTime; - private volatile long _expiration; + //private volatile long _expiration; private final byte[] _data; private final byte[] _validateBuf; private final byte[] _ivBuf; private volatile int _markedType; - private volatile RemoteHostId _remoteHost; - private volatile boolean _released; - private volatile Exception _releasedBy; - private volatile Exception _acquiredBy; + private RemoteHostId _remoteHost; + private boolean _released; + //private volatile Exception _releasedBy; + //private volatile Exception _acquiredBy; private long _enqueueTime; private long _receivedTime; //private long _beforeValidate; @@ -112,7 +112,7 @@ class UDPPacket implements CDQEntry { init(ctx); } - private void init(I2PAppContext ctx) { + private synchronized void init(I2PAppContext ctx) { _context = ctx; //_dataBuf = _dataCache.acquire(); Arrays.fill(_data, (byte)0); @@ -146,20 +146,20 @@ class UDPPacket implements CDQEntry { ****/ /** */ - public DatagramPacket getPacket() { verifyNotReleased(); return _packet; } - public short getPriority() { verifyNotReleased(); return _priority; } - public long getExpiration() { verifyNotReleased(); return _expiration; } - public long getBegin() { verifyNotReleased(); return _initializeTime; } + public synchronized DatagramPacket getPacket() { verifyNotReleased(); return _packet; } + public synchronized short getPriority() { verifyNotReleased(); return _priority; } + //public long getExpiration() { verifyNotReleased(); return _expiration; } + public synchronized long getBegin() { verifyNotReleased(); return _initializeTime; } public long getLifetime() { /** verifyNotReleased(); */ return _context.clock().now() - _initializeTime; } - public void resetBegin() { _initializeTime = _context.clock().now(); } + public synchronized void resetBegin() { _initializeTime = _context.clock().now(); } /** flag this packet as a particular type for accounting purposes */ - public void markType(int type) { verifyNotReleased(); _markedType = type; } + public synchronized void markType(int type) { verifyNotReleased(); _markedType = type; } /** * flag this packet as a particular type for accounting purposes, with * 1 implying the packet is an ACK, otherwise it is a data packet * */ - public int getMarkedType() { verifyNotReleased(); return _markedType; } + public synchronized int getMarkedType() { verifyNotReleased(); return _markedType; } private int _messageType; private int _fragmentCount; @@ -174,7 +174,7 @@ class UDPPacket implements CDQEntry { /** only for debugging and stats */ void setFragmentCount(int count) { _fragmentCount = count; } - RemoteHostId getRemoteHost() { + synchronized RemoteHostId getRemoteHost() { if (_remoteHost == null) { //long before = System.currentTimeMillis(); InetAddress addr = _packet.getAddress(); @@ -193,7 +193,7 @@ class UDPPacket implements CDQEntry { * MAC matches, false otherwise. * */ - public boolean validate(SessionKey macKey) { + public synchronized boolean validate(SessionKey macKey) { verifyNotReleased(); //_beforeValidate = _context.clock().now(); boolean eq = false; @@ -242,7 +242,7 @@ class UDPPacket implements CDQEntry { } else { Log log = _context.logManager().getLog(UDPPacket.class); if (log.shouldLog(Log.WARN)) - log.warn("Payload length is " + payloadLength + ", too short!\n" + + log.warn("Payload length is " + payloadLength + ", too short! From: " + getRemoteHost() + '\n' + net.i2p.util.HexDump.dump(_data, _packet.getOffset(), _packet.getLength())); } @@ -256,7 +256,7 @@ class UDPPacket implements CDQEntry { * with the decrypted data (leaving the MAC and IV unaltered) * */ - public void decrypt(SessionKey cipherKey) { + public synchronized void decrypt(SessionKey cipherKey) { verifyNotReleased(); System.arraycopy(_data, MAC_SIZE, _ivBuf, 0, IV_SIZE); int len = _packet.getLength(); @@ -279,7 +279,7 @@ class UDPPacket implements CDQEntry { public void setEnqueueTime(long now) { _enqueueTime = now; } /** a packet handler has pulled it off the inbound queue */ - void received() { _receivedTime = _context.clock().now(); } + synchronized void received() { _receivedTime = _context.clock().now(); } /** a packet handler has decrypted and verified the packet and is about to parse out the good bits */ //void beforeReceiveFragments() { _beforeReceiveFragments = _context.clock().now(); } @@ -293,7 +293,7 @@ class UDPPacket implements CDQEntry { public long getEnqueueTime() { return _enqueueTime; } /** a packet handler has pulled it off the inbound queue */ - long getTimeSinceReceived() { return (_receivedTime > 0 ? _context.clock().now() - _receivedTime : 0); } + synchronized long getTimeSinceReceived() { return (_receivedTime > 0 ? _context.clock().now() - _receivedTime : 0); } /** a packet handler has decrypted and verified the packet and is about to parse out the good bits */ //long getTimeSinceReceiveFragments() { return (_beforeReceiveFragments > 0 ? _context.clock().now() - _beforeReceiveFragments : 0); } @@ -343,16 +343,20 @@ class UDPPacket implements CDQEntry { UDPPacket rv = null; if (CACHE) { rv = _packetCache.poll(); - if (rv != null) - rv.init(ctx); + if (rv != null) { + synchronized(rv) { + if (!rv._released) { + Log log = rv._context.logManager().getLog(UDPPacket.class); + log.error("Unreleased cached packet", new Exception()); + rv = null; + } else { + rv.init(ctx); + } + } + } } if (rv == null) rv = new UDPPacket(ctx); - //if (rv._acquiredBy != null) { - // _log.log(Log.CRIT, "Already acquired! current stack trace is:", new Exception()); - // _log.log(Log.CRIT, "Earlier acquired:", rv._acquiredBy); - //} - //rv._acquiredBy = new Exception("acquired on"); return rv; } @@ -364,7 +368,7 @@ class UDPPacket implements CDQEntry { release(); } - public void release() { + public synchronized void release() { verifyNotReleased(); _released = true; //_releasedBy = new Exception("released by"); @@ -385,7 +389,7 @@ class UDPPacket implements CDQEntry { _packetCache.clear(); } - private void verifyNotReleased() { + private synchronized void verifyNotReleased() { if (!CACHE) return; if (_released) { Log log = _context.logManager().getLog(UDPPacket.class); -- GitLab