diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java index d5f43c6b55da35696b5914f1e5150441e6d4aaee..54c373e471f7ff8b2c8eaca377b70393e7090cc3 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java @@ -636,8 +636,8 @@ class BuildExecutor implements Runnable { long requestedOn = rv.getExpiration() - 10*60*1000; long rtt = _context.clock().now() - requestedOn; _context.statManager().addRateData("tunnel.buildReplySlow", rtt, 0); - if (_log.shouldLog(Log.WARN)) - _log.warn("Got reply late (rtt = " + rtt + ") for: " + rv); + if (_log.shouldInfo()) + _log.info("Got reply late (rtt = " + rtt + ") for: " + rv); } return rv; } diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java index fa7105e55a727a4964e56b62069c5e484d8a771e..6b590ea5fa2f88b6d6b5c63608d1b9f6639b947a 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java @@ -28,6 +28,7 @@ import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.transport.TransportUtil; import net.i2p.router.util.HashDistance; import net.i2p.util.Log; +import net.i2p.util.SystemVersion; import net.i2p.util.VersionComparator; /** @@ -37,6 +38,8 @@ import net.i2p.util.VersionComparator; */ public abstract class TunnelPeerSelector extends ConnectChecker { + private static final String DEFAULT_EXCLUDE_CAPS = String.valueOf(Router.CAPABILITY_BW12); + protected TunnelPeerSelector(RouterContext context) { super(context); } @@ -210,26 +213,23 @@ public abstract class TunnelPeerSelector extends ConnectChecker { // We could just try and exclude them as the inbound gateway but that's harder // (and even worse for anonymity?). // - // Defaults changed to true for inbound only in filterUnreachable below. Set<Hash> peers = new HashSet<Hash>(8); peers.addAll(ctx.profileOrganizer().selectPeersRecentlyRejecting()); peers.addAll(ctx.tunnelManager().selectPeersInTooManyTunnels()); - // if (false && filterUnreachable(ctx, isInbound, isExploratory)) { if (filterUnreachable(isInbound, isExploratory)) { - // NOTE: filterUnreachable returns true for inbound, false for outbound // This is the only use for getPeersByCapability? And the whole set of datastructures in PeerManager? Collection<Hash> caps = ctx.peerManager().getPeersByCapability(Router.CAPABILITY_UNREACHABLE); if (caps != null) peers.addAll(caps); - caps = ctx.profileOrganizer().selectPeersLocallyUnreachable(); - if (caps != null) - peers.addAll(caps); } + Collection<Hash> local = ctx.profileOrganizer().selectPeersLocallyUnreachable(); + if (local != null) + peers.addAll(local); if (filterSlow(isInbound, isExploratory)) { // NOTE: filterSlow always returns true - char excl[] = getExcludeCaps(ctx); - if (excl != null) { + String excl = getExcludeCaps(ctx); + FloodfillNetworkDatabaseFacade fac = (FloodfillNetworkDatabaseFacade)ctx.netDb(); List<RouterInfo> known = fac.getKnownRouterData(); if (known != null) { @@ -334,7 +334,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker { peers.addAll(matches); } */ - } + } return peers; } @@ -367,7 +367,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker { /** * Should we allow as IBGW? - * This just checks for IPv4 support. + * This just checks for the "R" capability and IPv4 support. * Will return false for hidden or IPv6-only. * This is intended for tunnel candidates, where we already have * the RI. Will not force RI lookups. @@ -379,6 +379,8 @@ public abstract class TunnelPeerSelector extends ConnectChecker { RouterInfo ri = ctx.netDb().lookupRouterInfoLocally(h); if (ri == null) return true; + if (ri.getCapabilities().indexOf(Router.CAPABILITY_REACHABLE) < 0) + return false; return canConnect(ANY_V4, ri); } @@ -452,25 +454,21 @@ public abstract class TunnelPeerSelector extends ConnectChecker { return shouldExclude(peer, getExcludeCaps(ctx)); } - private static char[] getExcludeCaps(RouterContext ctx) { - String excludeCaps = ctx.getProperty("router.excludePeerCaps", - String.valueOf(Router.CAPABILITY_BW12)); - if (excludeCaps != null) { - char excl[] = excludeCaps.toCharArray(); - return excl; - } else { - return null; - } + /** + * @return non-null, possibly empty + */ + private static String getExcludeCaps(RouterContext ctx) { + return ctx.getProperty("router.excludePeerCaps", DEFAULT_EXCLUDE_CAPS); } /** NTCP2 */ private static final String MIN_VERSION = "0.9.36"; /** warning, this is also called by ProfileOrganizer.isSelectable() */ - private static boolean shouldExclude(RouterInfo peer, char excl[]) { + private static boolean shouldExclude(RouterInfo peer, String excl) { String cap = peer.getCapabilities(); - for (int j = 0; j < excl.length; j++) { - if (cap.indexOf(excl[j]) >= 0) { + for (int j = 0; j < excl.length(); j++) { + if (cap.indexOf(excl.charAt(j)) >= 0) { return true; } } @@ -562,24 +560,32 @@ public abstract class TunnelPeerSelector extends ConnectChecker { private static final boolean DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false; private static final boolean DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = false; // see comments at getExclude() above - private static final boolean DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = true; - private static final boolean DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = true; + private static final boolean DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false; + private static final boolean DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = false; /** - * do we want to skip peers who haven't been up for long? - * @return true for inbound, false for outbound, unless configured otherwise + * do we want to skip unreachable peers? + * @return true if yes */ - protected boolean filterUnreachable(boolean isInbound, boolean isExploratory) { + private boolean filterUnreachable(boolean isInbound, boolean isExploratory) { + if (SystemVersion.isSlow() || ctx.router().getUptime() < 65*60*1000) + return true; if (isExploratory) { - if (isInbound) + if (isInbound) { + if (ctx.router().isHidden()) + return true; return ctx.getProperty(PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE); - else + } else { return ctx.getProperty(PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE); + } } else { - if (isInbound) + if (isInbound) { + if (ctx.router().isHidden()) + return true; return ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE); - else + } else { return ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE); + } } } @@ -682,7 +688,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker { * Connectivity check. * Check that each hop can connect to the next, including us. * Check that the OBEP is not IPv6-only, and the IBGW is - * not hidden or IPv6-only. + * reachable and not hidden or IPv6-only. * Tells the profile manager to blame the hop, and returns false on failure. * * @param tunnel ENDPOINT FIRST, GATEWAY LAST!!!!, length 2 or greater @@ -696,7 +702,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker { Hash h = tunnel.get(tunnel.size() - 1); if (!allowAsIBGW(h)) { if (log.shouldWarn()) - log.warn("Picked IPv6-only or hidden peer for IBGW: " + h); + log.warn("Picked IPv6-only or unreachable peer for IBGW: " + h); // treat as a timeout in the profile // tunnelRejected() would set the last heard from time ctx.profileManager().tunnelTimedOut(h); diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java index 47d1f3f00e7797bc3d014bcfd7cc22b77c94c7bd..d3edfe311cfd5eb40a081ca1219578b01b196f06 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java @@ -735,8 +735,8 @@ public class TunnelPool { int wanted = Math.min(_settings.getQuantity(), LeaseSet.MAX_LEASES); if (_tunnels.size() < wanted) { - if (_log.shouldLog(Log.WARN)) - _log.warn(toString() + ": Not enough tunnels (" + _tunnels.size() + ", wanted " + wanted + ")"); + if (_log.shouldInfo()) + _log.info(toString() + ": Not enough tunnels (" + _tunnels.size() + ", wanted " + wanted + ")"); // see comment below if (_tunnels.isEmpty()) return null; @@ -797,8 +797,8 @@ public class TunnelPool { // So we will generate a succession of leases at startup. That's OK. // Do we want a config option for this, or are there times when we shouldn't do this? if (leases.size() < wanted) { - if (_log.shouldLog(Log.WARN)) - _log.warn(toString() + ": Not enough leases (" + leases.size() + ", wanted " + wanted + ")"); + if (_log.shouldInfo()) + _log.info(toString() + ": Not enough leases (" + leases.size() + ", wanted " + wanted + ")"); if (leases.isEmpty()) return null; }