You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tv...@apache.org on 2020/04/12 17:06:18 UTC

[commons-jcs] 02/03: Better handling of multicast on multihomed machines

This is an automated email from the ASF dual-hosted git repository.

tv pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git

commit f4080fe78f15606df4f13bf2b9dbf893a7e8cb17
Author: Thomas Vandahl <tv...@apache.org>
AuthorDate: Sun Apr 12 19:05:00 2020 +0200

    Better handling of multicast on multihomed machines
---
 .../jcs/utils/discovery/UDPDiscoveryReceiver.java  | 12 ++++-
 .../apache/commons/jcs/utils/net/HostNameUtil.java | 55 ++++++++++++++++++++--
 .../jcs/utils/discovery/UDPDiscoveryUnitTest.java  |  6 +--
 3 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
index 2fbc2eb..0438ee3 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
@@ -25,6 +25,7 @@ import java.io.ObjectInputStream;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
+import java.net.NetworkInterface;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -34,6 +35,7 @@ import org.apache.commons.jcs.io.ObjectInputStreamClassLoaderAware;
 import org.apache.commons.jcs.log.Log;
 import org.apache.commons.jcs.log.LogManager;
 import org.apache.commons.jcs.utils.discovery.UDPDiscoveryMessage.BroadcastType;
+import org.apache.commons.jcs.utils.net.HostNameUtil;
 import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
 import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
 import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
@@ -117,11 +119,17 @@ public class UDPDiscoveryReceiver
         try
         {
             mSocket = new MulticastSocket( multicastPort );
+            InetAddress multicastAddress = InetAddress.getByName( multicastAddressString );
             if (log.isInfoEnabled())
             {
-                log.info( "Joining Group: [{0}]", InetAddress.getByName( multicastAddressString ) );
+                log.info( "Joining Group: [{0}]", multicastAddress );
             }
-            mSocket.joinGroup( InetAddress.getByName( multicastAddressString ) );
+            NetworkInterface multicastInterface = HostNameUtil.getMulticastNetworkInterface();
+            if (multicastInterface != null)
+            {
+                mSocket.setNetworkInterface(multicastInterface);
+            }
+            mSocket.joinGroup( multicastAddress );
         }
         catch ( IOException e )
         {
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/net/HostNameUtil.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/net/HostNameUtil.java
index 4e96e43..2c3bce6 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/net/HostNameUtil.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/net/HostNameUtil.java
@@ -1,12 +1,30 @@
 package org.apache.commons.jcs.utils.net;
 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 import java.net.InetAddress;
 import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.Enumeration;
-
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership.  The ASF licenses this file
@@ -135,7 +153,7 @@ public class HostNameUtil
             }
             return jdkSuppliedAddress;
         }
-        catch ( Exception e )
+        catch ( SocketException e )
         {
             UnknownHostException unknownHostException = new UnknownHostException( "Failed to determine LAN address: "
                 + e );
@@ -143,4 +161,35 @@ public class HostNameUtil
             throw unknownHostException;
         }
     }
+
+    /**
+     * On systems with multiple network interfaces and mixed IPv6/IPv4 get a valid network
+     * interface for binding to multicast
+     *
+     * @return a network interface suitable for multicast
+     * @throws SocketException if a problem occurs while reading the network interfaces
+     */
+    public static NetworkInterface getMulticastNetworkInterface() throws SocketException
+    {
+        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+        while (networkInterfaces.hasMoreElements())
+        {
+            NetworkInterface networkInterface = networkInterfaces.nextElement();
+            Enumeration<InetAddress> addressesFromNetworkInterface = networkInterface.getInetAddresses();
+            while (addressesFromNetworkInterface.hasMoreElements())
+            {
+                InetAddress inetAddress = addressesFromNetworkInterface.nextElement();
+                if (inetAddress.isSiteLocalAddress()
+                        && !inetAddress.isAnyLocalAddress()
+                        && !inetAddress.isLinkLocalAddress()
+                        && !inetAddress.isLoopbackAddress()
+                        && !inetAddress.isMulticastAddress())
+                {
+                    return networkInterface;
+                }
+            }
+        }
+
+        return null;
+    }
 }
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java
index 97af7bf..6a83885 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java
@@ -21,10 +21,10 @@ package org.apache.commons.jcs.utils.discovery;
 
 import java.util.ArrayList;
 
-import junit.framework.TestCase;
-
 import org.apache.commons.jcs.utils.timing.SleepUtil;
 
+import junit.framework.TestCase;
+
 /**
  * Unit tests for discovery
  */
@@ -39,7 +39,7 @@ public class UDPDiscoveryUnitTest
         throws Exception
     {
         UDPDiscoveryAttributes attributes = new UDPDiscoveryAttributes();
-        attributes.setUdpDiscoveryAddr( "228.5.6.7" );
+        attributes.setUdpDiscoveryAddr( /*"FF7E:230::1234"*/ "228.5.6.7" );
         attributes.setUdpDiscoveryPort( 6789 );
         attributes.setServicePort( 1000 );