Skip to content

Commit 8683da7

Browse files
chickenljralf0131
authored andcommitted
Multicast ipv6 support for branch 2.6.x (#3430)
* Multicast demo fails with message "Can't assign requested address * remove useless code * Fix multicast registry ut
1 parent 00a8edc commit 8683da7

File tree

3 files changed

+111
-26
lines changed

3 files changed

+111
-26
lines changed

dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/NetUtils.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
import com.alibaba.dubbo.common.logger.LoggerFactory;
2222

2323
import java.io.IOException;
24+
import java.net.Inet4Address;
25+
import java.net.Inet6Address;
2426
import java.net.InetAddress;
2527
import java.net.InetSocketAddress;
28+
import java.net.MulticastSocket;
2629
import java.net.NetworkInterface;
2730
import java.net.ServerSocket;
2831
import java.net.UnknownHostException;
@@ -284,4 +287,34 @@ public static String toURL(String protocol, String host, int port, String path)
284287
return sb.toString();
285288
}
286289

290+
public static void joinMulticastGroup(MulticastSocket multicastSocket, InetAddress multicastAddress) throws IOException {
291+
setInterface(multicastSocket, multicastAddress instanceof Inet6Address);
292+
multicastSocket.setLoopbackMode(false);
293+
multicastSocket.joinGroup(multicastAddress);
294+
}
295+
296+
public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException {
297+
boolean interfaceSet = false;
298+
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
299+
while (interfaces.hasMoreElements()) {
300+
NetworkInterface i = (NetworkInterface) interfaces.nextElement();
301+
Enumeration addresses = i.getInetAddresses();
302+
while (addresses.hasMoreElements()) {
303+
InetAddress address = (InetAddress) addresses.nextElement();
304+
if (preferIpv6 && address instanceof Inet6Address) {
305+
multicastSocket.setInterface(address);
306+
interfaceSet = true;
307+
break;
308+
} else if (!preferIpv6 && address instanceof Inet4Address) {
309+
multicastSocket.setInterface(address);
310+
interfaceSet = true;
311+
break;
312+
}
313+
}
314+
if (interfaceSet) {
315+
break;
316+
}
317+
}
318+
}
319+
287320
}

dubbo-registry/dubbo-registry-multicast/src/main/java/com/alibaba/dubbo/registry/multicast/MulticastRegistry.java

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
import java.io.IOException;
3333
import java.net.DatagramPacket;
34+
import java.net.Inet4Address;
3435
import java.net.InetAddress;
3536
import java.net.InetSocketAddress;
3637
import java.net.MulticastSocket;
@@ -58,11 +59,11 @@ public class MulticastRegistry extends FailbackRegistry {
5859

5960
private static final int DEFAULT_MULTICAST_PORT = 1234;
6061

61-
private final InetAddress mutilcastAddress;
62+
private final InetAddress multicastAddress;
6263

63-
private final MulticastSocket mutilcastSocket;
64+
private final MulticastSocket multicastSocket;
6465

65-
private final int mutilcastPort;
66+
private final int multicastPort;
6667

6768
private final ConcurrentMap<URL, Set<URL>> received = new ConcurrentHashMap<URL, Set<URL>>();
6869

@@ -79,23 +80,21 @@ public MulticastRegistry(URL url) {
7980
if (url.isAnyHost()) {
8081
throw new IllegalStateException("registry address == null");
8182
}
82-
if (!isMulticastAddress(url.getHost())) {
83-
throw new IllegalArgumentException("Invalid multicast address " + url.getHost() + ", scope: 224.0.0.0 - 239.255.255.255");
84-
}
8583
try {
86-
mutilcastAddress = InetAddress.getByName(url.getHost());
87-
mutilcastPort = url.getPort() <= 0 ? DEFAULT_MULTICAST_PORT : url.getPort();
88-
mutilcastSocket = new MulticastSocket(mutilcastPort);
89-
mutilcastSocket.setLoopbackMode(false);
90-
mutilcastSocket.joinGroup(mutilcastAddress);
84+
multicastAddress = InetAddress.getByName(url.getHost());
85+
checkMulticastAddress(multicastAddress);
86+
87+
multicastPort = url.getPort() <= 0 ? DEFAULT_MULTICAST_PORT : url.getPort();
88+
multicastSocket = new MulticastSocket(multicastPort);
89+
NetUtils.joinMulticastGroup(multicastSocket, multicastAddress);
9190
Thread thread = new Thread(new Runnable() {
9291
@Override
9392
public void run() {
9493
byte[] buf = new byte[2048];
9594
DatagramPacket recv = new DatagramPacket(buf, buf.length);
96-
while (!mutilcastSocket.isClosed()) {
95+
while (!multicastSocket.isClosed()) {
9796
try {
98-
mutilcastSocket.receive(recv);
97+
multicastSocket.receive(recv);
9998
String msg = new String(recv.getData()).trim();
10099
int i = msg.indexOf('\n');
101100
if (i > 0) {
@@ -104,7 +103,7 @@ public void run() {
104103
MulticastRegistry.this.receive(msg, (InetSocketAddress) recv.getSocketAddress());
105104
Arrays.fill(buf, (byte) 0);
106105
} catch (Throwable e) {
107-
if (!mutilcastSocket.isClosed()) {
106+
if (!multicastSocket.isClosed()) {
108107
logger.error(e.getMessage(), e);
109108
}
110109
}
@@ -133,6 +132,19 @@ public void run() {
133132
}
134133
}
135134

135+
private void checkMulticastAddress(InetAddress multicastAddress) {
136+
if (!multicastAddress.isMulticastAddress()) {
137+
String message = "Invalid multicast address " + multicastAddress;
138+
if (!(multicastAddress instanceof Inet4Address)) {
139+
throw new IllegalArgumentException(message + ", " +
140+
"ipv4 multicast address scope: 224.0.0.0 - 239.255.255.255.");
141+
} else {
142+
throw new IllegalArgumentException(message + ", " + "ipv6 multicast address must start with ff, " +
143+
"for example: ff01::1");
144+
}
145+
}
146+
}
147+
136148
private static boolean isMulticastAddress(String ip) {
137149
int i = ip.indexOf('.');
138150
if (i > 0) {
@@ -233,25 +245,25 @@ private void receive(String msg, InetSocketAddress remoteAddress) {
233245

234246
private void broadcast(String msg) {
235247
if (logger.isInfoEnabled()) {
236-
logger.info("Send broadcast message: " + msg + " to " + mutilcastAddress + ":" + mutilcastPort);
248+
logger.info("Send broadcast message: " + msg + " to " + multicastAddress + ":" + multicastPort);
237249
}
238250
try {
239251
byte[] data = (msg + "\n").getBytes();
240-
DatagramPacket hi = new DatagramPacket(data, data.length, mutilcastAddress, mutilcastPort);
241-
mutilcastSocket.send(hi);
252+
DatagramPacket hi = new DatagramPacket(data, data.length, multicastAddress, multicastPort);
253+
multicastSocket.send(hi);
242254
} catch (Exception e) {
243255
throw new IllegalStateException(e.getMessage(), e);
244256
}
245257
}
246258

247259
private void unicast(String msg, String host) {
248260
if (logger.isInfoEnabled()) {
249-
logger.info("Send unicast message: " + msg + " to " + host + ":" + mutilcastPort);
261+
logger.info("Send unicast message: " + msg + " to " + host + ":" + multicastPort);
250262
}
251263
try {
252264
byte[] data = (msg + "\n").getBytes();
253-
DatagramPacket hi = new DatagramPacket(data, data.length, InetAddress.getByName(host), mutilcastPort);
254-
mutilcastSocket.send(hi);
265+
DatagramPacket hi = new DatagramPacket(data, data.length, InetAddress.getByName(host), multicastPort);
266+
multicastSocket.send(hi);
255267
} catch (Exception e) {
256268
throw new IllegalStateException(e.getMessage(), e);
257269
}
@@ -293,7 +305,7 @@ protected void doUnsubscribe(URL url, NotifyListener listener) {
293305
@Override
294306
public boolean isAvailable() {
295307
try {
296-
return mutilcastSocket != null;
308+
return multicastSocket != null;
297309
} catch (Throwable t) {
298310
return false;
299311
}
@@ -310,8 +322,8 @@ public void destroy() {
310322
logger.warn(t.getMessage(), t);
311323
}
312324
try {
313-
mutilcastSocket.leaveGroup(mutilcastAddress);
314-
mutilcastSocket.close();
325+
multicastSocket.leaveGroup(multicastAddress);
326+
multicastSocket.close();
315327
} catch (Throwable t) {
316328
logger.warn(t.getMessage(), t);
317329
}
@@ -434,7 +446,7 @@ public List<URL> lookup(URL url) {
434446
}
435447

436448
public MulticastSocket getMutilcastSocket() {
437-
return mutilcastSocket;
449+
return multicastSocket;
438450
}
439451

440452
public Map<URL, Set<URL>> getReceived() {

dubbo-registry/dubbo-registry-multicast/src/test/java/com/alibaba/dubbo/registry/multicast/MulticastRegistryTest.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@
2323
import org.junit.Before;
2424
import org.junit.Test;
2525

26+
import java.net.InetAddress;
2627
import java.net.MulticastSocket;
2728
import java.util.List;
2829
import java.util.Map;
2930
import java.util.Set;
3031
import java.util.concurrent.atomic.AtomicReference;
3132

3233
import static org.hamcrest.CoreMatchers.is;
34+
import static org.junit.Assert.assertEquals;
3335
import static org.junit.Assert.assertThat;
3436
import static org.junit.Assert.assertTrue;
35-
import static org.junit.Assert.assertEquals;
3637

3738
public class MulticastRegistryTest {
3839

@@ -52,7 +53,7 @@ public void setUp() throws Exception {
5253
registry.register(serviceUrl);
5354
}
5455

55-
@Test(expected = IllegalArgumentException.class)
56+
@Test(expected = IllegalStateException.class)
5657
public void testUrlError() {
5758
URL errorUrl = URL.valueOf("multicast://mullticast/");
5859
new MulticastRegistry(errorUrl);
@@ -124,4 +125,43 @@ public void testDefaultPort() {
124125
}
125126
}
126127

128+
@Test
129+
public void testMulticastAddress() {
130+
InetAddress multicastAddress = null;
131+
MulticastSocket multicastSocket = null;
132+
try {
133+
// ipv4 multicast address
134+
multicastAddress = InetAddress.getByName("224.55.66.77");
135+
multicastSocket = new MulticastSocket(2345);
136+
multicastSocket.setLoopbackMode(false);
137+
NetUtils.setInterface(multicastSocket, false);
138+
multicastSocket.joinGroup(multicastAddress);
139+
} catch (Exception e) {
140+
e.printStackTrace();
141+
Assert.fail(e.getMessage());
142+
} finally {
143+
if (multicastSocket != null) {
144+
multicastSocket.close();
145+
}
146+
}
147+
148+
// multicast ipv6 address,
149+
try {
150+
multicastAddress = InetAddress.getByName("ff01::1");
151+
152+
multicastSocket = new MulticastSocket();
153+
multicastSocket.setLoopbackMode(false);
154+
NetUtils.setInterface(multicastSocket, true);
155+
multicastSocket.joinGroup(multicastAddress);
156+
} catch (Throwable t) {
157+
t.printStackTrace();
158+
} finally {
159+
if (multicastSocket != null) {
160+
multicastSocket.close();
161+
}
162+
}
163+
164+
}
165+
166+
127167
}

0 commit comments

Comments
 (0)