From 5ef93f11a98d0d4f3b7696c332e70efd6215353b Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Tue, 1 Mar 2022 07:25:49 -0500 Subject: [PATCH] Util: Add Addresses.getConnectedAddressTypes() method to efficiently get all types in one pass --- core/java/src/net/i2p/util/Addresses.java | 41 ++++++++++++++++++- core/java/src/net/i2p/util/DNSOverHTTPS.java | 3 +- .../networkdb/reseed/ReseedChecker.java | 5 ++- .../transport/CommSystemFacadeImpl.java | 4 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/core/java/src/net/i2p/util/Addresses.java b/core/java/src/net/i2p/util/Addresses.java index c228954298..a1b3937287 100644 --- a/core/java/src/net/i2p/util/Addresses.java +++ b/core/java/src/net/i2p/util/Addresses.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -57,6 +58,7 @@ public abstract class Addresses { /** * Do we have any address of this type? * Warning, very slow on Windows, appx. 200ms + 50ms/interface + * Use getConnectedAddressTypes() to get all types at once. * * @since 0.9.54 */ @@ -77,6 +79,7 @@ public abstract class Addresses { /** * Do we have any non-loop, non-wildcard IPv4 address at all? * Warning, very slow on Windows, appx. 200ms + 50ms/interface + * Use getConnectedAddressTypes() to get all types at once. * * @since 0.9.4 */ @@ -88,6 +91,7 @@ public abstract class Addresses { /** * Do we have any non-loop, non-wildcard IPv6 address at all? * Warning, very slow on Windows, appx. 200ms + 50ms/interface + * Use getConnectedAddressTypes() to get all types at once. * * @since 0.9.29 */ @@ -313,6 +317,39 @@ public abstract class Addresses { return null; } + /** + * Efficiently get all connected address types in one pass. + * Warning, very slow on Windows. Caller should cache. + * + * @return the set of connected address types, non-null + * @since 0.9.54 + */ + public static Set<AddressType> getConnectedAddressTypes() { + Set<AddressType> rv = EnumSet.noneOf(AddressType.class); + try { + Enumeration<NetworkInterface> ifcs = NetworkInterface.getNetworkInterfaces(); + if (ifcs != null) { + while (ifcs.hasMoreElements()) { + NetworkInterface ifc = ifcs.nextElement(); + if (!ifc.isUp()) + continue; + for(Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements();) { + InetAddress addr = addrs.nextElement(); + byte[] ip = addr.getAddress(); + if (ip.length == 16 && (ip[0] & 0xfe) == 0x02) { + rv.add(AddressType.YGG); + } else if (shouldInclude(addr, true, false, true)) { + rv.add(ip.length == 16 ? AddressType.IPV6 : AddressType.IPV4); + } + } + } + } + } catch (SocketException e) { + } catch (java.lang.Error e) { + } + return rv; + } + /** * Strip the trailing "%nn" from Inet6Address.getHostAddress() * @since IPv6 @@ -901,6 +938,7 @@ public abstract class Addresses { * Print out the local addresses */ public static void main(String[] args) { + System.out.println("Connected Address Types: " + getConnectedAddressTypes() + '\n'); System.out.println("External IPv4 Addresses:"); Set<String> a = getAddresses(false, false, false); print(a); @@ -970,7 +1008,8 @@ public abstract class Addresses { } print(macs); System.out.println("\nHas IPv4? " + isConnected() + - "\nHas IPv6? " + isConnectedIPv6()); + "\nHas IPv6? " + isConnectedIPv6() + + "\nHas Ygg? " + (ygg != null)); System.out.println("Has v6 flags? " + INET6_CACHE_ENABLED); System.out.println("Uses v6 temp? " + getPrivacyStatus()); // Windows 8.1 Java 1.8.0_66 netbook appx. 200ms + 50ms/interface diff --git a/core/java/src/net/i2p/util/DNSOverHTTPS.java b/core/java/src/net/i2p/util/DNSOverHTTPS.java index e406795345..206596237d 100644 --- a/core/java/src/net/i2p/util/DNSOverHTTPS.java +++ b/core/java/src/net/i2p/util/DNSOverHTTPS.java @@ -166,7 +166,8 @@ public class DNSOverHTTPS implements EepGet.StatusListener { * @return null if not found */ public String lookup(String host) { - Type type = (Addresses.isConnected() || !Addresses.isConnectedIPv6()) ? Type.V4_ONLY : Type.V6_ONLY; + Set<AddressType> addrs = Addresses.getConnectedAddressTypes(); + Type type = (addrs.contains(AddressType.IPV4) || !addrs.contains(AddressType.IPV6)) ? Type.V4_ONLY : Type.V6_ONLY; return lookup(host, type); } diff --git a/router/java/src/net/i2p/router/networkdb/reseed/ReseedChecker.java b/router/java/src/net/i2p/router/networkdb/reseed/ReseedChecker.java index b221df4943..d3680a1730 100644 --- a/router/java/src/net/i2p/router/networkdb/reseed/ReseedChecker.java +++ b/router/java/src/net/i2p/router/networkdb/reseed/ReseedChecker.java @@ -4,11 +4,13 @@ import java.io.File; import java.io.InputStream; import java.io.IOException; import java.net.URI; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import net.i2p.data.DataHelper; import net.i2p.router.RouterContext; import net.i2p.util.Addresses; +import net.i2p.util.AddressType; import net.i2p.util.Log; import net.i2p.util.SimpleTimer; @@ -105,7 +107,8 @@ public class ReseedChecker { File noReseedFileAlt2 = new File(_context.getConfigDir(), ".i2pnoreseed"); File noReseedFileAlt3 = new File(_context.getConfigDir(), "noreseed.i2p"); if (!noReseedFile.exists() && !noReseedFileAlt1.exists() && !noReseedFileAlt2.exists() && !noReseedFileAlt3.exists()) { - if (!Addresses.isConnected() && !Addresses.isConnectedIPv6()) { + Set<AddressType> addrs = Addresses.getConnectedAddressTypes(); + if (!addrs.contains(AddressType.IPV4) && !addrs.contains(AddressType.IPV6)) { if (!_networkLogged) { _log.logAlways(Log.WARN, "Cannot reseed, no network connection"); _networkLogged = true; diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index bd42472bae..0114d27725 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -31,6 +31,7 @@ import net.i2p.router.transport.crypto.X25519KeyFactory; import net.i2p.router.transport.udp.UDPTransport; import net.i2p.router.util.EventLog; import net.i2p.util.Addresses; +import net.i2p.util.AddressType; import net.i2p.util.I2PThread; import net.i2p.util.Log; import net.i2p.util.SimpleTimer; @@ -711,7 +712,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade { } public void timeReached() { - boolean good = Addresses.isConnected() || Addresses.isConnectedIPv6(); + Set<AddressType> addrs = Addresses.getConnectedAddressTypes(); + boolean good = addrs.contains(AddressType.IPV4) || addrs.contains(AddressType.IPV6); if (_netMonitorStatus != good) { if (good) _log.logAlways(Log.INFO, "Network reconnected"); -- GitLab