/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package libcore.java.nio.channels;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
import java.util.ArrayList;
import java.util.Enumeration;

import libcore.io.IoBridge;

import static android.system.OsConstants.POLLIN;

/**
 * Tests associated with multicast behavior of DatagramChannel.
 * These tests require IPv6 multicasting enabled network.
 */
public class DatagramChannelMulticastTest extends TestCase {

    private static InetAddress lookup(String s) {
        try {
            return InetAddress.getByName(s);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    // These IP addresses aren't inherently "good" or "bad"; they're just used like that.
    // We use the "good" addresses for our actual group, and the "bad" addresses are for
    // a group that we won't actually set up.
    private static final InetAddress GOOD_MULTICAST_IPv4 = lookup("239.255.0.1");
    private static final InetAddress BAD_MULTICAST_IPv4 = lookup("239.255.0.2");
    private static final InetAddress GOOD_MULTICAST_IPv6 = lookup("ff05::7:7");
    private static final InetAddress BAD_MULTICAST_IPv6 = lookup("ff05::7:8");

    // Special addresses.
    private static final InetAddress WILDCARD_IPv4 = lookup("0.0.0.0");
    private static final InetAddress WILDCARD_IPv6 = lookup("::");

    // Arbitrary unicast addresses. Used when the value doesn't actually matter. e.g. for source
    // filters.
    private static final InetAddress UNICAST_IPv4_1 = lookup("192.168.1.1");
    private static final InetAddress UNICAST_IPv4_2 = lookup("192.168.1.2");
    private static final InetAddress UNICAST_IPv6_1 = lookup("2001:db8::1");
    private static final InetAddress UNICAST_IPv6_2 = lookup("2001:db8::2");

    private NetworkInterface ipv4NetworkInterface;
    private NetworkInterface ipv6NetworkInterface;
    private NetworkInterface loopbackInterface;

    private boolean supportsMulticast;

    @Override
    protected void setUp() throws Exception {
        // The loopback interface isn't actually useful for sending/receiving multicast messages
        // but it can be used as a dummy for tests where that does not matter.
        loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
        assertNotNull(loopbackInterface);
        assertTrue(loopbackInterface.isLoopback());
        assertFalse(loopbackInterface.supportsMulticast());

        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

        // Determine if the device is marked to support multicast or not. If this propery is not
        // set we assume the device has an interface capable of supporting multicast.
        supportsMulticast = Boolean.parseBoolean(
                System.getProperty("android.cts.device.multicast", "true"));
        if (!supportsMulticast) {
            return;
        }

        while (interfaces.hasMoreElements()
                && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
            NetworkInterface nextInterface = interfaces.nextElement();
            if (willWorkForMulticast(nextInterface)) {
                Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    final InetAddress nextAddress = addresses.nextElement();
                    if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
                        ipv6NetworkInterface = nextInterface;
                    } else if (nextAddress instanceof Inet4Address
                            && ipv4NetworkInterface == null) {
                        ipv4NetworkInterface = nextInterface;
                    }
                }
            }
        }

        if (ipv4NetworkInterface == null) {
            fail("Test environment must have at least one network interface capable of IPv4"
                    + " multicast");
        }
        if (ipv6NetworkInterface == null) {
            fail("Test environment must have at least one network interface capable of IPv6"
                    + " multicast");
        }
    }

    public void test_open() throws IOException {
        DatagramChannel dc = DatagramChannel.open();

        // Unlike MulticastSocket, DatagramChannel has SO_REUSEADDR set to false by default.
        assertFalse(dc.getOption(StandardSocketOptions.SO_REUSEADDR));

        assertNull(dc.getLocalAddress());
        assertTrue(dc.isOpen());
        assertFalse(dc.isConnected());
    }

    public void test_bind_null() throws Exception {
        DatagramChannel dc = createReceiverChannel();
        assertNotNull(dc.getLocalAddress());
        assertTrue(dc.isOpen());
        assertFalse(dc.isConnected());

        dc.close();
        try {
            dc.getLocalAddress();
            fail();
        } catch (ClosedChannelException expected) {
        }
        assertFalse(dc.isOpen());
        assertFalse(dc.isConnected());
    }

    public void test_joinAnySource_afterClose() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        dc.close();
        try {
            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
            fail();
        } catch (ClosedChannelException expected) {
        }
    }

    public void test_joinAnySource_nullGroupAddress() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(null, ipv4NetworkInterface);
            fail();
        } catch (NullPointerException expected) {
        }
        dc.close();
    }

    public void test_joinAnySource_nullNetworkInterface() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv4, null);
            fail();
        } catch (NullPointerException expected) {
        }
        dc.close();
    }

    public void test_joinAnySource_nonMulticastGroupAddress_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(UNICAST_IPv4_1, ipv4NetworkInterface);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinAnySource_nonMulticastGroupAddress_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(UNICAST_IPv6_1, ipv6NetworkInterface);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinAnySource_IPv4() throws Exception {
        test_joinAnySource(GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4, ipv4NetworkInterface);
    }

    public void test_joinAnySource_IPv6() throws Exception {
        test_joinAnySource(GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6, ipv6NetworkInterface);
    }

    private void test_joinAnySource(InetAddress group, InetAddress group2,
            NetworkInterface networkInterface) throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Set up a receiver join the group on ipv4NetworkInterface
        DatagramChannel receiverChannel = createReceiverChannel();
        InetSocketAddress localAddress = (InetSocketAddress) receiverChannel.getLocalAddress();
        receiverChannel.join(group, networkInterface);

        String msg = "Hello World";
        sendMulticastMessage(group, localAddress.getPort(), msg);

        // now verify that we received the data as expected
        ByteBuffer recvBuffer = ByteBuffer.allocate(100);
        SocketAddress sourceAddress = receiverChannel.receive(recvBuffer);
        assertNotNull(sourceAddress);
        assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));

        // now verify that we didn't receive the second message
        String msg2 = "Hello World - Different Group";
        sendMulticastMessage(group2, localAddress.getPort(), msg2);
        recvBuffer.position(0);
        SocketAddress sourceAddress2 = receiverChannel.receive(recvBuffer);
        assertNull(sourceAddress2);

        receiverChannel.close();
    }

    public void test_joinAnySource_processLimit() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        for (byte i = 1; i <= 25; i++) {
            InetAddress groupAddress = Inet4Address.getByName("239.255.0." + i);
            try {
                dc.join(groupAddress, ipv4NetworkInterface);
            } catch (SocketException e) {
                // There is a limit, that's ok according to the RI docs. For this test a lower bound of 20
                // is used, which appears to be the default linux limit.
                // See /proc/sys/net/ipv4/igmp_max_memberships
                assertTrue(i > 20);
                break;
            }
        }

        dc.close();
    }

    public void test_joinAnySource_blockLimit() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        for (byte i = 1; i <= 15; i++) {
            InetAddress sourceAddress = Inet4Address.getByName("10.0.0." + i);
            try {
                key.block(sourceAddress);
            } catch (SocketException e) {
                // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
                // is used, which appears to be the default linux limit.
                // See /proc/sys/net/ipv4/igmp_max_msf
                assertTrue(i > 10);
                break;
            }
        }

        dc.close();
    }

    /** Confirms that calling join() does not cause an implicit bind() to take place. */
    public void test_joinAnySource_doesNotCauseBind() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = DatagramChannel.open();
        dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        assertNull(dc.getLocalAddress());

        dc.close();
    }

    public void test_joinAnySource_networkInterfaces() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Check that we can join on specific interfaces and that we only receive if data is
        // received on that interface. This test is only really useful on devices with multiple
        // non-loopback interfaces.

        ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
        while (theInterfaces.hasMoreElements()) {
            NetworkInterface thisInterface = theInterfaces.nextElement();
            if (thisInterface.getInetAddresses().hasMoreElements()) {
                realInterfaces.add(thisInterface);
            }
        }

        for (int i = 0; i < realInterfaces.size(); i++) {
            NetworkInterface thisInterface = realInterfaces.get(i);
            if (!thisInterface.supportsMulticast()) {
                // Skip interfaces that do not support multicast - there's no point in proving
                // they cannot send / receive multicast messages.
                continue;
            }

            // get the first address on the interface

            // start server which is joined to the group and has
            // only asked for packets on this interface
            Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();

            NetworkInterface sendingInterface = null;
            InetAddress group = null;
            if (addresses.hasMoreElements()) {
                InetAddress firstAddress = addresses.nextElement();
                if (firstAddress instanceof Inet4Address) {
                    group = GOOD_MULTICAST_IPv4;
                    sendingInterface = ipv4NetworkInterface;
                } else {
                    // if this interface only seems to support IPV6 addresses
                    group = GOOD_MULTICAST_IPv6;
                    sendingInterface = ipv6NetworkInterface;
                }
            }

            DatagramChannel dc = createReceiverChannel();
            InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
            dc.join(group, thisInterface);

            // Now send out a package on sendingInterface. We should only see the packet if we send
            // it on the same interface we are listening on (thisInterface).
            String msg = "Hello World - Again" + thisInterface.getName();
            sendMulticastMessage(group, localAddress.getPort(), msg, sendingInterface);

            ByteBuffer recvBuffer = ByteBuffer.allocate(100);
            SocketAddress sourceAddress = dc.receive(recvBuffer);
            if (thisInterface.equals(sendingInterface)) {
                assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
            } else {
                assertNull(sourceAddress);
            }

            dc.close();
        }
    }

    /** Confirms that the scope of each membership is network interface-level. */
    public void test_join_canMixTypesOnDifferentInterfaces() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = DatagramChannel.open();
        MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        MembershipKey membershipKey2 = dc.join(GOOD_MULTICAST_IPv4, loopbackInterface, UNICAST_IPv4_1);
        assertNotSame(membershipKey1, membershipKey2);

        dc.close();
    }


    private DatagramChannel createReceiverChannel() throws Exception {
        DatagramChannel dc = DatagramChannel.open();
        dc.bind(null /* leave the OS to determine the port, and use the wildcard address */);
        configureChannelForReceiving(dc);
        return dc;
    }

    public void test_joinAnySource_multiple_joins_IPv4()
            throws Exception {
        test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
    }

    public void test_joinAnySource_multiple_joins_IPv6()
            throws Exception {
        test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
    }

    private void test_joinAnySource_multiple_joins(InetAddress group,
            NetworkInterface networkInterface) throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();

        MembershipKey membershipKey1 = dc.join(group, networkInterface);

        MembershipKey membershipKey2 = dc.join(group, loopbackInterface);
        assertFalse(membershipKey1.equals(membershipKey2));

        MembershipKey membershipKey1_2 = dc.join(group, networkInterface);
        assertEquals(membershipKey1, membershipKey1_2);

        dc.close();
    }

    public void test_joinAnySource_multicastLoopOption_IPv4() throws Exception {
        test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
    }

    public void test_multicastLoopOption_IPv6() throws Exception {
        test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
    }

    private void test_joinAnySource_multicastLoopOption(InetAddress group,
            NetworkInterface networkInterface) throws Exception {
        if (!supportsMulticast) {
            return;
        }
        final String message = "Hello, world!";

        DatagramChannel dc = createReceiverChannel();
        dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */);
        configureChannelForReceiving(dc);
        dc.join(group, networkInterface);

        InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();

        // send the datagram
        byte[] sendData = message.getBytes();
        ByteBuffer sendBuffer = ByteBuffer.wrap(sendData);
        dc.send(sendBuffer, new InetSocketAddress(group, localAddress.getPort()));

        // receive the datagram
        ByteBuffer recvBuffer = ByteBuffer.allocate(100);
        SocketAddress sourceAddress = dc.receive(recvBuffer);
        assertNotNull(sourceAddress);

        String recvMessage = new String(recvBuffer.array(), 0, recvBuffer.position());
        assertEquals(message, recvMessage);

        // Turn off loop
        dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false /* enable loopback */);

        // send another datagram
        recvBuffer.position(0);
        ByteBuffer sendBuffer2 = ByteBuffer.wrap(sendData);
        dc.send(sendBuffer2, new InetSocketAddress(group, localAddress.getPort()));

        SocketAddress sourceAddress2 = dc.receive(recvBuffer);
        assertNull(sourceAddress2);

        dc.close();
    }

    public void testMembershipKeyAccessors_IPv4() throws Exception {
        testMembershipKeyAccessors(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
    }

    public void testMembershipKeyAccessors_IPv6() throws Exception {
        testMembershipKeyAccessors(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
    }

    private void testMembershipKeyAccessors(InetAddress group,
            NetworkInterface networkInterface) throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();

        MembershipKey key = dc.join(group, networkInterface);
        assertSame(dc, key.channel());
        assertSame(group, key.group());
        assertTrue(key.isValid());
        assertSame(networkInterface, key.networkInterface());
        assertNull(key.sourceAddress());
        dc.close();
    }

    public void test_dropAnySource_twice_IPv4() throws Exception {
        test_dropAnySource_twice(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
    }

    public void test_dropAnySource_twice_IPv6() throws Exception {
        test_dropAnySource_twice(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
    }

    private void test_dropAnySource_twice(InetAddress group,
            NetworkInterface networkInterface) throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(group, networkInterface);

        assertTrue(membershipKey.isValid());
        membershipKey.drop();
        assertFalse(membershipKey.isValid());

        // Try to leave a group we are no longer a member of - should do nothing.
        membershipKey.drop();

        dc.close();
    }

    public void test_close_invalidatesMembershipKey() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);

        assertTrue(membershipKey.isValid());

        dc.close();

        assertFalse(membershipKey.isValid());
    }

    public void test_block_null() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        try {
            membershipKey.block(null);
            fail();
        } catch (NullPointerException expected) {
        }

        dc.close();
    }

    public void test_block_mixedAddressTypes_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        try {
            membershipKey.block(UNICAST_IPv6_1);
            fail();
        } catch (IllegalArgumentException expected) {
        }

        dc.close();
    }

    public void test_block_mixedAddressTypes_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
        try {
            membershipKey.block(UNICAST_IPv4_1);
            fail();
        } catch (IllegalArgumentException expected) {
        }

        dc.close();
    }

    public void test_block_cannotBlockWithSourceSpecificMembership() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
        try {
            membershipKey.block(UNICAST_IPv4_2);
            fail();
        } catch (IllegalStateException expected) {
        }

        dc.close();
    }

    public void test_block_multipleBlocksIgnored() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        membershipKey.block(UNICAST_IPv4_1);

        MembershipKey membershipKey2 = membershipKey.block(UNICAST_IPv4_1);
        assertSame(membershipKey2, membershipKey);

        dc.close();
    }

    public void test_block_wildcardAddress() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        try {
            membershipKey.block(WILDCARD_IPv4);
            fail();
        } catch (IllegalArgumentException expected) {
        }

        dc.close();
    }

    public void test_unblock_multipleUnblocksFail() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);

        try {
            membershipKey.unblock(UNICAST_IPv4_1);
            fail();
        } catch (IllegalStateException expected) {
        }

        assertTrue(membershipKey.isValid());

        membershipKey.block(UNICAST_IPv4_1);
        membershipKey.unblock(UNICAST_IPv4_1);

        try {
            membershipKey.unblock(UNICAST_IPv4_1);
            fail();
        } catch (IllegalStateException expected) {
        }

        dc.close();
    }

    public void test_unblock_null() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        membershipKey.block(UNICAST_IPv4_1);

        try {
            membershipKey.unblock(null);
            fail();
        } catch (IllegalStateException expected) {
            // Either of these exceptions are fine
        } catch (NullPointerException expected) {
            // Either of these exception are fine
        }

        dc.close();
    }

    public void test_unblock_mixedAddressTypes_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
        try {
            membershipKey.unblock(UNICAST_IPv6_1);
            fail();
        } catch (IllegalStateException expected) {
            // Either of these exceptions are fine
        } catch (IllegalArgumentException expected) {
            // Either of these exceptions are fine
        }

        dc.close();
    }

    public void test_unblock_mixedAddressTypes_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
        try {
            membershipKey.unblock(UNICAST_IPv4_1);
            fail();
        } catch (IllegalStateException expected) {
            // Either of these exceptions are fine
        } catch (IllegalArgumentException expected) {
            // Either of these exceptions are fine
        }

        dc.close();
    }

    /** Checks that block() works when the receiver is bound to the multicast group address */
    public void test_block_filtersAsExpected_groupBind_ipv4() throws Exception {
        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
        test_block_filtersAsExpected(
                ipv4LocalAddress /* senderBindAddress */,
                GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv4 /* groupAddress */,
                ipv4NetworkInterface);
    }

    /** Checks that block() works when the receiver is bound to the multicast group address */
    public void test_block_filtersAsExpected_groupBind_ipv6() throws Exception {
        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
        test_block_filtersAsExpected(
                ipv6LocalAddress /* senderBindAddress */,
                GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv6 /* groupAddress */,
                ipv6NetworkInterface);
    }

    /** Checks that block() works when the receiver is bound to the "any" address */
    public void test_block_filtersAsExpected_anyBind_ipv4() throws Exception {
        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
        test_block_filtersAsExpected(
                ipv4LocalAddress /* senderBindAddress */,
                WILDCARD_IPv4 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv4 /* groupAddress */,
                ipv4NetworkInterface);
    }

    /** Checks that block() works when the receiver is bound to the "any" address */
    public void test_block_filtersAsExpected_anyBind_ipv6() throws Exception {
        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
        test_block_filtersAsExpected(
                ipv6LocalAddress /* senderBindAddress */,
                WILDCARD_IPv6 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv6 /* groupAddress */,
                ipv6NetworkInterface);
    }

    private void test_block_filtersAsExpected(
            InetAddress senderBindAddress, InetAddress receiverBindAddress,
            InetAddress groupAddress, NetworkInterface networkInterface)
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel sendingChannel = DatagramChannel.open();
        // In order to block a sender the sender's address must be known. The sendingChannel is
        // explicitly bound to a known, non-loopback address.
        sendingChannel.bind(new InetSocketAddress(senderBindAddress, 0));
        InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress();

        DatagramChannel receivingChannel = DatagramChannel.open();
        configureChannelForReceiving(receivingChannel);
        receivingChannel.bind(
                new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */);
        InetSocketAddress localReceivingAddress =
                (InetSocketAddress) receivingChannel.getLocalAddress();
        InetSocketAddress groupSocketAddress =
                new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
        MembershipKey membershipKey =
                receivingChannel.join(groupSocketAddress.getAddress(), networkInterface);

        ByteBuffer receiveBuffer = ByteBuffer.allocate(10);

        // Send a message. It should be received.
        String msg1 = "Hello1";
        sendMessage(sendingChannel, msg1, groupSocketAddress);
        IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000);
        InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
        assertEquals(sourceAddress1, sendingAddress);
        assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position()));

        // Now block the sender
        membershipKey.block(sendingAddress.getAddress());

        // Send a message. It should be filtered.
        String msg2 = "Hello2";
        sendMessage(sendingChannel, msg2, groupSocketAddress);
        try {
            IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000);
            fail();
        } catch (SocketTimeoutException expected) { }
        receiveBuffer.position(0);
        InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
        assertNull(sourceAddress2);

        // Now unblock the sender
        membershipKey.unblock(sendingAddress.getAddress());

        // Send a message. It should be received.
        String msg3 = "Hello3";
        sendMessage(sendingChannel, msg3, groupSocketAddress);
        IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000);
        receiveBuffer.position(0);
        InetSocketAddress sourceAddress3 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
        assertEquals(sourceAddress3, sendingAddress);
        assertEquals(msg3, new String(receiveBuffer.array(), 0, receiveBuffer.position()));

        sendingChannel.close();
        receivingChannel.close();
    }

    public void test_joinSourceSpecific_nullGroupAddress() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(null, ipv4NetworkInterface, UNICAST_IPv4_1);
            fail();
        } catch (NullPointerException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_afterClose() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        dc.close();
        try {
            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
            fail();
        } catch (ClosedChannelException expected) {
        }
    }

    public void test_joinSourceSpecific_nullNetworkInterface() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv4, null, UNICAST_IPv4_1);
            fail();
        } catch (NullPointerException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(UNICAST_IPv4_1, ipv4NetworkInterface, UNICAST_IPv4_1);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(UNICAST_IPv6_1, ipv6NetworkInterface, UNICAST_IPv6_1);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_nullSourceAddress_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, null);
            fail();
        } catch (NullPointerException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_nullSourceAddress_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, null);
            fail();
        } catch (NullPointerException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_mixedAddressTypes() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv6_1);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        try {
            dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, UNICAST_IPv4_1);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_nonUnicastSourceAddress_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, BAD_MULTICAST_IPv4);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_nonUniicastSourceAddress_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        try {
            dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, BAD_MULTICAST_IPv6);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        dc.close();
    }

    public void test_joinSourceSpecific_multipleSourceAddressLimit() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        for (byte i = 1; i <= 20; i++) {
            InetAddress sourceAddress = Inet4Address.getByAddress(new byte[] { 10, 0, 0, i});
            try {
                dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, sourceAddress);
            } catch (SocketException e) {
                // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
                // is used, which appears to be the default linux limit. See /proc/sys/net/ipv4/igmp_max_msf
                assertTrue(i > 10);
                break;
            }
        }

        dc.close();
    }

    /**
     * Checks that a source-specific join() works when the receiver is bound to the multicast group
     * address
     */
    public void test_joinSourceSpecific_null() throws Exception {
        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
        test_joinSourceSpecific(
                ipv4LocalAddress /* senderBindAddress */,
                GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv4 /* groupAddress */,
                UNICAST_IPv4_1 /* badSenderAddress */,
                ipv4NetworkInterface);
    }

    /**
     * Checks that a source-specific join() works when the receiver is bound to the multicast group
     * address
     */
    public void test_joinSourceSpecific_groupBind_ipv4() throws Exception {
        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
        test_joinSourceSpecific(
                ipv4LocalAddress /* senderBindAddress */,
                GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv4 /* groupAddress */,
                UNICAST_IPv4_1 /* badSenderAddress */,
                ipv6NetworkInterface);
    }

    /**
     * Checks that a source-specific join() works when the receiver is bound to the multicast group
     * address
     */
    public void test_joinSourceSpecific_groupBind_ipv6() throws Exception {
        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
        test_joinSourceSpecific(
                ipv6LocalAddress /* senderBindAddress */,
                GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv6 /* groupAddress */,
                UNICAST_IPv6_1 /* badSenderAddress */,
                ipv6NetworkInterface);
    }

    /** Checks that a source-specific join() works when the receiver is bound to the "any" address */
    public void test_joinSourceSpecific_anyBind_ipv4() throws Exception {
        InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
        test_joinSourceSpecific(
                ipv4LocalAddress /* senderBindAddress */,
                WILDCARD_IPv4 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv4 /* groupAddress */,
                UNICAST_IPv4_1 /* badSenderAddress */,
                ipv4NetworkInterface);
    }

    /** Checks that a source-specific join() works when the receiver is bound to the "any" address */
    public void test_joinSourceSpecific_anyBind_ipv6() throws Exception {
        InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
        test_joinSourceSpecific(
                ipv6LocalAddress /* senderBindAddress */,
                WILDCARD_IPv6 /* receiverBindAddress */,
                GOOD_MULTICAST_IPv6 /* groupAddress */,
                UNICAST_IPv6_1 /* badSenderAddress */,
                ipv6NetworkInterface);
    }

    /**
     * Checks that the source-specific membership is correctly source-filtering.
     *
     * @param senderBindAddress the address to bind the sender socket to
     * @param receiverBindAddress the address to bind the receiver socket to
     * @param groupAddress the group address to join
     * @param badSenderAddress a unicast address to join to perform a negative test
     */
    private void test_joinSourceSpecific(
            InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress,
            InetAddress badSenderAddress, NetworkInterface networkInterface)
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel sendingChannel = DatagramChannel.open();
        // In order to be source-specific the sender's address must be known. The sendingChannel is
        // explicitly bound to a known, non-loopback address.
        sendingChannel.bind(new InetSocketAddress(senderBindAddress, 0));
        InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress();

        DatagramChannel receivingChannel = DatagramChannel.open();
        receivingChannel.bind(
                new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */);
        configureChannelForReceiving(receivingChannel);

        InetSocketAddress localReceivingAddress =
                (InetSocketAddress) receivingChannel.getLocalAddress();
        InetSocketAddress groupSocketAddress =
                new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
        MembershipKey membershipKey1 = receivingChannel
                .join(groupSocketAddress.getAddress(), networkInterface, senderBindAddress);

        ByteBuffer receiveBuffer = ByteBuffer.allocate(10);

        // Send a message. It should be received.
        String msg1 = "Hello1";
        sendMessage(sendingChannel, msg1, groupSocketAddress);
        InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
        assertEquals(sourceAddress1, sendingAddress);
        assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position()));

        membershipKey1.drop();

        receivingChannel.join(groupSocketAddress.getAddress(), networkInterface, badSenderAddress);

        // Send a message. It should not be received.
        String msg2 = "Hello2";
        sendMessage(sendingChannel, msg2, groupSocketAddress);
        InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
        assertNull(sourceAddress2);

        receivingChannel.close();
        sendingChannel.close();
    }

    public void test_dropSourceSpecific_twice_IPv4() throws Exception {
        test_dropSourceSpecific_twice(
                GOOD_MULTICAST_IPv4 /* groupAddress */, UNICAST_IPv4_1 /* sourceAddress */,
                ipv4NetworkInterface);
    }

    public void test_dropSourceSpecific_twice_IPv6() throws Exception {
        test_dropSourceSpecific_twice(
                GOOD_MULTICAST_IPv6 /* groupAddress */, UNICAST_IPv6_1 /* sourceAddress */,
                ipv6NetworkInterface);
    }

    private void test_dropSourceSpecific_twice(InetAddress groupAddress, InetAddress sourceAddress,
            NetworkInterface networkInterface)
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(groupAddress, networkInterface, sourceAddress);

        assertTrue(membershipKey.isValid());
        membershipKey.drop();
        assertFalse(membershipKey.isValid());

        // Try to leave a group we are no longer a member of - should do nothing.
        membershipKey.drop();

        dc.close();
    }

    public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv4() throws Exception {
        test_dropSourceSpecific_sourceKeysAreIndependent(
                GOOD_MULTICAST_IPv4 /* groupAddress */,
                UNICAST_IPv4_1 /* sourceAddress1 */,
                UNICAST_IPv4_2 /* sourceAddress2 */,
                ipv4NetworkInterface);
    }

    public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv6() throws Exception {
        test_dropSourceSpecific_sourceKeysAreIndependent(
                GOOD_MULTICAST_IPv6 /* groupAddress */,
                UNICAST_IPv6_1 /* sourceAddress1 */,
                UNICAST_IPv6_2 /* sourceAddress2 */,
                ipv6NetworkInterface);
    }

    private void test_dropSourceSpecific_sourceKeysAreIndependent(
            InetAddress groupAddress, InetAddress sourceAddress1, InetAddress sourceAddress2,
            NetworkInterface networkInterface) throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface, sourceAddress1);
        MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface, sourceAddress2);
        assertFalse(membershipKey1.equals(membershipKey2));
        assertTrue(membershipKey1.isValid());
        assertTrue(membershipKey2.isValid());

        membershipKey1.drop();

        assertFalse(membershipKey1.isValid());
        assertTrue(membershipKey2.isValid());

        dc.close();
    }

    public void test_drop_keyBehaviorAfterDrop() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        DatagramChannel dc = createReceiverChannel();
        MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
        membershipKey.drop();
        assertFalse(membershipKey.isValid());

        try {
            membershipKey.block(UNICAST_IPv4_1);
            fail();
        } catch (IllegalStateException expected) {
        }

        try {
            membershipKey.unblock(UNICAST_IPv4_1);
            fail();
        } catch (IllegalStateException expected) {
        }

        assertSame(dc, membershipKey.channel());
        assertSame(GOOD_MULTICAST_IPv4, membershipKey.group());
        assertSame(UNICAST_IPv4_1, membershipKey.sourceAddress());
        assertSame(ipv4NetworkInterface, membershipKey.networkInterface());
    }

    private static void configureChannelForReceiving(DatagramChannel receivingChannel)
            throws Exception {

        // NOTE: At the time of writing setSoTimeout() has no effect in the RI, making these tests hang
        // if the channel is in blocking mode. configureBlocking(false) is used instead and rely on the
        // network to the local host being instantaneous.
        // receivingChannel.socket().setSoTimeout(200);
        // receivingChannel.configureBlocking(true);
        receivingChannel.configureBlocking(false);
    }

    private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
        return iface.isUp()
                // Typically loopback interfaces do not support multicast, but they are ruled out
                // explicitly here anyway.
                && !iface.isLoopback() && iface.supportsMulticast()
                && iface.getInetAddresses().hasMoreElements();
    }

    private static void sendMulticastMessage(InetAddress group, int port, String msg)
            throws IOException {
        sendMulticastMessage(group, port, msg, null /* networkInterface */);
    }

    private static void sendMulticastMessage(
            InetAddress group, int port, String msg, NetworkInterface sendingInterface)
            throws IOException {
        // Any datagram socket can send to a group. It does not need to have joined the group.
        DatagramChannel dc = DatagramChannel.open();
        if (sendingInterface != null) {
            // For some reason, if set, this must be set to a real (non-loopback) device for an IPv6
            // group, but can be loopback for an IPv4 group.
            dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, sendingInterface);
        }
        sendMessage(dc, msg, new InetSocketAddress(group, port));
        dc.close();
    }

    private static void sendMessage(
            DatagramChannel sendingChannel, String msg, InetSocketAddress targetAddress)
            throws IOException {

        ByteBuffer sendBuffer = ByteBuffer.wrap(msg.getBytes());
        sendingChannel.send(sendBuffer, targetAddress);
    }

    private static InetAddress getLocalIpv4Address(NetworkInterface networkInterface) {
        for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
            if (interfaceAddress.getAddress() instanceof Inet4Address) {
                return interfaceAddress.getAddress();
            }
        }
        throw new AssertionFailedError("Unable to find local IPv4 address for " + networkInterface);
    }

    private static InetAddress getLocalIpv6Address(NetworkInterface networkInterface) {
        for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
            if (interfaceAddress.getAddress() instanceof Inet6Address) {
                return interfaceAddress.getAddress();
            }
        }
        throw new AssertionFailedError("Unable to find local IPv6 address for " + networkInterface);
    }
}

