1aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller/*
2aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * Copyright (C) 2016 The Android Open Source Project
3aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller *
4aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
5aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * you may not use this file except in compliance with the License.
6aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * You may obtain a copy of the License at
7aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller *
8aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
9aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller *
10aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * Unless required by applicable law or agreed to in writing, software
11aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
12aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * See the License for the specific language governing permissions and
14aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * limitations under the License
15aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller */
16aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
17aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerpackage libcore.java.nio.channels;
18aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
19aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport junit.framework.AssertionFailedError;
20aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport junit.framework.TestCase;
21aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.io.IOException;
22aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.Inet4Address;
23aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.Inet6Address;
24aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.InetAddress;
25aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.InetSocketAddress;
26aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.InterfaceAddress;
27aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.NetworkInterface;
28aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.SocketAddress;
29aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.SocketException;
30d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kongimport java.net.SocketTimeoutException;
31aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.net.StandardSocketOptions;
32aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.nio.ByteBuffer;
33aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.nio.channels.ClosedChannelException;
34aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.nio.channels.DatagramChannel;
35aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.nio.channels.MembershipKey;
36aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.util.ArrayList;
37aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerimport java.util.Enumeration;
38aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
39d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kongimport libcore.io.IoBridge;
40d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong
416a68248983b32c8fe6e6c330ac8e09853b4e61b1Yi Kongimport static android.system.OsConstants.POLLIN;
426a68248983b32c8fe6e6c330ac8e09853b4e61b1Yi Kong
43aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller/**
44aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * Tests associated with multicast behavior of DatagramChannel.
45aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller * These tests require IPv6 multicasting enabled network.
46aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller */
47aea78555169709a2586b585e61414d9aee1d8e28Neil Fullerpublic class DatagramChannelMulticastTest extends TestCase {
48aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
49aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static InetAddress lookup(String s) {
50aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
51aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            return InetAddress.getByName(s);
52aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IOException ex) {
53aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throw new RuntimeException(ex);
54aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
55aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
56aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
57aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    // These IP addresses aren't inherently "good" or "bad"; they're just used like that.
58aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    // We use the "good" addresses for our actual group, and the "bad" addresses are for
59aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    // a group that we won't actually set up.
60aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress GOOD_MULTICAST_IPv4 = lookup("239.255.0.1");
61aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress BAD_MULTICAST_IPv4 = lookup("239.255.0.2");
62aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress GOOD_MULTICAST_IPv6 = lookup("ff05::7:7");
63aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress BAD_MULTICAST_IPv6 = lookup("ff05::7:8");
64aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
65aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    // Special addresses.
66aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress WILDCARD_IPv4 = lookup("0.0.0.0");
67aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress WILDCARD_IPv6 = lookup("::");
68aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
69aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    // Arbitrary unicast addresses. Used when the value doesn't actually matter. e.g. for source
70aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    // filters.
71aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress UNICAST_IPv4_1 = lookup("192.168.1.1");
72aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress UNICAST_IPv4_2 = lookup("192.168.1.2");
73aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress UNICAST_IPv6_1 = lookup("2001:db8::1");
74aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static final InetAddress UNICAST_IPv6_2 = lookup("2001:db8::2");
75aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
76d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera    private NetworkInterface ipv4NetworkInterface;
77d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera    private NetworkInterface ipv6NetworkInterface;
78aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private NetworkInterface loopbackInterface;
79aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
80d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera    private boolean supportsMulticast;
81d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera
82aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    @Override
83aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    protected void setUp() throws Exception {
84aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // The loopback interface isn't actually useful for sending/receiving multicast messages
85aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // but it can be used as a dummy for tests where that does not matter.
86aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
87aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNotNull(loopbackInterface);
88aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(loopbackInterface.isLoopback());
89aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(loopbackInterface.supportsMulticast());
90aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
91aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
92aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
93d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        // Determine if the device is marked to support multicast or not. If this propery is not
94d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        // set we assume the device has an interface capable of supporting multicast.
95d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        supportsMulticast = Boolean.parseBoolean(
96d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                System.getProperty("android.cts.device.multicast", "true"));
97d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
98d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
99d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
100aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
101d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        while (interfaces.hasMoreElements()
102d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
103d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface nextInterface = interfaces.nextElement();
104d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            if (willWorkForMulticast(nextInterface)) {
105d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
106d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                while (addresses.hasMoreElements()) {
107d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    final InetAddress nextAddress = addresses.nextElement();
108d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
109d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                        ipv6NetworkInterface = nextInterface;
110d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    } else if (nextAddress instanceof Inet4Address
111d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                            && ipv4NetworkInterface == null) {
112d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                        ipv4NetworkInterface = nextInterface;
113aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                    }
114aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                }
115aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
116aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
117d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera
118d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (ipv4NetworkInterface == null) {
119d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            fail("Test environment must have at least one network interface capable of IPv4"
120d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    + " multicast");
121d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
122d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (ipv6NetworkInterface == null) {
123d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            fail("Test environment must have at least one network interface capable of IPv6"
124d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    + " multicast");
125d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
126aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
127aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
128aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_open() throws IOException {
129aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = DatagramChannel.open();
130aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
131aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Unlike MulticastSocket, DatagramChannel has SO_REUSEADDR set to false by default.
132aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(dc.getOption(StandardSocketOptions.SO_REUSEADDR));
133aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
134aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(dc.getLocalAddress());
135aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(dc.isOpen());
136aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(dc.isConnected());
137aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
138aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
139aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_bind_null() throws Exception {
140aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
141aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNotNull(dc.getLocalAddress());
142aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(dc.isOpen());
143aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(dc.isConnected());
144aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
145aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
146aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
147aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            dc.getLocalAddress();
148aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
149aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (ClosedChannelException expected) {
150aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
151aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(dc.isOpen());
152aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(dc.isConnected());
153aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
154aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
155aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_afterClose() throws Exception {
156d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
157d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
158d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
159aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
160aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
161aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
162d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
163aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
164aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (ClosedChannelException expected) {
165aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
166aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
167aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
168aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_nullGroupAddress() throws Exception {
169d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
170d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
171d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
172aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
173aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
174d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(null, ipv4NetworkInterface);
175aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
176aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
177aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
178aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
179aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
180aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
181aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_nullNetworkInterface() throws Exception {
182d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
183d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
184d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
185aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
186aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
187aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            dc.join(GOOD_MULTICAST_IPv4, null);
188aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
189aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
190aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
191aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
192aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
193aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
194aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_nonMulticastGroupAddress_IPv4() throws Exception {
195d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
196d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
197d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
198aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
199aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
200d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(UNICAST_IPv4_1, ipv4NetworkInterface);
201aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
202aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
203aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
204aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
205aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
206aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
207aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_nonMulticastGroupAddress_IPv6() throws Exception {
208d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
209d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
210d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
211aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
212aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
213d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(UNICAST_IPv6_1, ipv6NetworkInterface);
214aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
215aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
216aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
217aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
218aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
219aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
220aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_IPv4() throws Exception {
221f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinAnySource(GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4, ipv4NetworkInterface);
222aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
223aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
224aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_IPv6() throws Exception {
225f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinAnySource(GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6, ipv6NetworkInterface);
226aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
227aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
228f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_joinAnySource(InetAddress group, InetAddress group2,
229d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface) throws Exception {
230d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
231d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
232d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
233d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        // Set up a receiver join the group on ipv4NetworkInterface
234aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel receiverChannel = createReceiverChannel();
235aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress localAddress = (InetSocketAddress) receiverChannel.getLocalAddress();
236d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        receiverChannel.join(group, networkInterface);
237aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
238aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg = "Hello World";
2394f51e6cf5f53293434b1ddd69bc6bb449898ae68Lorenzo Colitti        sendMulticastMessage(group, localAddress.getPort(), msg, networkInterface);
240aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
241aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // now verify that we received the data as expected
242aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer recvBuffer = ByteBuffer.allocate(100);
243aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        SocketAddress sourceAddress = receiverChannel.receive(recvBuffer);
244aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNotNull(sourceAddress);
245aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
246aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
247aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // now verify that we didn't receive the second message
248aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg2 = "Hello World - Different Group";
2494f51e6cf5f53293434b1ddd69bc6bb449898ae68Lorenzo Colitti        sendMulticastMessage(group2, localAddress.getPort(), msg2, networkInterface);
250aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        recvBuffer.position(0);
251aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        SocketAddress sourceAddress2 = receiverChannel.receive(recvBuffer);
252aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(sourceAddress2);
253aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
254aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receiverChannel.close();
255aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
256aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
257aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_processLimit() throws Exception {
258d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
259d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
260d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
261aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
262aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        for (byte i = 1; i <= 25; i++) {
263aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetAddress groupAddress = Inet4Address.getByName("239.255.0." + i);
264aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            try {
265d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                dc.join(groupAddress, ipv4NetworkInterface);
266aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            } catch (SocketException e) {
267aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // There is a limit, that's ok according to the RI docs. For this test a lower bound of 20
268aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // is used, which appears to be the default linux limit.
269aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // See /proc/sys/net/ipv4/igmp_max_memberships
270aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                assertTrue(i > 20);
271aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                break;
272aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
273aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
274aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
275aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
276aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
277aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
278aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_blockLimit() throws Exception {
279d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
280d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
281d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
282aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
283d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
284aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        for (byte i = 1; i <= 15; i++) {
285aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetAddress sourceAddress = Inet4Address.getByName("10.0.0." + i);
286aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            try {
287aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                key.block(sourceAddress);
288aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            } catch (SocketException e) {
289aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
290aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // is used, which appears to be the default linux limit.
291aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // See /proc/sys/net/ipv4/igmp_max_msf
292aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                assertTrue(i > 10);
293aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                break;
294aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
295aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
296aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
297aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
298aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
299aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
300aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Confirms that calling join() does not cause an implicit bind() to take place. */
301aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_doesNotCauseBind() throws Exception {
302d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
303d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
304d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
305aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = DatagramChannel.open();
306d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
307aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(dc.getLocalAddress());
308aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
309aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
310aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
311aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
312aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_networkInterfaces() throws Exception {
313d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
314d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
315d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
316aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Check that we can join on specific interfaces and that we only receive if data is
317aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // received on that interface. This test is only really useful on devices with multiple
318aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // non-loopback interfaces.
319aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
320aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
321aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
322aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        while (theInterfaces.hasMoreElements()) {
323aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            NetworkInterface thisInterface = theInterfaces.nextElement();
324aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            if (thisInterface.getInetAddresses().hasMoreElements()) {
325aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                realInterfaces.add(thisInterface);
326aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
327aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
328aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
329aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        for (int i = 0; i < realInterfaces.size(); i++) {
330aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            NetworkInterface thisInterface = realInterfaces.get(i);
331aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            if (!thisInterface.supportsMulticast()) {
332aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // Skip interfaces that do not support multicast - there's no point in proving
333aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // they cannot send / receive multicast messages.
334aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                continue;
335aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
336aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
337aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // get the first address on the interface
338aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
339aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // start server which is joined to the group and has
340aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // only asked for packets on this interface
341aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
342aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
343aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            NetworkInterface sendingInterface = null;
344aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetAddress group = null;
345aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            if (addresses.hasMoreElements()) {
346aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                InetAddress firstAddress = addresses.nextElement();
347aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                if (firstAddress instanceof Inet4Address) {
348aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                    group = GOOD_MULTICAST_IPv4;
349d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    sendingInterface = ipv4NetworkInterface;
350aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                } else {
351aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                    // if this interface only seems to support IPV6 addresses
352aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                    group = GOOD_MULTICAST_IPv6;
353d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                    sendingInterface = ipv6NetworkInterface;
354aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                }
355aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
356aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
357aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            DatagramChannel dc = createReceiverChannel();
358aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
359aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            dc.join(group, thisInterface);
360aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
361aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Now send out a package on sendingInterface. We should only see the packet if we send
362aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // it on the same interface we are listening on (thisInterface).
363aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            String msg = "Hello World - Again" + thisInterface.getName();
364aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            sendMulticastMessage(group, localAddress.getPort(), msg, sendingInterface);
365aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
366aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            ByteBuffer recvBuffer = ByteBuffer.allocate(100);
367aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            SocketAddress sourceAddress = dc.receive(recvBuffer);
368aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            if (thisInterface.equals(sendingInterface)) {
369aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
370aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            } else {
371aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                assertNull(sourceAddress);
372aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
373aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
374aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            dc.close();
375aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
376aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
377aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
378aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Confirms that the scope of each membership is network interface-level. */
379aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_join_canMixTypesOnDifferentInterfaces() throws Exception {
380d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
381d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
382d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
383aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = DatagramChannel.open();
384d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
385aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        MembershipKey membershipKey2 = dc.join(GOOD_MULTICAST_IPv4, loopbackInterface, UNICAST_IPv4_1);
386aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNotSame(membershipKey1, membershipKey2);
387aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
388aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
389aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
390aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
391aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
392aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private DatagramChannel createReceiverChannel() throws Exception {
393aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = DatagramChannel.open();
394aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.bind(null /* leave the OS to determine the port, and use the wildcard address */);
395aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        configureChannelForReceiving(dc);
396aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        return dc;
397aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
398aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
399aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_multiple_joins_IPv4()
400aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws Exception {
401f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
402aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
403aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
404aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_multiple_joins_IPv6()
405aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws Exception {
406f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
407aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
408aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
409f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_joinAnySource_multiple_joins(InetAddress group,
410d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface) throws Exception {
411d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
412d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
413d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
414aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
415aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
416d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey1 = dc.join(group, networkInterface);
417aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
418aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        MembershipKey membershipKey2 = dc.join(group, loopbackInterface);
419aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey1.equals(membershipKey2));
420aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
421d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey1_2 = dc.join(group, networkInterface);
422aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(membershipKey1, membershipKey1_2);
423aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
424aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
425aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
426aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
427aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinAnySource_multicastLoopOption_IPv4() throws Exception {
428f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
429aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
430aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
431aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_multicastLoopOption_IPv6() throws Exception {
432f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
433aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
434aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
435f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_joinAnySource_multicastLoopOption(InetAddress group,
436d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface) throws Exception {
437d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
438d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
439d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
440aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        final String message = "Hello, world!";
441aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
442aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
443aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */);
4442c9bf1099057a50df42d7257b2e16115051e1370Shigeki Yokomichi        dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
445aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        configureChannelForReceiving(dc);
446d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        dc.join(group, networkInterface);
447aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
448aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
449aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
450aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // send the datagram
451aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        byte[] sendData = message.getBytes();
452aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer sendBuffer = ByteBuffer.wrap(sendData);
453aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.send(sendBuffer, new InetSocketAddress(group, localAddress.getPort()));
454aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
455aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // receive the datagram
456aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer recvBuffer = ByteBuffer.allocate(100);
457aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        SocketAddress sourceAddress = dc.receive(recvBuffer);
458aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNotNull(sourceAddress);
459aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
460aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String recvMessage = new String(recvBuffer.array(), 0, recvBuffer.position());
461aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(message, recvMessage);
462aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
463aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Turn off loop
464aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false /* enable loopback */);
465aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
466aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // send another datagram
467aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        recvBuffer.position(0);
468aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer sendBuffer2 = ByteBuffer.wrap(sendData);
469aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.send(sendBuffer2, new InetSocketAddress(group, localAddress.getPort()));
470aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
471aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        SocketAddress sourceAddress2 = dc.receive(recvBuffer);
472aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(sourceAddress2);
473aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
474aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
475aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
476aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
477aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void testMembershipKeyAccessors_IPv4() throws Exception {
478f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        checkMembershipKeyAccessors(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
479aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
480aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
481aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void testMembershipKeyAccessors_IPv6() throws Exception {
482f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        checkMembershipKeyAccessors(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
483aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
484aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
485f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void checkMembershipKeyAccessors(InetAddress group,
486d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface) throws Exception {
487d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
488d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
489d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
490aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
491aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
492d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey key = dc.join(group, networkInterface);
493aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertSame(dc, key.channel());
494aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertSame(group, key.group());
495aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(key.isValid());
496d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        assertSame(networkInterface, key.networkInterface());
497aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(key.sourceAddress());
4982e5060e06146d114175319477783488d2360da93Shubham Ajmera        dc.close();
499aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
500aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
501aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_dropAnySource_twice_IPv4() throws Exception {
502f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_dropAnySource_twice(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
503aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
504aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
505aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_dropAnySource_twice_IPv6() throws Exception {
506f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_dropAnySource_twice(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
507aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
508aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
509f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_dropAnySource_twice(InetAddress group,
510d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface) throws Exception {
511d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
512d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
513d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
514aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
515d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(group, networkInterface);
516aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
517aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey.isValid());
518aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.drop();
519aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey.isValid());
520aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
521aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Try to leave a group we are no longer a member of - should do nothing.
522aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.drop();
523aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
524aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
525aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
526aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
527aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_close_invalidatesMembershipKey() throws Exception {
528d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
529d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
530d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
531aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
532d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
533aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
534aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey.isValid());
535aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
536aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
537aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
538aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey.isValid());
539aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
540aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
541aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_null() throws Exception {
542d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
543d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
544d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
545aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
546d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
547aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
548aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.block(null);
549aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
550aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
551aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
552aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
553aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
554aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
555aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
556aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_mixedAddressTypes_IPv4() throws Exception {
557d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
558d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
559d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
560aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
561d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
562aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
563aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.block(UNICAST_IPv6_1);
564aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
565aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
566aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
567aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
568aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
569aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
570aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
571aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_mixedAddressTypes_IPv6() throws Exception {
572d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
573d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
574d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
575aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
576d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
577aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
578aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.block(UNICAST_IPv4_1);
579aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
580aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
581aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
582aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
583aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
584aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
585aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
586aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_cannotBlockWithSourceSpecificMembership() throws Exception {
587d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
588d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
589d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
590aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
591d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
592aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
593aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.block(UNICAST_IPv4_2);
594aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
595aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
596aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
597aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
598aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
599aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
600aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
601aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_multipleBlocksIgnored() throws Exception {
602d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
603d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
604d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
605aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
606d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
607aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.block(UNICAST_IPv4_1);
608aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
609aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        MembershipKey membershipKey2 = membershipKey.block(UNICAST_IPv4_1);
610aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertSame(membershipKey2, membershipKey);
611aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
612aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
613aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
614aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
615aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_wildcardAddress() throws Exception {
616d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
617d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
618d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
619aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
620d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
621aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
622aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.block(WILDCARD_IPv4);
623aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
624aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
625aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
626aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
627aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
628aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
629aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
630aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_unblock_multipleUnblocksFail() throws Exception {
631d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
632d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
633d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
634aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
635d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
636aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
637aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
638aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.unblock(UNICAST_IPv4_1);
639aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
640aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
641aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
642aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
643aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey.isValid());
644aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
645aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.block(UNICAST_IPv4_1);
646aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.unblock(UNICAST_IPv4_1);
647aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
648aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
649aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.unblock(UNICAST_IPv4_1);
650aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
651aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
652aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
653aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
654aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
655aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
656aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
657aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_unblock_null() throws Exception {
658d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
659d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
660d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
661aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
662d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
663aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.block(UNICAST_IPv4_1);
664aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
665aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
666aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.unblock(null);
667aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
668aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
669aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Either of these exceptions are fine
670aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
671aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Either of these exception are fine
672aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
673aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
674aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
675aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
676aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
677aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_unblock_mixedAddressTypes_IPv4() throws Exception {
678d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
679d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
680d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
681aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
682d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
683aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
684aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.unblock(UNICAST_IPv6_1);
685aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
686aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
687aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Either of these exceptions are fine
688aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
689aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Either of these exceptions are fine
690aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
691aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
692aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
693aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
694aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
695aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_unblock_mixedAddressTypes_IPv6() throws Exception {
696d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
697d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
698d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
699aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
700d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
701aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
702aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.unblock(UNICAST_IPv4_1);
703aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
704aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
705aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Either of these exceptions are fine
706aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
707aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // Either of these exceptions are fine
708aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
709aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
710aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
711aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
712aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
713aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Checks that block() works when the receiver is bound to the multicast group address */
714aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_filtersAsExpected_groupBind_ipv4() throws Exception {
715f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
716f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
717f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
718d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
719f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_block_filtersAsExpected(
720aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv4LocalAddress /* senderBindAddress */,
721aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
722d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                GOOD_MULTICAST_IPv4 /* groupAddress */,
723d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv4NetworkInterface);
724aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
725aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
726aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Checks that block() works when the receiver is bound to the multicast group address */
727aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_filtersAsExpected_groupBind_ipv6() throws Exception {
728f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
729f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
730f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
731d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
732f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_block_filtersAsExpected(
733aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv6LocalAddress /* senderBindAddress */,
734aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
735d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                GOOD_MULTICAST_IPv6 /* groupAddress */,
736d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv6NetworkInterface);
737aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
738aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
739aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Checks that block() works when the receiver is bound to the "any" address */
740aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_filtersAsExpected_anyBind_ipv4() throws Exception {
741f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
742f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
743f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
744d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
745f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_block_filtersAsExpected(
746aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv4LocalAddress /* senderBindAddress */,
747aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                WILDCARD_IPv4 /* receiverBindAddress */,
748d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                GOOD_MULTICAST_IPv4 /* groupAddress */,
749d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv4NetworkInterface);
750aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
751aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
752aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Checks that block() works when the receiver is bound to the "any" address */
753aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_block_filtersAsExpected_anyBind_ipv6() throws Exception {
754f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
755f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
756f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
757d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
758f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_block_filtersAsExpected(
759aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv6LocalAddress /* senderBindAddress */,
760aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                WILDCARD_IPv6 /* receiverBindAddress */,
761d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                GOOD_MULTICAST_IPv6 /* groupAddress */,
762d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv6NetworkInterface);
763aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
764aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
765f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_block_filtersAsExpected(
766d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            InetAddress senderBindAddress, InetAddress receiverBindAddress,
767d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            InetAddress groupAddress, NetworkInterface networkInterface)
768aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws Exception {
769aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel sendingChannel = DatagramChannel.open();
770aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // In order to block a sender the sender's address must be known. The sendingChannel is
771aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // explicitly bound to a known, non-loopback address.
772aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendingChannel.bind(new InetSocketAddress(senderBindAddress, 0));
773aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress();
774aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
775aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel receivingChannel = DatagramChannel.open();
776aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        configureChannelForReceiving(receivingChannel);
777aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receivingChannel.bind(
778aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */);
779aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress localReceivingAddress =
780aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                (InetSocketAddress) receivingChannel.getLocalAddress();
781aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress groupSocketAddress =
782aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
783aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        MembershipKey membershipKey =
784d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                receivingChannel.join(groupSocketAddress.getAddress(), networkInterface);
785aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
786aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer receiveBuffer = ByteBuffer.allocate(10);
787aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
788aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Send a message. It should be received.
789aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg1 = "Hello1";
790aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendMessage(sendingChannel, msg1, groupSocketAddress);
791d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong        IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000);
792aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
793aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(sourceAddress1, sendingAddress);
794aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position()));
795aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
796aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Now block the sender
797aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.block(sendingAddress.getAddress());
798aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
799aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Send a message. It should be filtered.
800aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg2 = "Hello2";
801aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendMessage(sendingChannel, msg2, groupSocketAddress);
802d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong        try {
803d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong            IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000);
804d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong            fail();
805d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong        } catch (SocketTimeoutException expected) { }
806aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receiveBuffer.position(0);
807aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
808aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(sourceAddress2);
809aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
810aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Now unblock the sender
811aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.unblock(sendingAddress.getAddress());
812aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
813aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Send a message. It should be received.
814aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg3 = "Hello3";
815aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendMessage(sendingChannel, msg3, groupSocketAddress);
816d880e69f88b68996b19385d55bcdfe7796f95e02Yi Kong        IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000);
817aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receiveBuffer.position(0);
818aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sourceAddress3 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
819aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(sourceAddress3, sendingAddress);
820aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(msg3, new String(receiveBuffer.array(), 0, receiveBuffer.position()));
821aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
822aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendingChannel.close();
823aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receivingChannel.close();
824aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
825aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
826aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nullGroupAddress() throws Exception {
827d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
828d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
829d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
830aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
831aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
832d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(null, ipv4NetworkInterface, UNICAST_IPv4_1);
833aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
834aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
835aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
836aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
837aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
838aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
839aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_afterClose() throws Exception {
840d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
841d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
842d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
843aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
844aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
845aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
846d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
847aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
848aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (ClosedChannelException expected) {
849aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
850aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
851aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
852aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nullNetworkInterface() throws Exception {
853d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
854d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
855d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
856aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
857aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
858aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            dc.join(GOOD_MULTICAST_IPv4, null, UNICAST_IPv4_1);
859aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
860aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
861aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
862aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
863aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
864aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
865aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv4() throws Exception {
866d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
867d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
868d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
869aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
870aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
871d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(UNICAST_IPv4_1, ipv4NetworkInterface, UNICAST_IPv4_1);
872aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
873aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
874aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
875aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
876aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
877aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
878aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv6() throws Exception {
879d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
880d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
881d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
882aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
883aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
884d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(UNICAST_IPv6_1, ipv6NetworkInterface, UNICAST_IPv6_1);
885aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
886aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
887aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
888aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
889aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
890aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
891aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nullSourceAddress_IPv4() throws Exception {
892d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
893d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
894d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
895aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
896aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
897d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, null);
898aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
899aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
900aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
901aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
902aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
903aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
904aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nullSourceAddress_IPv6() throws Exception {
905d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
906d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
907d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
908aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
909aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
910d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, null);
911aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
912aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (NullPointerException expected) {
913aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
914aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
915aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
916aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
917aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_mixedAddressTypes() throws Exception {
918d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
919d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
920d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
921aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
922aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
923d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv6_1);
924aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
925aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
926aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
927aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
928d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, UNICAST_IPv4_1);
929aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
930aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
931aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
932aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
933aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
934aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
935aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nonUnicastSourceAddress_IPv4() throws Exception {
936d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
937d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
938d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
939aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
940aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
941d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, BAD_MULTICAST_IPv4);
942aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
943aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
944aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
945aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
946aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
947aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
948aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_nonUniicastSourceAddress_IPv6() throws Exception {
949d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
950d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
951d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
952aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
953aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
954d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, BAD_MULTICAST_IPv6);
955aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            fail();
956aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalArgumentException expected) {
957aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
958aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
959aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
960aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
961aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_multipleSourceAddressLimit() throws Exception {
962d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
963d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
964d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
965aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
966aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        for (byte i = 1; i <= 20; i++) {
967aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetAddress sourceAddress = Inet4Address.getByAddress(new byte[] { 10, 0, 0, i});
968aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            try {
969d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, sourceAddress);
970aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            } catch (SocketException e) {
971aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
972aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // is used, which appears to be the default linux limit. See /proc/sys/net/ipv4/igmp_max_msf
973aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                assertTrue(i > 10);
974aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                break;
975aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
976aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
977aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
978aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
979aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
980aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
981aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /**
982aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * Checks that a source-specific join() works when the receiver is bound to the multicast group
983aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * address
984aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     */
985aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_null() throws Exception {
986f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
987f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
988f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
989d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
990f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinSourceSpecific(
991aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv4LocalAddress /* senderBindAddress */,
992aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
993aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* groupAddress */,
994d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv4_1 /* badSenderAddress */,
995d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv4NetworkInterface);
996aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
997aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
998aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /**
999aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * Checks that a source-specific join() works when the receiver is bound to the multicast group
1000aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * address
1001aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     */
1002aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_groupBind_ipv4() throws Exception {
1003f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
1004f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
1005f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
1006d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
1007f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinSourceSpecific(
1008aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv4LocalAddress /* senderBindAddress */,
1009aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
1010aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* groupAddress */,
1011d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv4_1 /* badSenderAddress */,
10127cd7bf2e543625280ac22d7b2a18ffa3e3cbbe44Tobias Thierer                ipv4NetworkInterface);
1013aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1014aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1015aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /**
1016aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * Checks that a source-specific join() works when the receiver is bound to the multicast group
1017aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * address
1018aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     */
1019aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_groupBind_ipv6() throws Exception {
1020f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
1021f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
1022f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
1023d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
1024f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinSourceSpecific(
1025aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv6LocalAddress /* senderBindAddress */,
1026aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
1027aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv6 /* groupAddress */,
1028d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv6_1 /* badSenderAddress */,
1029d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv6NetworkInterface);
1030aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1031aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1032aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Checks that a source-specific join() works when the receiver is bound to the "any" address */
1033aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_anyBind_ipv4() throws Exception {
1034f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
1035f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
1036f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
1037d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
1038f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinSourceSpecific(
1039aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv4LocalAddress /* senderBindAddress */,
1040aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                WILDCARD_IPv4 /* receiverBindAddress */,
1041aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* groupAddress */,
1042d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv4_1 /* badSenderAddress */,
1043d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv4NetworkInterface);
1044aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1045aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1046aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /** Checks that a source-specific join() works when the receiver is bound to the "any" address */
1047aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_joinSourceSpecific_anyBind_ipv6() throws Exception {
1048f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        if (!supportsMulticast) {
1049f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu            return;
1050f515ad8fb5dac39b9e32f4cd06097ecaabb10fbdbohu        }
1051d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
1052f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_joinSourceSpecific(
1053aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                ipv6LocalAddress /* senderBindAddress */,
1054aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                WILDCARD_IPv6 /* receiverBindAddress */,
1055aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv6 /* groupAddress */,
1056d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv6_1 /* badSenderAddress */,
1057d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv6NetworkInterface);
1058aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1059aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1060aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    /**
1061aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * Checks that the source-specific membership is correctly source-filtering.
1062aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     *
1063aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * @param senderBindAddress the address to bind the sender socket to
1064aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * @param receiverBindAddress the address to bind the receiver socket to
1065aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * @param groupAddress the group address to join
1066aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     * @param badSenderAddress a unicast address to join to perform a negative test
10677cd7bf2e543625280ac22d7b2a18ffa3e3cbbe44Tobias Thierer     * @param networkInterface The network interface on which to join the multicast group
1068aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller     */
1069f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_joinSourceSpecific(
1070aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress,
1071d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            InetAddress badSenderAddress, NetworkInterface networkInterface)
1072aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws Exception {
1073aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel sendingChannel = DatagramChannel.open();
1074aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // In order to be source-specific the sender's address must be known. The sendingChannel is
1075aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // explicitly bound to a known, non-loopback address.
1076aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendingChannel.bind(new InetSocketAddress(senderBindAddress, 0));
1077aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress();
1078aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1079aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel receivingChannel = DatagramChannel.open();
1080aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receivingChannel.bind(
1081aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */);
1082aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        configureChannelForReceiving(receivingChannel);
1083aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1084aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress localReceivingAddress =
1085aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                (InetSocketAddress) receivingChannel.getLocalAddress();
1086aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress groupSocketAddress =
1087aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
1088aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        MembershipKey membershipKey1 = receivingChannel
1089d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                .join(groupSocketAddress.getAddress(), networkInterface, senderBindAddress);
1090aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1091aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer receiveBuffer = ByteBuffer.allocate(10);
1092aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1093aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Send a message. It should be received.
1094aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg1 = "Hello1";
1095aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendMessage(sendingChannel, msg1, groupSocketAddress);
1096aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
1097aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(sourceAddress1, sendingAddress);
1098aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position()));
1099aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1100aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey1.drop();
1101aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1102d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        receivingChannel.join(groupSocketAddress.getAddress(), networkInterface, badSenderAddress);
1103aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1104aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Send a message. It should not be received.
1105aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        String msg2 = "Hello2";
1106aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendMessage(sendingChannel, msg2, groupSocketAddress);
1107aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
1108aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertNull(sourceAddress2);
1109aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1110aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receivingChannel.close();
1111aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendingChannel.close();
1112aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1113aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1114aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_dropSourceSpecific_twice_IPv4() throws Exception {
1115f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_dropSourceSpecific_twice(
1116d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                GOOD_MULTICAST_IPv4 /* groupAddress */, UNICAST_IPv4_1 /* sourceAddress */,
1117d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv4NetworkInterface);
1118aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1119aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1120aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_dropSourceSpecific_twice_IPv6() throws Exception {
1121f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_dropSourceSpecific_twice(
1122d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                GOOD_MULTICAST_IPv6 /* groupAddress */, UNICAST_IPv6_1 /* sourceAddress */,
1123d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv6NetworkInterface);
1124aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1125aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1126f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_dropSourceSpecific_twice(InetAddress groupAddress, InetAddress sourceAddress,
1127d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface)
1128aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws Exception {
1129d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
1130d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
1131d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
1132aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
1133d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(groupAddress, networkInterface, sourceAddress);
1134aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1135aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey.isValid());
1136aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.drop();
1137aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey.isValid());
1138aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1139aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Try to leave a group we are no longer a member of - should do nothing.
1140aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.drop();
1141aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1142aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
1143aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1144aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1145aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv4() throws Exception {
1146f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_dropSourceSpecific_sourceKeysAreIndependent(
1147aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv4 /* groupAddress */,
1148aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                UNICAST_IPv4_1 /* sourceAddress1 */,
1149d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv4_2 /* sourceAddress2 */,
1150d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv4NetworkInterface);
1151aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1152aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1153aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv6() throws Exception {
1154f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer        check_dropSourceSpecific_sourceKeysAreIndependent(
1155aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                GOOD_MULTICAST_IPv6 /* groupAddress */,
1156aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                UNICAST_IPv6_1 /* sourceAddress1 */,
1157d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                UNICAST_IPv6_2 /* sourceAddress2 */,
1158d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera                ipv6NetworkInterface);
1159aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1160aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1161f393ec80c97a5baa736abe6ecfb074138988165dTobias Thierer    private void check_dropSourceSpecific_sourceKeysAreIndependent(
1162d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            InetAddress groupAddress, InetAddress sourceAddress1, InetAddress sourceAddress2,
1163d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            NetworkInterface networkInterface) throws Exception {
1164d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
1165d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
1166d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
1167aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
1168d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface, sourceAddress1);
1169d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface, sourceAddress2);
1170aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey1.equals(membershipKey2));
1171aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey1.isValid());
1172aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey2.isValid());
1173aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1174aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey1.drop();
1175aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1176aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey1.isValid());
1177aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertTrue(membershipKey2.isValid());
1178aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1179aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
1180aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1181aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1182aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    public void test_drop_keyBehaviorAfterDrop() throws Exception {
1183d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        if (!supportsMulticast) {
1184d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera            return;
1185d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        }
1186aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = createReceiverChannel();
1187d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
1188aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        membershipKey.drop();
1189aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertFalse(membershipKey.isValid());
1190aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1191aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
1192aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.block(UNICAST_IPv4_1);
1193d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer            fail();
1194aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
1195aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
1196aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1197aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        try {
1198aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            membershipKey.unblock(UNICAST_IPv4_1);
1199d4b7449574ca69c713a3f2230cb77c68ee642700Tobias Thierer            fail();
1200aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        } catch (IllegalStateException expected) {
1201aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
1202aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1203aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertSame(dc, membershipKey.channel());
1204aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertSame(GOOD_MULTICAST_IPv4, membershipKey.group());
1205aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        assertSame(UNICAST_IPv4_1, membershipKey.sourceAddress());
1206d27d16405ee9c9753d253bc311bf00f5de2e25b5Shubham Ajmera        assertSame(ipv4NetworkInterface, membershipKey.networkInterface());
1207aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1208aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1209aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static void configureChannelForReceiving(DatagramChannel receivingChannel)
1210aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws Exception {
1211aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1212aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // NOTE: At the time of writing setSoTimeout() has no effect in the RI, making these tests hang
1213aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // if the channel is in blocking mode. configureBlocking(false) is used instead and rely on the
1214aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // network to the local host being instantaneous.
1215aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // receivingChannel.socket().setSoTimeout(200);
1216aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // receivingChannel.configureBlocking(true);
1217aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        receivingChannel.configureBlocking(false);
1218aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1219aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1220aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
1221aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        return iface.isUp()
1222aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // Typically loopback interfaces do not support multicast, but they are ruled out
1223aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                // explicitly here anyway.
1224aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                && !iface.isLoopback() && iface.supportsMulticast()
1225aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                && iface.getInetAddresses().hasMoreElements();
1226aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1227aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1228aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static void sendMulticastMessage(
1229aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            InetAddress group, int port, String msg, NetworkInterface sendingInterface)
1230aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws IOException {
1231aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        // Any datagram socket can send to a group. It does not need to have joined the group.
1232aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        DatagramChannel dc = DatagramChannel.open();
1233aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        if (sendingInterface != null) {
1234aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // For some reason, if set, this must be set to a real (non-loopback) device for an IPv6
1235aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            // group, but can be loopback for an IPv4 group.
1236aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, sendingInterface);
1237aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
1238aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendMessage(dc, msg, new InetSocketAddress(group, port));
1239aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        dc.close();
1240aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1241aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1242aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static void sendMessage(
1243aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            DatagramChannel sendingChannel, String msg, InetSocketAddress targetAddress)
1244aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            throws IOException {
1245aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1246aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        ByteBuffer sendBuffer = ByteBuffer.wrap(msg.getBytes());
1247aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        sendingChannel.send(sendBuffer, targetAddress);
1248aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1249aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1250aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static InetAddress getLocalIpv4Address(NetworkInterface networkInterface) {
1251aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
1252aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            if (interfaceAddress.getAddress() instanceof Inet4Address) {
1253aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                return interfaceAddress.getAddress();
1254aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
1255aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
1256aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        throw new AssertionFailedError("Unable to find local IPv4 address for " + networkInterface);
1257aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1258aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1259aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    private static InetAddress getLocalIpv6Address(NetworkInterface networkInterface) {
1260aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
1261aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            if (interfaceAddress.getAddress() instanceof Inet6Address) {
1262aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller                return interfaceAddress.getAddress();
1263aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller            }
1264aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        }
1265aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller        throw new AssertionFailedError("Unable to find local IPv6 address for " + networkInterface);
1266aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller    }
1267aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller}
1268aea78555169709a2586b585e61414d9aee1d8e28Neil Fuller
1269