mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			520 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			520 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);
 | |
|     
 | |
|     // FIXME: libgcj doesn't have createAnyInterface.
 | |
| //     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);
 | |
|   }
 | |
| }
 |