From 175806115b27ecd4b651240f060933ff520d7e1f Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 29 Jan 2015 20:34:49 +0000 Subject: [PATCH] SSU: - Sort introducers in router address, so we won't force a republish due to a different ordering of the same introducers - Don't publish an address if we need introducers but don't have any, so the user won't see a 'firewalled with inbound NTCP enabled' message --- history.txt | 7 +++- .../src/net/i2p/router/RouterVersion.java | 2 +- .../transport/udp/IntroductionManager.java | 36 ++++++++++++++++--- .../router/transport/udp/UDPTransport.java | 15 ++++++-- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/history.txt b/history.txt index c6da813c3..26436280d 100644 --- a/history.txt +++ b/history.txt @@ -1,5 +1,10 @@ 2015-01-29 zzz - * SSU: Fix replaceExternalAddress churn when firewalled + * SSU: + - Fix replaceExternalAddress churn when firewalled + - Sort introducers in router address, so we won't force a republish + due to a different ordering of the same introducers + - Don't publish an address if we need introducers but don't have any, + so the user won't see a 'firewalled with inbound NTCP enabled' message 2015-01-28 zzz * UPnP: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 7f4edb975..31c35f8c3 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 = 13; + public final static long BUILD = 14; /** for example "-test" */ public final static String EXTRA = ""; 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 951f0c192..53c9cff0c 100644 --- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java +++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java @@ -3,6 +3,7 @@ package net.i2p.router.transport.udp; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -176,6 +177,7 @@ class IntroductionManager { // if not too many to choose from, be less picky if (sz <= howMany + 2) inactivityCutoff -= UDPTransport.EXPIRE_TIMEOUT / 4; + List introducers = new ArrayList(howMany); for (int i = 0; i < sz && found < howMany; i++) { PeerState cur = peers.get((start + i) % sz); RouterInfo ri = _context.netDb().lookupRouterInfoLocally(cur.getRemotePeer()); @@ -222,19 +224,45 @@ class IntroductionManager { byte[] ikey = ura.getIntroKey(); if (ikey == null) continue; - ssuOptions.setProperty(UDPAddress.PROP_INTRO_HOST_PREFIX + found, Addresses.toString(ip)); - ssuOptions.setProperty(UDPAddress.PROP_INTRO_PORT_PREFIX + found, String.valueOf(port)); - ssuOptions.setProperty(UDPAddress.PROP_INTRO_KEY_PREFIX + found, Base64.encode(ikey)); - ssuOptions.setProperty(UDPAddress.PROP_INTRO_TAG_PREFIX + found, String.valueOf(cur.getTheyRelayToUsAs())); + introducers.add(new Introducer(ip, port, ikey, cur.getTheyRelayToUsAs())); found++; } + // we sort them so a change in order only won't happen, and won't cause a republish + Collections.sort(introducers); + for (int i = 0; i < found; i++) { + Introducer in = introducers.get(i); + ssuOptions.setProperty(UDPAddress.PROP_INTRO_HOST_PREFIX + i, in.sip); + ssuOptions.setProperty(UDPAddress.PROP_INTRO_PORT_PREFIX + i, in.sport); + ssuOptions.setProperty(UDPAddress.PROP_INTRO_KEY_PREFIX + i, in.skey); + ssuOptions.setProperty(UDPAddress.PROP_INTRO_TAG_PREFIX + i, in.stag); + } + // FIXME failsafe if found == 0, relax inactivityCutoff and try again? pingIntroducers(); return found; } + /** + * So we can sort them + * @since 0.9.18 + */ + private static class Introducer implements Comparable { + public final String sip, sport, skey, stag; + + public Introducer(byte[] ip, int port, byte[] key, long tag) { + sip = Addresses.toString(ip); + sport = String.valueOf(port); + skey = Base64.encode(key); + stag = String.valueOf(tag); + } + + public int compareTo(Introducer i) { + return skey.compareTo(i.skey); + } + } + /** * Was part of pickInbound(), moved out so we can call it more often * @since 0.8.11 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 bdf4aa893..b64b313c2 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -1878,9 +1878,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority boolean introducersIncluded = false; if (introducersRequired) { - // FIXME intro manager doesn't sort introducers, so - // deepEquals() below can fail even with same introducers. - // Only a problem when we have very very few peers to pick from. + // intro manager now sorts introducers, so + // deepEquals() below will not fail even with same introducers. + // Was only a problem when we had very very few peers to pick from. int found = _introManager.pickInbound(options, PUBLIC_RELAY_COUNT); if (found > 0) { if (_log.shouldLog(Log.INFO)) @@ -1974,6 +1974,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _log.warn("Wanted to rebuild my SSU address, but couldn't specify either the direct or indirect info (needs introducers? " + introducersRequired + ")", new Exception("source")); _needsRebuild = true; + if (hasCurrentAddress()) { + // We must remove current address, otherwise the user will see + // "firewalled with inbound NTCP enabled" warning in console. + // Unfortunately this will remove any IPv6 also, + // but we don't have a method to remove just the IPv4 address. FIXME + replaceAddress(null); + if (allowRebuildRouterInfo) + _context.router().rebuildRouterInfo(); + } return null; } }