mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			519 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			519 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
/* MulticastSocket.java -- Class for using multicast sockets
 | 
						|
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2007
 | 
						|
   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., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 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");
 | 
						|
 | 
						|
    InetAddress address;
 | 
						|
    if (netIf != null)
 | 
						|
      out:
 | 
						|
      {
 | 
						|
        Enumeration e = netIf.getInetAddresses();
 | 
						|
        if (getLocalAddress() instanceof Inet4Address)
 | 
						|
          {
 | 
						|
            // Search for a IPv4 address.
 | 
						|
            while (e.hasMoreElements())
 | 
						|
              {
 | 
						|
                address = (InetAddress) e.nextElement();
 | 
						|
                if (address instanceof Inet4Address)
 | 
						|
                  break out;
 | 
						|
              }
 | 
						|
            throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
 | 
						|
          }
 | 
						|
        else if (getLocalAddress() instanceof Inet6Address)
 | 
						|
          {
 | 
						|
            // Search for a IPv6 address.
 | 
						|
            while (e.hasMoreElements())
 | 
						|
              {
 | 
						|
                address = (InetAddress) e.nextElement();
 | 
						|
                if (address instanceof Inet6Address)
 | 
						|
                  break out;
 | 
						|
              }
 | 
						|
            throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
 | 
						|
          }
 | 
						|
        else
 | 
						|
          throw new SocketException("interface " + netIf.getName() + " has no suitable IP address");
 | 
						|
      }
 | 
						|
    else
 | 
						|
      address = InetAddress.ANY_IF;
 | 
						|
 | 
						|
 | 
						|
    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);
 | 
						|
 | 
						|
    if (address.isAnyLocalAddress())
 | 
						|
      return NetworkInterface.createAnyInterface();
 | 
						|
 | 
						|
    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
 | 
						|
   * 0 and 255, inclusive.
 | 
						|
   *
 | 
						|
   * @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);
 | 
						|
  }
 | 
						|
}
 |