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 <[email protected]> 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 );
