diff --git a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java index 2e3329a8f..0fe2f96a0 100644 --- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java +++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java @@ -23,9 +23,9 @@ public class IntroductionManager { private UDPTransport _transport; private PacketBuilder _builder; /** map of relay tag to PeerState that should receive the introduction */ - private Map _outbound; + private Map _outbound; /** list of peers (PeerState) who have given us introduction tags */ - private final List _inbound; + private final List _inbound; public IntroductionManager(RouterContext ctx, UDPTransport transport) { _context = ctx; @@ -74,7 +74,7 @@ public class IntroductionManager { } public PeerState get(long id) { - return (PeerState)_outbound.get(new Long(id)); + return _outbound.get(new Long(id)); } /** @@ -90,7 +90,7 @@ public class IntroductionManager { * and we want to keep our introducers valid. */ public int pickInbound(Properties ssuOptions, int howMany) { - List peers = null; + List peers = null; int start = _context.random().nextInt(Integer.MAX_VALUE); synchronized (_inbound) { if (_log.shouldLog(Log.DEBUG)) @@ -103,7 +103,7 @@ public class IntroductionManager { int found = 0; long inactivityCutoff = _context.clock().now() - (UDPTransport.EXPIRE_TIMEOUT / 2); for (int i = 0; i < sz && found < howMany; i++) { - PeerState cur = (PeerState)peers.get((start + i) % sz); + PeerState cur = peers.get((start + i) % sz); RouterInfo ri = _context.netDb().lookupRouterInfoLocally(cur.getRemotePeer()); if (ri == null) { if (_log.shouldLog(Log.INFO)) @@ -144,7 +144,7 @@ public class IntroductionManager { long pingCutoff = _context.clock().now() - (2 * 60 * 60 * 1000); inactivityCutoff = _context.clock().now() - (UDPTransport.EXPIRE_TIMEOUT / 4); for (int i = 0; i < sz; i++) { - PeerState cur = (PeerState)peers.get(i); + PeerState cur = peers.get(i); if (cur.getIntroducerTime() > pingCutoff && cur.getLastSendTime() < inactivityCutoff) { if (_log.shouldLog(Log.INFO)) @@ -157,6 +157,18 @@ public class IntroductionManager { return found; } + /** + * Not as elaborate as pickInbound() above. + * Just a quick check to see how many volunteers we know, + * which the Transport uses to see if we need more. + * @return number of peers that have volunteerd to introduce us + */ + int introducerCount() { + synchronized(_inbound) { + return _inbound.size(); + } + } + void receiveRelayIntro(RemoteHostId bob, UDPPacketReader reader) { if (_context.router().isHidden()) return; 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 7bc5990b9..2868440e9 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -461,13 +461,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority boolean updated = false; boolean fireTest = false; + if (_log.shouldLog(Log.WARN)) + _log.warn("Change address? status = " + _reachabilityStatus + + " diff = " + (_context.clock().now() - _reachabilityStatusLastUpdated) + + " old = " + _externalListenHost + ':' + _externalListenPort + + " new = " + DataHelper.toString(ourIP) + ':' + ourPort); + synchronized (this) { if ( (_externalListenHost == null) || (!eq(_externalListenHost.getAddress(), _externalListenPort, ourIP, ourPort)) ) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Change address? status = " + _reachabilityStatus + - " diff = " + (_context.clock().now() - _reachabilityStatusLastUpdated) + - " old = " + _externalListenHost + ':' + _externalListenPort); if ( (_reachabilityStatus != CommSystemFacade.STATUS_OK) || (_externalListenHost == null) || (_externalListenPort <= 0) || (_context.clock().now() - _reachabilityStatusLastUpdated > 2*TEST_FREQUENCY) ) { @@ -968,6 +970,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return _endpoint.send(packet); } + /** minimum active peers to maintain IP detection, etc. */ + private static final int MIN_PEERS = 3; + /** minimum peers volunteering to be introducers if we need that */ + private static final int MIN_INTRODUCER_POOL = 4; + public TransportBid bid(RouterInfo toAddress, long dataSize) { if (dataSize > OutboundMessageState.MAX_MSG_SIZE) { // NTCP max is lower, so msg will get dropped @@ -1015,11 +1022,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // Try to maintain at least 3 peers so we can determine our IP address and // we have a selection to run peer tests with. + // If we are firewalled, and we don't have enough peers that volunteered to + // also introduce us, also bid aggressively so we are preferred over NTCP. + // (Otherwise we only talk UDP to those that are firewalled, and we will + // never get any introducers) int count; synchronized (_peersByIdent) { count = _peersByIdent.size(); } - if (alwaysPreferUDP() || count < 3) + if (alwaysPreferUDP() || count < MIN_PEERS || + (introducersRequired() && _introManager.introducerCount() < MIN_INTRODUCER_POOL)) return _slowPreferredBid; else if (preferUDP()) return _slowBid; @@ -1157,6 +1169,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _log.info("Picked peers: " + found); _introducersSelectedOn = _context.clock().now(); introducersIncluded = true; + } else { + if (_log.shouldLog(Log.WARN)) + _log.warn("Need introducers but we don't know any"); } }