/*
 * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @bug 4527345
 * @summary Unit test for DatagramChannel's multicast support
 * @build MulticastSendReceiveTests NetworkConfiguration
 * @run main MulticastSendReceiveTests
 */

import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;

public class MulticastSendReceiveTests {

    static Random rand = new Random();

    /**
     * Send datagram from given local address to given multicast
     * group.
     */
    static int sendDatagram(InetAddress local,
                            NetworkInterface nif,
                            InetAddress group,
                            int port)
        throws IOException
    {
        ProtocolFamily family = (group instanceof Inet6Address) ?
            StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
        DatagramChannel dc = DatagramChannel.open(family)
            .bind(new InetSocketAddress(local, 0))
            .setOption(StandardSocketOption.IP_MULTICAST_IF, nif);
        int id = rand.nextInt();
        byte[] msg = Integer.toString(id).getBytes("UTF-8");
        ByteBuffer buf = ByteBuffer.wrap(msg);
        System.out.format("Send message from %s -> group %s (id=0x%x)\n",
            local.getHostAddress(), group.getHostAddress(), id);
        dc.send(buf, new InetSocketAddress(group, port));
        dc.close();
        return id;
    }

    /**
     * Wait (with timeout) for datagram.
     *
     * @param   expectedSender - expected sender address, or
     *                           null if no datagram expected
     * @param   id - expected id of datagram
     */
    static void receiveDatagram(DatagramChannel dc,
                                InetAddress expectedSender,
                                int id)
        throws IOException
    {
        Selector sel = Selector.open();
        dc.configureBlocking(false);
        dc.register(sel, SelectionKey.OP_READ);
        ByteBuffer buf = ByteBuffer.allocateDirect(100);

        try {
            for (;;) {
                System.out.println("Waiting to receive message");
                sel.select(5*1000);
                SocketAddress sa = dc.receive(buf);

                // no datagram received
                if (sa == null) {
                    if (expectedSender != null) {
                        throw new RuntimeException("Expected message not recieved");
                    }
                    System.out.println("No message received (correct)");
                    return;
                }

                // datagram received

                InetAddress sender = ((InetSocketAddress)sa).getAddress();
                buf.flip();
                byte[] bytes = new byte[buf.remaining()];
                buf.get(bytes);
                int receivedId = Integer.parseInt(new String(bytes));

                System.out.format("Received message from %s (id=0x%x)\n",
                    sender, receivedId);

                if (expectedSender == null) {
                    if (receivedId == id)
                        throw new RuntimeException("Message not expected");
                    System.out.println("Message ignored (has wrong id)");
                } else {
                    if (sender.equals(expectedSender)) {
                        System.out.println("Message expected");
                        return;
                    }
                    System.out.println("Message ignored (wrong sender)");
                }

                sel.selectedKeys().clear();
                buf.rewind();
            }
        } finally {
            sel.close();
        }
    }


    /**
     * Exercise multicast send/receive on given group/interface
     */
    static void test(NetworkInterface nif, InetAddress group, InetAddress source)
        throws IOException
    {
        ProtocolFamily family = (group instanceof Inet6Address) ?
            StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
        System.out.format("create channel to %s socket\n", family.name());
        DatagramChannel dc = DatagramChannel.open(family)
            .setOption(StandardSocketOption.SO_REUSEADDR, true)
            .bind(new InetSocketAddress(0));

        // join group
        System.out.format("join %s @ %s\n", group.getHostAddress(),
            nif.getName());
        MembershipKey key = dc.join(group, nif);

        // send message to group
        int port = ((InetSocketAddress)dc.getLocalAddress()).getPort();
        int id = sendDatagram(source, nif, group, port);

        // receive message and check id matches
        receiveDatagram(dc, source, id);

        // exclude-mode filtering

        try {
            System.out.format("block %s\n", source.getHostAddress());

            // may throw UOE
            key.block(source);
            id = sendDatagram(source, nif, group, port);
            receiveDatagram(dc, null, id);

            // unblock source, send message, message should be received
            System.out.format("unblock %s\n", source.getHostAddress());
            key.unblock(source);
            id = sendDatagram(source, nif, group, port);
            receiveDatagram(dc, source, id);
        } catch (UnsupportedOperationException x) {
            System.out.println("Exclude-mode filtering not supported!");
        }

        key.drop();

        // include-mode filtering

        InetAddress bogus = (group instanceof Inet6Address) ?
            InetAddress.getByName("fe80::1234") :
            InetAddress.getByName("1.2.3.4");
        System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
            nif.getName(), bogus.getHostAddress());
        try {
            // may throw UOE
            key = dc.join(group, nif, bogus);

            id = sendDatagram(source, nif, group, port);
            receiveDatagram(dc, null, id);

            System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
                nif.getName(), source.getHostAddress());
            key = dc.join(group, nif, source);

            id = sendDatagram(source, nif, group, port);
            receiveDatagram(dc, source, id);
        } catch (UnsupportedOperationException x) {
            System.out.println("Include-mode filtering not supported!");
        }

        // done
        dc.close();
    }

    public static void main(String[] args) throws IOException {
        NetworkConfiguration config = NetworkConfiguration.probe();

        // multicast groups used for the test
        InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
        InetAddress ip6Group = InetAddress.getByName("ff02::a");

        for (NetworkInterface nif: config.ip4Interfaces()) {
            InetAddress source = config.ip4Addresses(nif).iterator().next();
            test(nif, ip4Group, source);
        }

        for (NetworkInterface nif: config.ip6Interfaces()) {
            InetAddress source = config.ip6Addresses(nif).iterator().next();
            test(nif, ip6Group, source);
        }
    }
}
