/* MulticastSocket.java -- Class for using multicast sockets
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.net;

import java.io.IOException;
import java.util.Enumeration;


/**
 * Written using on-line Java Platform 1.2 API Specification, as well
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
 * Status:  Believed complete and correct.
 */
/**
 * This class models a multicast UDP socket.  A multicast address is a
 * class D internet address (one whose most significant bits are 1110).
 * A multicast group consists of a multicast address and a well known
 * port number.  All members of the group listening on that address and
 * port will receive all the broadcasts to the group.
 * <p>
 * Please note that applets are not allowed to use multicast sockets
 *
 * Written using on-line Java Platform 1.2 API Specification, as well
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
 * Status:  Believed complete and correct.
 *
 * @author Warren Levy (warrenl@cygnus.com)
 * @author Aaron M. Renn (arenn@urbanophile.com) (Documentation comments)
 * @since 1.1
 * @date May 18, 1999.
 */
public class MulticastSocket extends DatagramSocket
{
  /**
   * Create a MulticastSocket that this not bound to any address
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkListen method doesn't allow the operation
   */
  public MulticastSocket() throws IOException
  {
    this(new InetSocketAddress(0));
  }

  /**
   * Create a multicast socket bound to the specified port
   *
   * @param port The port to bind to
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkListen method doesn't allow the operation
   */
  public MulticastSocket(int port) throws IOException
  {
    this(new InetSocketAddress(port));
  }

  /**
   * Create a multicast socket bound to the specified SocketAddress.
   *
   * @param address The SocketAddress the multicast socket will be bound to
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkListen method doesn't allow the operation
   *
   * @since 1.4
   */
  public MulticastSocket(SocketAddress address) throws IOException
  {
    super((SocketAddress) null);
    setReuseAddress(true);
    if (address != null)
      bind(address);
  }

  /**
   * Returns the interface being used for multicast packets
   *
   * @return The multicast interface
   *
   * @exception SocketException If an error occurs
   */
  public InetAddress getInterface() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    return (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
  }

  /**
   * Returns the current value of the "Time to Live" option.  This is the
   * number of hops a packet can make before it "expires".   This method id
   * deprecated.  Use <code>getTimeToLive</code> instead.
   *
   * @return The TTL value
   *
   * @exception IOException If an error occurs
   *
   * @deprecated 1.2 Replaced by getTimeToLive()
   *
   * @see MulticastSocket#getTimeToLive()
   */
  public byte getTTL() throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    // Use getTTL here rather than getTimeToLive in case we're using an impl
    // other than the default PlainDatagramSocketImpl and it doesn't have
    // getTimeToLive yet.
    return getImpl().getTTL();
  }

  /**
   * Returns the current value of the "Time to Live" option.  This is the
   * number of hops a packet can make before it "expires".
   *
   * @return The TTL value
   *
   * @exception IOException If an error occurs
   *
   * @since 1.2
   */
  public int getTimeToLive() throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    return getImpl().getTimeToLive();
  }

  /**
   * Sets the interface to use for sending multicast packets.
   *
   * @param addr The new interface to use.
   *
   * @exception SocketException If an error occurs.
   *
   * @since 1.4
   */
  public void setInterface(InetAddress addr) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().setOption(SocketOptions.IP_MULTICAST_IF, addr);
  }

  /**
   * Sets the local network interface used to send multicast messages
   *
   * @param netIf The local network interface used to send multicast messages
   *
   * @exception SocketException If an error occurs
   *
   * @see MulticastSocket#getNetworkInterface()
   *
   * @since 1.4
   */
  public void setNetworkInterface(NetworkInterface netIf)
    throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Enumeration e = netIf.getInetAddresses();

    if (! e.hasMoreElements())
      throw new SocketException("no network devices found");

    InetAddress address = (InetAddress) e.nextElement();
    getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
  }

  /**
   * Gets the local network interface which is used to send multicast messages
   *
   * @return The local network interface to send multicast messages
   *
   * @exception SocketException If an error occurs
   *
   * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
   *
   * @since 1.4
   */
  public NetworkInterface getNetworkInterface() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    InetAddress address =
      (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
    NetworkInterface netIf = NetworkInterface.getByInetAddress(address);

    return netIf;
  }

  /**
   * Disable/Enable local loopback of multicast packets.  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.
   *
   * Because this option is a hint, applications that want to verify what
   * loopback mode is set to should call #getLoopbackMode
   *
   * @param disable True to disable loopback mode
   *
   * @exception SocketException If an error occurs
   *
   * @since 1.4
   */
  public void setLoopbackMode(boolean disable) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP,
                        Boolean.valueOf(disable));
  }

  /**
   * Checks if local loopback mode is enabled
   *
   * @return true if loopback mode is enabled, false otherwise
   * 
   * @exception SocketException If an error occurs
   *
   * @since 1.4
   */
  public boolean getLoopbackMode() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object buf = getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP);

    if (buf instanceof Boolean)
      return ((Boolean) buf).booleanValue();

    throw new SocketException("unexpected type");
  }

  /**
   * Sets the "Time to Live" value for a socket.  The value must be between
   * 1 and 255.
   *
   * @param ttl The new TTL value
   *
   * @exception IOException If an error occurs
   *
   * @deprecated 1.2 Replaced by <code>setTimeToLive</code>
   *
   * @see MulticastSocket#setTimeToLive(int ttl)
   */
  public void setTTL(byte ttl) throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    // Use setTTL here rather than setTimeToLive in case we're using an impl
    // other than the default PlainDatagramSocketImpl and it doesn't have
    // setTimeToLive yet.
    getImpl().setTTL(ttl);
  }

  /**
   * Sets the "Time to Live" value for a socket.  The value must be between
   * 1 and 255.
   *
   * @param ttl The new TTL value
   *
   * @exception IOException If an error occurs
   *
   * @since 1.2
   */
  public void setTimeToLive(int ttl) throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (ttl <= 0 || ttl > 255)
      throw new IllegalArgumentException("Invalid ttl: " + ttl);

    getImpl().setTimeToLive(ttl);
  }

  /**
   * Joins the specified multicast group.
   *
   * @param mcastaddr The address of the group to join
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkMulticast method doesn't allow the operation
   */
  public void joinGroup(InetAddress mcastaddr) throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (! mcastaddr.isMulticastAddress())
      throw new IOException("Not a Multicast address");

    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkMulticast(mcastaddr);

    getImpl().join(mcastaddr);
  }

  /**
   * Leaves the specified multicast group
   *
   * @param mcastaddr The address of the group to leave
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkMulticast method doesn't allow the operation
   */
  public void leaveGroup(InetAddress mcastaddr) throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (! mcastaddr.isMulticastAddress())
      throw new IOException("Not a Multicast address");

    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkMulticast(mcastaddr);

    getImpl().leave(mcastaddr);
  }

  /**
   * Joins the specified mulitcast group on a specified interface.
   *
   * @param mcastaddr The multicast address to join
   * @param netIf The local network interface to receive the multicast
   * messages on or null to defer the interface set by #setInterface or
   * #setNetworkInterface
   *
   * @exception IOException If an error occurs
   * @exception IllegalArgumentException If address type is not supported
   * @exception SecurityException If a security manager exists and its
   * checkMulticast method doesn't allow the operation
   *
   * @see MulticastSocket#setInterface(InetAddress addr)
   * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
   *
   * @since 1.4
   */
  public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
    throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (! (mcastaddr instanceof InetSocketAddress))
      throw new IllegalArgumentException("SocketAddress type not supported");

    InetSocketAddress tmp = (InetSocketAddress) mcastaddr;

    if (! tmp.getAddress().isMulticastAddress())
      throw new IOException("Not a Multicast address");

    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkMulticast(tmp.getAddress());

    getImpl().joinGroup(mcastaddr, netIf);
  }

  /**
   * Leaves the specified mulitcast group on a specified interface.
   *
   * @param mcastaddr The multicast address to leave
   * @param netIf The local networki interface or null to defer to the
   * interface set by setInterface or setNetworkInterface
   *
   * @exception IOException If an error occurs
   * @exception IllegalArgumentException If address type is not supported
   * @exception SecurityException If a security manager exists and its
   * checkMulticast method doesn't allow the operation
   *
   * @see MulticastSocket#setInterface(InetAddress addr)
   * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
   *
   * @since 1.4
   */
  public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
    throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    InetSocketAddress tmp = (InetSocketAddress) mcastaddr;

    if (! tmp.getAddress().isMulticastAddress())
      throw new IOException("Not a Multicast address");

    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkMulticast(tmp.getAddress());

    getImpl().leaveGroup(mcastaddr, netIf);
  }

  /**
   * Sends a packet of data to a multicast address with a TTL that is
   * different from the default TTL on this socket.  The default TTL for
   * the socket is not changed.
   *
   * @param packet The packet of data to send
   * @param ttl The TTL for this packet
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect or checkMulticast method doesn't allow the operation
   *
   * @deprecated
   */
  public synchronized void send(DatagramPacket packet, byte ttl)
    throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    SecurityManager s = System.getSecurityManager();
    if (s != null)
      {
	InetAddress addr = packet.getAddress();
	if (addr.isMulticastAddress())
	  s.checkPermission(new SocketPermission(addr.getHostName()
	                                         + packet.getPort(),
	                                         "accept,connect"));
	else
	  s.checkConnect(addr.getHostAddress(), packet.getPort());
      }

    int oldttl = getImpl().getTimeToLive();
    getImpl().setTimeToLive(((int) ttl) & 0xFF);
    getImpl().send(packet);
    getImpl().setTimeToLive(oldttl);
  }
}
