/*
 * Copyright (c) 2007, 2025, 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 4742177
 * @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code
 * @requires os.family != "windows"
 * @library /test/lib
 */
import java.util.*;
import java.net.*;
import jdk.test.lib.NetworkConfiguration;
import jdk.test.lib.net.IPSupport;

public class NoLoopbackPackets {

    private static final String MESSAGE = "hello world (" + System.nanoTime() + ")";

    public static void main(String[] args) throws Exception {

        MulticastSocket msock = null;
        List<SocketAddress> failedGroups = new ArrayList<SocketAddress>();
        Sender sender = null;
        Thread senderThread = null;
        try {
            msock = new MulticastSocket();
            int port = msock.getLocalPort();

            // we will send packets to three multicast groups :-
            // 224.1.1.1, ::ffff:224.1.1.2, and ff02::1:1
            //
            List<SocketAddress> groups = new ArrayList<SocketAddress>();
            if (IPSupport.hasIPv4()) {
                groups.add(new InetSocketAddress(InetAddress.getByName("224.1.1.1"), port));
            }

            NetworkConfiguration nc = NetworkConfiguration.probe();
            if (IPSupport.hasIPv6() && nc.hasTestableIPv6Address()) {
                groups.add(new InetSocketAddress(InetAddress.getByName("::ffff:224.1.1.2"), port));
                groups.add(new InetSocketAddress(InetAddress.getByName("ff02::1:1"), port));
            }
            if (groups.isEmpty()) {
                System.err.println("Nothing to test: there are no network interfaces");
            }

            sender = new Sender(groups);
            senderThread = new Thread(sender);
            senderThread.start();

            // Now try to receive multicast packets. we should not see any of them
            // since we disable loopback mode.
            //
            msock.setSoTimeout(5000);       // 5 seconds

            byte[] buf = new byte[1024];
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) 'z';
            }
            DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
            byte[] expected = MESSAGE.getBytes();
            assert expected.length <= buf.length;
            for (SocketAddress group : groups) {
                System.out.println("joining group: " + group);
                msock.joinGroup(group, null);

                try {
                    do {
                        for (int i = 0; i < buf.length; i++) {
                            buf[i] = (byte) 'a';
                        }
                        msock.receive(packet);
                        byte[] data = packet.getData();
                        int len = packet.getLength();

                        if (expected(data, len, expected)) {
                            failedGroups.add(group);
                            break;
                        } else {
                            System.err.println("WARNING: Unexpected packet received from "
                                               + group + ": "
                                               + len + " bytes");
                            System.err.println("\t as text: " + new String(data, 0, len));
                        }
                    } while (true);
                } catch (SocketTimeoutException e) {
                    // we expect this
                    System.out.println("Received expected exception from " + group + ": " + e);
                } finally {
                    msock.leaveGroup(group, null);
                }
            }
        } finally {
            if (msock != null) try { msock.close(); } catch (Exception e) {}
            if (sender != null) {
                sender.stop();
            }
        }
        try {
            if (failedGroups.size() > 0) {
                System.out.println("We should not receive anything from following groups, but we did:");
                for (SocketAddress group : failedGroups)
                    System.out.println(group);
                throw new RuntimeException("test failed.");
            }
        } finally {
            if (senderThread != null) {
                senderThread.join();
            }
        }
    }

    static boolean expected(byte[] data, int len, byte[] expected) {
        if (len != expected.length) return false;
        for (int i = 0; i < len; i++) {
            if (data[i] != expected[i]) return false;
        }
        return true;
    }

    static class Sender implements Runnable {
        private List<SocketAddress> sendToGroups;
        private volatile boolean stop;

        public Sender(List<SocketAddress> groups) {
            sendToGroups = groups;
        }

        public void run() {
            byte[] buf = MESSAGE.getBytes();
            List<DatagramPacket> packets = new ArrayList<DatagramPacket>();

            try (MulticastSocket msock = new MulticastSocket()) {
                for (SocketAddress group : sendToGroups) {
                    DatagramPacket packet = new DatagramPacket(buf, buf.length, group);
                    packets.add(packet);
                }

                msock.setLoopbackMode(true);    // disable loopback mode
                while (!stop) {
                    for (DatagramPacket packet : packets) {
                        msock.send(packet);
                    }

                    Thread.sleep(1000);     // 1 second
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        void stop() {
            stop = true;
        }
    }
}
