/*
 * Copyright (c) 1995, 2024, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

package java.net;

import java.io.IOException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MulticastChannel;

/**
 * A {@code MulticastSocket} is a datagram socket that is
 * convenient for sending and receiving IP multicast datagrams.
 * The {@code MulticastSocket} constructors create a socket
 * with appropriate socket options enabled that make
 * it suitable for receiving multicast datagrams.
 * The {@code MulticastSocket} class additionally defines
 * convenient setter and getter methods for socket options
 * that are commonly used by multicasting applications.
 * <P>
 * Joining one or more multicast groups makes it possible to
 * receive multicast datagrams sent to these groups.
 * <P>
 * An IPv4 multicast group is specified by a class D IP address
 * and by a standard UDP port number. Class D IP addresses
 * are in the range {@code 224.0.0.0} to {@code 239.255.255.255},
 * inclusive. The address 224.0.0.0 is reserved and should not be used.
 * <P>
 * One would join a multicast group by first creating a MulticastSocket
 * with the desired port, then invoking the
 * <CODE>joinGroup</CODE> method, specifying the group address and
 * the network interface through which multicast datagrams will be
 * received:
 * <PRE>{@code
 * // join a Multicast group and send the group salutations
 * ...
 * String msg = "Hello";
 * InetAddress mcastaddr = InetAddress.getByName("228.5.6.7");
 * InetSocketAddress group = new InetSocketAddress(mcastaddr, 6789);
 * NetworkInterface netIf = NetworkInterface.getByName("bge0");
 * MulticastSocket s = new MulticastSocket(6789);
 *
 * s.joinGroup(new InetSocketAddress(mcastaddr, 0), netIf);
 * byte[] msgBytes = msg.getBytes(StandardCharsets.UTF_8);
 * DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, group);
 * s.send(hi);
 * // get their responses!
 * byte[] buf = new byte[1000];
 * DatagramPacket recv = new DatagramPacket(buf, buf.length);
 * s.receive(recv);
 * ...
 * // OK, I'm done talking - leave the group...
 * s.leaveGroup(group, netIf);
 * }</PRE>
 *
 * When one sends a message to a multicast group, <B>all</B> subscribing
 * recipients to that host and port receive the message (within the
 * time-to-live range of the packet, see below). The socket needn't
 * be a member of the multicast group to send messages to it.
 * <P>
 * When a socket subscribes to a multicast group/port, it receives
 * datagrams sent by other hosts to the group/port, as do all other
 * members of the group and port.  A socket relinquishes membership
 * in a group by the leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
 * method.
 * <B>Multiple MulticastSockets</B> may subscribe to a multicast group
 * and port concurrently, and they will all receive group datagrams.
 *
 * <p> The {@code DatagramSocket} and {@code MulticastSocket}
 * classes define convenience methods to set and get several
 * socket options. Like {@code DatagramSocket} this class also
 * supports the {@link #setOption(SocketOption, Object) setOption}
 * and {@link #getOption(SocketOption) getOption} methods to set
 * and query socket options.
 * <a id="MulticastOptions"></a>The set of supported socket options
 * is defined in <a href="DatagramSocket.html#SocketOptions">{@code DatagramSocket}</a>.
 * Additional (implementation specific) options may also be supported.
 *
 * @apiNote {@link DatagramSocket} may be used directly for
 *          sending and receiving multicast datagrams.
 *          {@link DatagramChannel} implements the {@link MulticastChannel} interface
 *          and provides an alternative API for sending and receiving multicast datagrams.
 *          The {@link MulticastChannel} API supports both {@linkplain
 *          MulticastChannel#join(InetAddress, NetworkInterface) any-source} and
 *          {@linkplain MulticastChannel#join(InetAddress, NetworkInterface, InetAddress)
 *          source-specific} multicast. Consider using {@link DatagramChannel} for
 *          multicasting.
 *
 * @author Pavani Diwanji
 * @since 1.1
 */
public class MulticastSocket extends DatagramSocket {

    @Override
    final MulticastSocket delegate() {
        return (MulticastSocket) super.delegate();
    }

    /**
     * Create a MulticastSocket that delegates to the given delegate if not null.
     * @param delegate the delegate, can be null.
     */
    MulticastSocket(MulticastSocket delegate) {
        super(delegate);
    }

    /**
     * Constructs a multicast socket and binds it to any available port
     * on the local host machine.  The socket will be bound to the
     * {@link InetAddress#isAnyLocalAddress wildcard} address.
     *
     * <p>
     * When the socket is created the
     * {@link DatagramSocket#setReuseAddress(boolean)} method is called to
     * enable the SO_REUSEADDR socket option.
     *
     * @throws    IOException if an I/O exception occurs while creating the
     * MulticastSocket
     * @see java.net.DatagramSocket#setReuseAddress(boolean)
     * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object)
     */
    public MulticastSocket() throws IOException {
        this(new InetSocketAddress(0));
    }

    /**
     * Constructs a multicast socket and binds it to the specified port
     * on the local host machine. The socket will be bound to the
     * {@link InetAddress#isAnyLocalAddress wildcard} address.
     *
     * <p>
     * When the socket is created the
     * {@link DatagramSocket#setReuseAddress(boolean)} method is
     * called to enable the SO_REUSEADDR socket option.
     *
     * @param     port port to use
     * @throws    IOException if an I/O exception occurs
     *            while creating the MulticastSocket
     * @throws    IllegalArgumentException  if port is  <a href="DatagramSocket.html#PortRange">
     *            out of range.</a>
     *
     * @see       java.net.DatagramSocket#setReuseAddress(boolean)
     */
    public MulticastSocket(int port) throws IOException {
        this(new InetSocketAddress(port));
    }

    /**
     * Creates a multicast socket, bound to the specified local
     * socket address.
     * <p>
     * If the address is {@code null} an unbound socket will be created.
     * <p>
     * When the socket is created the
     * {@link DatagramSocket#setReuseAddress(boolean)} method is
     * called to enable the SO_REUSEADDR socket option.
     *
     * @param    bindaddr Socket address to bind to, or {@code null} for
     *           an unbound socket.
     * @throws   IOException if an I/O exception occurs
     *           while creating the MulticastSocket
     * @see      java.net.DatagramSocket#setReuseAddress(boolean)
     *
     * @since 1.4
     */
    public MulticastSocket(SocketAddress bindaddr) throws IOException {
        this(createDelegate(bindaddr, MulticastSocket.class));
    }

    /**
     * Set the default time-to-live for multicast packets sent out
     * on this {@code MulticastSocket} in order to control the
     * scope of the multicasts.
     *
     * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be
     * in the range {@code 0 <= ttl <= 0xFF }.
     *
     * @param      ttl the time-to-live
     * @throws     IOException if an I/O exception occurs
     *             while setting the default time-to-live value, or the socket is closed.
     * @deprecated use the {@link #setTimeToLive(int)} method instead, which uses
     *             <b>int</b> instead of <b>byte</b> as the type for ttl.
     * @see #getTTL()
     */
    @Deprecated(forRemoval = true, since = "1.2")
    public void setTTL(byte ttl) throws IOException {
        delegate().setTTL(ttl);
    }

    /**
     * Set the default time-to-live for multicast packets sent out
     * on this {@code MulticastSocket} in order to control the
     * scope of the multicasts.
     *
     * <P> The ttl <B>must</B> be in the range {@code  0 <= ttl <=
     * 255} or an {@code IllegalArgumentException} will be thrown.
     * Multicast packets sent with a TTL of {@code 0} are not transmitted
     * on the network but may be delivered locally.
     *
     * @apiNote
     * This method is equivalent to calling {@link #setOption(SocketOption, Object)
     * setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl)}.
     *
     * @param  ttl
     *         the time-to-live
     *
     * @throws  IOException
     *          if an I/O exception occurs while setting the
     *          default time-to-live value, or the socket is closed.
     *
     * @see #getTimeToLive()
     * @see StandardSocketOptions#IP_MULTICAST_TTL
     * @since 1.2
     */
    public void setTimeToLive(int ttl) throws IOException {
        delegate().setTimeToLive(ttl);
    }

    /**
     * Get the default time-to-live for multicast packets sent out on
     * the socket.
     *
     * @throws    IOException if an I/O exception occurs
     *            while getting the default time-to-live value, or the socket is closed.
     * @return the default time-to-live value
     * @deprecated use the {@link #getTimeToLive()} method instead,
     * which returns an <b>int</b> instead of a <b>byte</b>.
     * @see #setTTL(byte)
     */
    @Deprecated(forRemoval = true, since = "1.2")
    public byte getTTL() throws IOException {
        return delegate().getTTL();
    }

    /**
     * Get the default time-to-live for multicast packets sent out on
     * the socket.
     *
     * @apiNote
     * This method is equivalent to calling {@link #getOption(SocketOption)
     * getOption(StandardSocketOptions.IP_MULTICAST_TTL)}.
     *
     * @throws    IOException if an I/O exception occurs while
     *            getting the default time-to-live value, or the socket is closed.
     * @return the default time-to-live value
     * @see #setTimeToLive(int)
     * @see StandardSocketOptions#IP_MULTICAST_TTL
     * @since 1.2
     */
    public int getTimeToLive() throws IOException {
        return delegate().getTimeToLive();
    }

    /**
     * Joins a multicast group. Its behavior may be affected by
     * {@code setInterface} or {@code setNetworkInterface}.
     *
     * @apiNote
     * Calling this method is equivalent to calling
     * {@link #joinGroup(SocketAddress, NetworkInterface)
     * joinGroup(new InetSocketAddress(mcastaddr, 0), null)}.
     *
     * @param      mcastaddr is the multicast address to join
     * @throws     IOException if there is an error joining,
     *             or when the address is not a multicast address,
     *             or the platform does not support multicasting, or the socket is closed.
     * @deprecated This method does not accept the network interface on
     *             which to join the multicast group. Use
     *             {@link #joinGroup(SocketAddress, NetworkInterface)} instead.
     */
    @Deprecated(since="14")
    public void joinGroup(InetAddress mcastaddr) throws IOException {
        delegate().joinGroup(mcastaddr);
    }

    /**
     * Leave a multicast group. Its behavior may be affected by
     * {@code setInterface} or {@code setNetworkInterface}.
     *
     * @apiNote
     * Calling this method is equivalent to calling
     * {@link #leaveGroup(SocketAddress, NetworkInterface)
     * leaveGroup(new InetSocketAddress(mcastaddr, 0), null)}.
     *
     * @param      mcastaddr is the multicast address to leave
     * @throws     IOException if there is an error leaving
     *             or when the address is not a multicast address, or the socket is closed.
     * @deprecated This method does not accept the network interface on which
     *             to leave the multicast group. Use
     *             {@link #leaveGroup(SocketAddress, NetworkInterface)} instead.
     */
    @Deprecated(since="14")
    public void leaveGroup(InetAddress mcastaddr) throws IOException {
        delegate().leaveGroup(mcastaddr);
    }

    /**
     * {@inheritDoc}
     * @throws IOException {@inheritDoc}
     * @throws IllegalArgumentException {@inheritDoc}
     * @see    DatagramChannel#join(InetAddress, NetworkInterface)
     * @see    StandardSocketOptions#IP_MULTICAST_IF
     * @see    #setNetworkInterface(NetworkInterface)
     * @see    #setInterface(InetAddress)
     * @since 1.4
     */
    @Override
    public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
            throws IOException {
        super.joinGroup(mcastaddr, netIf);
    }

    /**
     * {@inheritDoc}
     * @apiNote {@inheritDoc}
     * @throws IOException {@inheritDoc}
     * @throws IllegalArgumentException {@inheritDoc}
     * @see    #joinGroup(SocketAddress, NetworkInterface)
     * @since 1.4
     */
    @Override
    public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
            throws IOException {
        super.leaveGroup(mcastaddr, netIf);
    }

    /**
     * Set the multicast network interface used by methods
     * whose behavior would be affected by the value of the
     * network interface. Useful for multihomed hosts.
     *
     * @param      inf the InetAddress
     * @throws     SocketException if there is an error in
     *             the underlying protocol, such as a TCP error, or the socket is closed.
     * @deprecated The InetAddress may not uniquely identify
     *             the network interface. Use
     *             {@link #setNetworkInterface(NetworkInterface)} instead.
     * @see        #getInterface()
     */
    @Deprecated(since="14")
    public void setInterface(InetAddress inf) throws SocketException {
        delegate().setInterface(inf);
    }

    /**
     * Retrieve the address of the network interface used for
     * multicast packets.
     *
     * @return     An {@code InetAddress} representing the address
     *             of the network interface used for multicast packets,
     *             or if no interface has been set, an {@code InetAddress}
     *             representing any local address.
     * @throws     SocketException if there is an error in the
     *             underlying protocol, such as a TCP error, or the socket is closed.
     * @deprecated The network interface may not be uniquely identified by
     *             the InetAddress returned.
     *             Use {@link #getNetworkInterface()} instead.
     * @see        #setInterface(java.net.InetAddress)
     */
    @Deprecated(since="14")
    public InetAddress getInterface() throws SocketException {
        return delegate().getInterface();
    }

    /**
     * Specify the network interface for outgoing multicast datagrams
     * sent on this socket.
     *
     * @apiNote
     * This method is equivalent to calling {@link #setOption(SocketOption, Object)
     * setOption(StandardSocketOptions.IP_MULTICAST_IF, netIf)}.
     *
     * @param netIf the interface
     * @throws    SocketException if there is an error in
     *            the underlying protocol, such as a TCP error, or the socket is closed.
     * @see #getNetworkInterface()
     * @see StandardSocketOptions#IP_MULTICAST_IF
     * @since 1.4
     */
    public void setNetworkInterface(NetworkInterface netIf)
        throws SocketException {
        delegate().setNetworkInterface(netIf);
    }

    /**
     * Get the multicast network interface set for outgoing multicast
     * datagrams sent from this socket.
     *
     * @apiNote
     * When an interface is set, this method is equivalent
     * to calling {@link #getOption(SocketOption)
     * getOption(StandardSocketOptions.IP_MULTICAST_IF)}.
     *
     * @throws SocketException if there is an error in
     *         the underlying protocol, such as a TCP error, or the socket is closed.
     * @return The multicast {@code NetworkInterface} currently set. A placeholder
     *         NetworkInterface is returned when there is no interface set; it has
     *         a single InetAddress to represent any local address.
     * @see    #setNetworkInterface(NetworkInterface)
     * @see    StandardSocketOptions#IP_MULTICAST_IF
     * @since  1.4
     */
    public NetworkInterface getNetworkInterface() throws SocketException {
        return delegate().getNetworkInterface();
    }

    /**
     * Disable/Enable local loopback of multicast datagrams.
     * The option is used by the platform's networking code as a hint
     * for setting whether multicast data will be looped back to
     * the local socket.
     *
     * <p>Because this option is a hint, applications that want to
     * verify what loopback mode is set to should call
     * {@link #getLoopbackMode()}
     * @param      disable {@code true} to disable the LoopbackMode
     * @throws     SocketException if an error occurs while setting the value, or
     *             the socket is closed.
     * @since      1.4
     * @deprecated Use {@link #setOption(SocketOption, Object)} with
     *             {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP}
     *             instead. The loopback mode is enabled by default,
     *             {@code MulticastSocket.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false)}
     *             disables it.
     * @see        #getLoopbackMode
     */
    @Deprecated(since="14")
    public void setLoopbackMode(boolean disable) throws SocketException {
        delegate().setLoopbackMode(disable);
    }

    /**
     * Get the setting for local loopback of multicast datagrams.
     *
     * @throws     SocketException if an error occurs while getting the value, or
     *             the socket is closed.
     * @return     true if the LoopbackMode has been disabled
     * @since      1.4
     * @deprecated Use {@link #getOption(SocketOption)} with
     *             {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP}
     *             instead.
     * @see        #setLoopbackMode
     */
    @Deprecated(since="14")
    public boolean getLoopbackMode() throws SocketException {
        return delegate().getLoopbackMode();
    }

    /**
     * Sends a datagram packet to the destination, with a TTL (time-to-live)
     * other than the default for the socket.  This method
     * need only be used in instances where a particular TTL is desired;
     * otherwise it is preferable to set a TTL once on the socket, and
     * use that default TTL for all packets.  This method does <B>not
     * </B> alter the default TTL for the socket. Its behavior may be
     * affected by {@code setInterface}.
     *
     * @param p is the packet to be sent. The packet should contain
     * the destination multicast ip address and the data to be sent.
     * One does not need to be the member of the group to send
     * packets to a destination multicast address.
     * @param ttl optional time to live for multicast packet.
     * default ttl is 1.
     *
     * @throws     IOException  if an I/O error occurs, or the socket is closed.
     * @throws     PortUnreachableException may be thrown if the socket is connected
     *             to a currently unreachable destination. Note, there is no
     *             guarantee that the exception will be thrown.
     * @throws     IllegalArgumentException if the socket is connected,
     *             and connected address and packet address differ, or
     *             if the socket is not connected and the packet address
     *             is not set or if its port is out of range.
     *
     *
     * @deprecated Use the following code or its equivalent instead:
     *  <pre>{@code   ......
     *  int ttl = mcastSocket.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
     *  mcastSocket.setOption(StandardSocketOptions.IP_MULTICAST_TTL, newttl);
     *  mcastSocket.send(p);
     *  mcastSocket.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
     *  ......}</pre>
     *
     * @see DatagramSocket#send
     * @see DatagramSocket#receive
     */
    @Deprecated(forRemoval = true, since = "1.4")
    public void send(DatagramPacket p, byte ttl)
        throws IOException {
        delegate().send(p, ttl);
    }
}
