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