diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java b/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java index a9c5dae01..2cdead758 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestEvent.java @@ -6,6 +6,7 @@ import net.i2p.router.RouterContext; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; +import net.i2p.router.CommSystemFacade.Status; import static net.i2p.router.transport.TransportUtil.IPv6Config.*; import static net.i2p.router.transport.udp.PeerTestState.Role.*; @@ -94,6 +95,7 @@ class PeerTestEvent extends SimpleTimer2.TimedEvent { private void locked_runTest(boolean isIPv6) { _lastTestIPv6 = isIPv6; + boolean allowForce = false; PeerState bob = _transport.pickTestPeer(BOB, 0, isIPv6, null); if (bob != null) { if (_log.shouldLog(Log.INFO)) @@ -104,10 +106,73 @@ class PeerTestEvent extends SimpleTimer2.TimedEvent { } else { if (_log.shouldLog(Log.WARN)) _log.warn("Unable to run peer test, no peers available - v6? " + isIPv6); + if (_context.router().getUptime() > 10*60*1000 && + _transport.countPeers() >= UDPTransport.MIN_PEERS && + _transport.getInboundConnectionLastReceived(isIPv6) < _context.clock().now() - 10*60*1000) { + // if we have no test peers at all after 10 minutes, presume firewalled + Status old = _transport.getReachabilityStatus(); + if (isIPv6) { + switch (old) { + case OK: + case IPV4_OK_IPV6_UNKNOWN: + case IPV4_OK_IPV6_FIREWALLED: + case IPV4_UNKNOWN_IPV6_OK: + case IPV4_FIREWALLED_IPV6_OK: + case IPV4_DISABLED_IPV6_OK: + case IPV4_SNAT_IPV6_OK: + case IPV4_SNAT_IPV6_UNKNOWN: + case IPV4_FIREWALLED_IPV6_UNKNOWN: + case REJECT_UNSOLICITED: + case IPV4_UNKNOWN_IPV6_FIREWALLED: + case IPV4_DISABLED_IPV6_UNKNOWN: + case IPV4_DISABLED_IPV6_FIREWALLED: + case UNKNOWN: + Status status = Status.IPV4_UNKNOWN_IPV6_FIREWALLED; + if (_log.shouldWarn()) + _log.warn("Old status: " + old + " new status: " + status); + _transport.setReachabilityStatus(status, isIPv6); + allowForce = true; + break; + + default: + // SYMNAT, DISCONNECTED, HOSED, ... + if (_log.shouldWarn()) + _log.warn("Not changing current status: " + old); + break; + } + } else { + switch (old) { + case OK: + case IPV4_OK_IPV6_UNKNOWN: + case IPV4_OK_IPV6_FIREWALLED: + case IPV4_UNKNOWN_IPV6_OK: + case IPV4_FIREWALLED_IPV6_OK: + case IPV4_DISABLED_IPV6_OK: + case IPV4_FIREWALLED_IPV6_UNKNOWN: + case REJECT_UNSOLICITED: + case IPV4_UNKNOWN_IPV6_FIREWALLED: + case IPV4_DISABLED_IPV6_UNKNOWN: + case IPV4_DISABLED_IPV6_FIREWALLED: + case UNKNOWN: + Status status = Status.IPV4_FIREWALLED_IPV6_UNKNOWN; + if (_log.shouldWarn()) + _log.warn("Old status: " + old + " new status: " + status); + _transport.setReachabilityStatus(status, isIPv6); + allowForce = true; + break; + + default: + if (_log.shouldWarn()) + _log.warn("Not changing current status: " + old); + break; + } + } + } } - // We switch to NO_FORCE even if no peers, + // We switch to NO_FORCE unless no peers, // so we don't get stuck running the same test over and over - _forceRun &= ~(isIPv6 ? FORCE_IPV6 : FORCE_IPV4); + if (!allowForce) + _forceRun &= ~(isIPv6 ? FORCE_IPV6 : FORCE_IPV4); } /** 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 3eaab96a6..7aecd4d0c 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -236,7 +236,7 @@ public class UDPTransport extends TransportImpl { private static final int SSU_OUTBOUND_COST = 14; static final long[] RATES = { 10*60*1000 }; /** minimum active peers to maintain IP detection, etc. */ - private static final int MIN_PEERS = 5; + static final int MIN_PEERS = 10; private static final int MIN_PEERS_IF_HAVE_V6 = 30; /** minimum peers volunteering to be introducers if we need that */ private static final int MIN_INTRODUCER_POOL = 5; @@ -1155,12 +1155,18 @@ public class UDPTransport extends TransportImpl { } else { // Introduced connections are still inbound, this is not evidence // that we are not firewalled. - // use OS clock since its an ordering thing, not a time thing - _lastInboundReceivedOn = System.currentTimeMillis(); + _lastInboundReceivedOn = _context.clock().now(); _context.statManager().addRateData("udp.inboundIPv4Conn", 1); } } - + + /** + * @since 0.9.69 + */ + long getInboundConnectionLastReceived(boolean isIPv6) { + return isIPv6 ? _lastInboundIPv6 : _lastInboundReceivedOn; + } + // temp prevent multiples private boolean gotIPv4Addr = false; private boolean gotIPv6Addr = false; @@ -1309,7 +1315,7 @@ public class UDPTransport extends TransportImpl { boolean inboundRecent; boolean isIPv6 = ourIP.length == 16; if (!isIPv6) - inboundRecent = _lastInboundReceivedOn + ALLOW_IP_CHANGE_INTERVAL > System.currentTimeMillis(); + inboundRecent = _lastInboundReceivedOn + ALLOW_IP_CHANGE_INTERVAL > _context.clock().now(); else inboundRecent = _lastInboundIPv6 + ALLOW_IP_CHANGE_INTERVAL > _context.clock().now(); if (_log.shouldLog(Log.INFO))