From 48fb12ebeb362139a1b8696d1526e48c6200a537 Mon Sep 17 00:00:00 2001 From: zzz Date: Wed, 29 Mar 2017 12:30:21 +0000 Subject: [PATCH] SSU: Refactor PeerTestEvent out of UDPTransport --- .../i2p/router/transport/TransportImpl.java | 12 +- .../router/transport/udp/PeerTestEvent.java | 146 ++++++++++++++++++ .../router/transport/udp/UDPTransport.java | 141 ++--------------- 3 files changed, 163 insertions(+), 136 deletions(-) create mode 100644 router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java index df9f33adf..f132f47b7 100644 --- a/router/java/src/net/i2p/router/transport/TransportImpl.java +++ b/router/java/src/net/i2p/router/transport/TransportImpl.java @@ -815,18 +815,18 @@ public abstract class TransportImpl implements Transport { /** * This returns true if the force-firewalled setting is configured, false otherwise. * - * @since 0.9.20 + * @since 0.9.20, public since 0.9.30 */ - protected boolean isIPv4Firewalled() { + public boolean isIPv4Firewalled() { return TransportUtil.isIPv4Firewalled(_context, getStyle()); } /** * This returns true if the force-firewalled setting is configured, false otherwise. * - * @since 0.9.27 + * @since 0.9.27, public since 0.9.30 */ - protected boolean isIPv6Firewalled() { + public boolean isIPv6Firewalled() { return TransportUtil.isIPv6Firewalled(_context, getStyle()); } @@ -987,9 +987,9 @@ public abstract class TransportImpl implements Transport { } /** - * @since IPv6 + * @since IPv6, public since 0.9.30 */ - protected TransportUtil.IPv6Config getIPv6Config() { + public TransportUtil.IPv6Config getIPv6Config() { return TransportUtil.getIPv6Config(_context, getStyle()); } diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java b/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java new file mode 100644 index 000000000..e6d0c402a --- /dev/null +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java @@ -0,0 +1,146 @@ +package net.i2p.router.transport.udp; + +import java.util.concurrent.atomic.AtomicLong; + +import net.i2p.router.RouterContext; +import net.i2p.util.Log; +import net.i2p.util.SimpleTimer2; + +import static net.i2p.router.transport.TransportUtil.IPv6Config.*; +import static net.i2p.router.transport.udp.PeerTestState.Role.*; + +/** + * Initiate a test (we are Alice) + * + * @since 0.9.30 moved out of UDPTransport + */ +class PeerTestEvent extends SimpleTimer2.TimedEvent { + private final RouterContext _context; + private final Log _log; + private final UDPTransport _transport; + private final PeerTestManager _testManager; + + private boolean _alive; + /** when did we last test our reachability */ + private final AtomicLong _lastTested = new AtomicLong(); + private final AtomicLong _lastTestedV6 = new AtomicLong(); + private static final int NO_FORCE = 0, FORCE_IPV4 = 1, FORCE_IPV6 = 2; + private int _forceRun; + + private static final int TEST_FREQUENCY = 13*60*1000; + private static final int MIN_TEST_FREQUENCY = 45*1000; + + PeerTestEvent(RouterContext ctx, UDPTransport udp, PeerTestManager ptmgr) { + super(ctx.simpleTimer2()); + _context = ctx; + _log = ctx.logManager().getLog(PeerTestEvent.class); + _transport = udp; + _testManager = ptmgr; + } + + public synchronized void timeReached() { + // just for IPv6 for now + if (shouldTest()) { + long now = _context.clock().now(); + long sinceRunV4 = now - _lastTested.get(); + long sinceRunV6 = now - _lastTestedV6.get(); + if (_forceRun == FORCE_IPV4 && sinceRunV4 >= MIN_TEST_FREQUENCY) { + locked_runTest(false); + } else if (_transport.hasIPv6Address() &&_forceRun == FORCE_IPV6 && sinceRunV6 >= MIN_TEST_FREQUENCY) { + locked_runTest(true); + } else if (sinceRunV4 >= TEST_FREQUENCY && _transport.getIPv6Config() != IPV6_ONLY) { + locked_runTest(false); + } else if (_transport.hasIPv6Address() && sinceRunV6 >= TEST_FREQUENCY) { + locked_runTest(true); + } else { + if (_log.shouldLog(Log.INFO)) + _log.info("PTE timeReached(), no test run, last v4 test: " + new java.util.Date(_lastTested.get()) + + " last v6 test: " + new java.util.Date(_lastTestedV6.get())); + } + } + if (_alive) { + long delay = (TEST_FREQUENCY / 2) + _context.random().nextInt(TEST_FREQUENCY); + // if we have 2 addresses, give IPv6 a chance also + if (_transport.hasIPv6Address() && _transport.getIPv6Config() != IPV6_ONLY) + delay /= 2; + schedule(delay); + } + } + + private void locked_runTest(boolean isIPv6) { + PeerState bob = _transport.pickTestPeer(BOB, isIPv6, null); + if (bob != null) { + if (_log.shouldLog(Log.INFO)) + _log.info("Running periodic test with bob = " + bob); + _testManager.runTest(bob.getRemoteIPAddress(), bob.getRemotePort(), bob.getCurrentCipherKey(), bob.getCurrentMACKey()); + setLastTested(isIPv6); + } else { + if (_log.shouldLog(Log.WARN)) + _log.warn("Unable to run peer test, no peers available - v6? " + isIPv6); + } + _forceRun = NO_FORCE; + } + + /** + * Run within the next 45 seconds at the latest + * @since 0.9.13 + */ + public synchronized void forceRunSoon(boolean isIPv6) { + if (!isIPv6 && _transport.isIPv4Firewalled()) + return; + if (isIPv6 && _transport.isIPv6Firewalled()) + return; + _forceRun = isIPv6 ? FORCE_IPV6 : FORCE_IPV4; + reschedule(MIN_TEST_FREQUENCY); + } + + /** + * + * Run within the next 5 seconds at the latest + * @since 0.9.13 + */ + public synchronized void forceRunImmediately(boolean isIPv6) { + if (!isIPv6 && _transport.isIPv4Firewalled()) + return; + if (isIPv6 && _transport.isIPv6Firewalled()) + return; + if (isIPv6) + _lastTestedV6.set(0); + else + _lastTested.set(0); + _forceRun = isIPv6 ? FORCE_IPV6 : FORCE_IPV4; + reschedule(5*1000); + } + + public synchronized void setIsAlive(boolean isAlive) { + _alive = isAlive; + if (isAlive) { + long delay = _context.random().nextInt(2*TEST_FREQUENCY); + reschedule(delay); + } else { + cancel(); + } + } + + /** + * Set the last-tested timer to now + * @since 0.9.13 + */ + public void setLastTested(boolean isIPv6) { + // do not synchronize - deadlock with PeerTestManager + long now = _context.clock().now(); + if (isIPv6) + _lastTestedV6.set(now); + else + _lastTested.set(now); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("PTE.setLastTested() - v6? " + isIPv6, new Exception()); + } + + private boolean shouldTest() { + return ! (_context.router().isHidden() || + (_transport.isIPv4Firewalled() && _transport.isIPv6Firewalled())); + //String val = _context.getProperty(PROP_SHOULD_TEST); + //return ( (val != null) && ("true".equals(val)) ); + } +} diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 7df924642..d7f55564f 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -75,7 +75,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private volatile PacketPusher _pusher; private final InboundMessageFragments _inboundFragments; //private UDPFlooder _flooder; - private PeerTestManager _testManager; + private final PeerTestManager _testManager; private final IntroductionManager _introManager; private final ExpirePeerEvent _expireEvent; private final PeerTestEvent _testEvent; @@ -195,8 +195,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static final int MAX_CONSECUTIVE_FAILED = 5; public static final int DEFAULT_COST = 5; - private static final int TEST_FREQUENCY = 13*60*1000; - private static final int MIN_TEST_FREQUENCY = 45*1000; static final long[] RATES = { 10*60*1000 }; /** minimum active peers to maintain IP detection, etc. */ private static final int MIN_PEERS = 5; @@ -266,7 +264,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // _flooder = new UDPFlooder(_context, this); _expireTimeout = EXPIRE_TIMEOUT; _expireEvent = new ExpirePeerEvent(); - _testEvent = new PeerTestEvent(); + _testManager = new PeerTestManager(_context, this); + _testEvent = new PeerTestEvent(_context, this, _testManager); _reachabilityStatus = Status.UNKNOWN; _introManager = new IntroductionManager(_context, this); _introducersSelectedOn = -1; @@ -476,9 +475,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (_establisher == null) _establisher = new EstablishmentManager(_context, this); - if (_testManager == null) - _testManager = new PeerTestManager(_context, this); - if (_handler == null) _handler = new PacketHandler(_context, this, _establisher, _inboundFragments, _testManager, _introManager); @@ -667,6 +663,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return null; } + /** + * For PeerTestManager + * @since 0.9.30 + */ + boolean hasIPv6Address() { + return _haveIPv6Address; + } + /** * Is this IP too close to ours to trust it for * things like relaying? @@ -3283,129 +3287,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return null; } - private boolean shouldTest() { - return ! (_context.router().isHidden() || - (isIPv4Firewalled() && isIPv6Firewalled())); - //String val = _context.getProperty(PROP_SHOULD_TEST); - //return ( (val != null) && ("true".equals(val)) ); - } - - /** - * Initiate a test (we are Alice) - */ - private class PeerTestEvent extends SimpleTimer2.TimedEvent { - private boolean _alive; - /** when did we last test our reachability */ - private final AtomicLong _lastTested = new AtomicLong(); - private final AtomicLong _lastTestedV6 = new AtomicLong(); - private static final int NO_FORCE = 0, FORCE_IPV4 = 1, FORCE_IPV6 = 2; - private int _forceRun; - - PeerTestEvent() { - super(_context.simpleTimer2()); - } - - public synchronized void timeReached() { - // just for IPv6 for now - if (shouldTest()) { - long now = _context.clock().now(); - long sinceRunV4 = now - _lastTested.get(); - long sinceRunV6 = now - _lastTestedV6.get(); - if (_forceRun == FORCE_IPV4 && sinceRunV4 >= MIN_TEST_FREQUENCY) { - locked_runTest(false); - } else if (_haveIPv6Address &&_forceRun == FORCE_IPV6 && sinceRunV6 >= MIN_TEST_FREQUENCY) { - locked_runTest(true); - } else if (sinceRunV4 >= TEST_FREQUENCY && getIPv6Config() != IPV6_ONLY) { - locked_runTest(false); - } else if (_haveIPv6Address && sinceRunV6 >= TEST_FREQUENCY) { - locked_runTest(true); - } else { - if (_log.shouldLog(Log.INFO)) - _log.info("PTE timeReached(), no test run, last v4 test: " + new java.util.Date(_lastTested.get()) + - " last v6 test: " + new java.util.Date(_lastTestedV6.get())); - } - } - if (_alive) { - long delay = (TEST_FREQUENCY / 2) + _context.random().nextInt(TEST_FREQUENCY); - // if we have 2 addresses, give IPv6 a chance also - if (_haveIPv6Address && getIPv6Config() != IPV6_ONLY) - delay /= 2; - schedule(delay); - } - } - - private void locked_runTest(boolean isIPv6) { - PeerState bob = pickTestPeer(BOB, isIPv6, null); - if (bob != null) { - if (_log.shouldLog(Log.INFO)) - _log.info("Running periodic test with bob = " + bob); - _testManager.runTest(bob.getRemoteIPAddress(), bob.getRemotePort(), bob.getCurrentCipherKey(), bob.getCurrentMACKey()); - setLastTested(isIPv6); - } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Unable to run peer test, no peers available - v6? " + isIPv6); - } - _forceRun = NO_FORCE; - } - - /** - * Run within the next 45 seconds at the latest - * @since 0.9.13 - */ - public synchronized void forceRunSoon(boolean isIPv6) { - if (!isIPv6 && isIPv4Firewalled()) - return; - if (isIPv6 && isIPv6Firewalled()) - return; - _forceRun = isIPv6 ? FORCE_IPV6 : FORCE_IPV4; - reschedule(MIN_TEST_FREQUENCY); - } - - /** - * - * Run within the next 5 seconds at the latest - * @since 0.9.13 - */ - public synchronized void forceRunImmediately(boolean isIPv6) { - if (!isIPv6 && isIPv4Firewalled()) - return; - if (isIPv6 && isIPv6Firewalled()) - return; - if (isIPv6) - _lastTestedV6.set(0); - else - _lastTested.set(0); - _forceRun = isIPv6 ? FORCE_IPV6 : FORCE_IPV4; - reschedule(5*1000); - } - - public synchronized void setIsAlive(boolean isAlive) { - _alive = isAlive; - if (isAlive) { - long delay = _context.random().nextInt(2*TEST_FREQUENCY); - reschedule(delay); - } else { - cancel(); - } - } - - /** - * Set the last-tested timer to now - * @since 0.9.13 - */ - public void setLastTested(boolean isIPv6) { - // do not synchronize - deadlock with PeerTestManager - long now = _context.clock().now(); - if (isIPv6) - _lastTestedV6.set(now); - else - _lastTested.set(now); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("PTE.setLastTested() - v6? " + isIPv6, new Exception()); - } - - } - /** * Periodically ping the introducers, split out since we need to * do it faster than we rebuild our address.