Source for java.net.MulticastSocket

   1: /* MulticastSocket.java -- Class for using multicast sockets
   2:    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: package java.net;
  40: 
  41: import java.io.IOException;
  42: import java.util.Enumeration;
  43: 
  44: 
  45: /**
  46:  * Written using on-line Java Platform 1.2 API Specification, as well
  47:  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
  48:  * Status:  Believed complete and correct.
  49:  */
  50: /**
  51:  * This class models a multicast UDP socket.  A multicast address is a
  52:  * class D internet address (one whose most significant bits are 1110).
  53:  * A multicast group consists of a multicast address and a well known
  54:  * port number.  All members of the group listening on that address and
  55:  * port will receive all the broadcasts to the group.
  56:  * <p>
  57:  * Please note that applets are not allowed to use multicast sockets
  58:  *
  59:  * Written using on-line Java Platform 1.2 API Specification, as well
  60:  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
  61:  * Status:  Believed complete and correct.
  62:  *
  63:  * @author Warren Levy (warrenl@cygnus.com)
  64:  * @author Aaron M. Renn (arenn@urbanophile.com) (Documentation comments)
  65:  * @since 1.1
  66:  * @date May 18, 1999.
  67:  */
  68: public class MulticastSocket extends DatagramSocket
  69: {
  70:   /**
  71:    * Create a MulticastSocket that this not bound to any address
  72:    *
  73:    * @exception IOException If an error occurs
  74:    * @exception SecurityException If a security manager exists and its
  75:    * checkListen method doesn't allow the operation
  76:    */
  77:   public MulticastSocket() throws IOException
  78:   {
  79:     this(new InetSocketAddress(0));
  80:   }
  81: 
  82:   /**
  83:    * Create a multicast socket bound to the specified port
  84:    *
  85:    * @param port The port to bind to
  86:    *
  87:    * @exception IOException If an error occurs
  88:    * @exception SecurityException If a security manager exists and its
  89:    * checkListen method doesn't allow the operation
  90:    */
  91:   public MulticastSocket(int port) throws IOException
  92:   {
  93:     this(new InetSocketAddress(port));
  94:   }
  95: 
  96:   /**
  97:    * Create a multicast socket bound to the specified SocketAddress.
  98:    *
  99:    * @param address The SocketAddress the multicast socket will be bound to
 100:    *
 101:    * @exception IOException If an error occurs
 102:    * @exception SecurityException If a security manager exists and its
 103:    * checkListen method doesn't allow the operation
 104:    *
 105:    * @since 1.4
 106:    */
 107:   public MulticastSocket(SocketAddress address) throws IOException
 108:   {
 109:     super((SocketAddress) null);
 110:     setReuseAddress(true);
 111:     if (address != null)
 112:       bind(address);
 113:   }
 114: 
 115:   /**
 116:    * Returns the interface being used for multicast packets
 117:    *
 118:    * @return The multicast interface
 119:    *
 120:    * @exception SocketException If an error occurs
 121:    */
 122:   public InetAddress getInterface() throws SocketException
 123:   {
 124:     if (isClosed())
 125:       throw new SocketException("socket is closed");
 126: 
 127:     return (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
 128:   }
 129: 
 130:   /**
 131:    * Returns the current value of the "Time to Live" option.  This is the
 132:    * number of hops a packet can make before it "expires".   This method id
 133:    * deprecated.  Use <code>getTimeToLive</code> instead.
 134:    *
 135:    * @return The TTL value
 136:    *
 137:    * @exception IOException If an error occurs
 138:    *
 139:    * @deprecated 1.2 Replaced by getTimeToLive()
 140:    *
 141:    * @see MulticastSocket#getTimeToLive()
 142:    */
 143:   public byte getTTL() throws IOException
 144:   {
 145:     if (isClosed())
 146:       throw new SocketException("socket is closed");
 147: 
 148:     // Use getTTL here rather than getTimeToLive in case we're using an impl
 149:     // other than the default PlainDatagramSocketImpl and it doesn't have
 150:     // getTimeToLive yet.
 151:     return getImpl().getTTL();
 152:   }
 153: 
 154:   /**
 155:    * Returns the current value of the "Time to Live" option.  This is the
 156:    * number of hops a packet can make before it "expires".
 157:    *
 158:    * @return The TTL value
 159:    *
 160:    * @exception IOException If an error occurs
 161:    *
 162:    * @since 1.2
 163:    */
 164:   public int getTimeToLive() throws IOException
 165:   {
 166:     if (isClosed())
 167:       throw new SocketException("socket is closed");
 168: 
 169:     return getImpl().getTimeToLive();
 170:   }
 171: 
 172:   /**
 173:    * Sets the interface to use for sending multicast packets.
 174:    *
 175:    * @param addr The new interface to use.
 176:    *
 177:    * @exception SocketException If an error occurs.
 178:    *
 179:    * @since 1.4
 180:    */
 181:   public void setInterface(InetAddress addr) throws SocketException
 182:   {
 183:     if (isClosed())
 184:       throw new SocketException("socket is closed");
 185: 
 186:     getImpl().setOption(SocketOptions.IP_MULTICAST_IF, addr);
 187:   }
 188: 
 189:   /**
 190:    * Sets the local network interface used to send multicast messages
 191:    *
 192:    * @param netIf The local network interface used to send multicast messages
 193:    *
 194:    * @exception SocketException If an error occurs
 195:    *
 196:    * @see MulticastSocket#getNetworkInterface()
 197:    *
 198:    * @since 1.4
 199:    */
 200:   public void setNetworkInterface(NetworkInterface netIf)
 201:     throws SocketException
 202:   {
 203:     if (isClosed())
 204:       throw new SocketException("socket is closed");
 205: 
 206:     Enumeration e = netIf.getInetAddresses();
 207: 
 208:     if (! e.hasMoreElements())
 209:       throw new SocketException("no network devices found");
 210: 
 211:     InetAddress address = (InetAddress) e.nextElement();
 212:     getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
 213:   }
 214: 
 215:   /**
 216:    * Gets the local network interface which is used to send multicast messages
 217:    *
 218:    * @return The local network interface to send multicast messages
 219:    *
 220:    * @exception SocketException If an error occurs
 221:    *
 222:    * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
 223:    *
 224:    * @since 1.4
 225:    */
 226:   public NetworkInterface getNetworkInterface() throws SocketException
 227:   {
 228:     if (isClosed())
 229:       throw new SocketException("socket is closed");
 230: 
 231:     InetAddress address =
 232:       (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
 233:     NetworkInterface netIf = NetworkInterface.getByInetAddress(address);
 234: 
 235:     return netIf;
 236:   }
 237: 
 238:   /**
 239:    * Disable/Enable local loopback of multicast packets.  The option is used by
 240:    * the platform's networking code as a hint for setting whether multicast
 241:    * data will be looped back to the local socket.
 242:    *
 243:    * Because this option is a hint, applications that want to verify what
 244:    * loopback mode is set to should call #getLoopbackMode
 245:    *
 246:    * @param disable True to disable loopback mode
 247:    *
 248:    * @exception SocketException If an error occurs
 249:    *
 250:    * @since 1.4
 251:    */
 252:   public void setLoopbackMode(boolean disable) throws SocketException
 253:   {
 254:     if (isClosed())
 255:       throw new SocketException("socket is closed");
 256: 
 257:     getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP,
 258:                         Boolean.valueOf(disable));
 259:   }
 260: 
 261:   /**
 262:    * Checks if local loopback mode is enabled
 263:    *
 264:    * @return true if loopback mode is enabled, false otherwise
 265:    * 
 266:    * @exception SocketException If an error occurs
 267:    *
 268:    * @since 1.4
 269:    */
 270:   public boolean getLoopbackMode() throws SocketException
 271:   {
 272:     if (isClosed())
 273:       throw new SocketException("socket is closed");
 274: 
 275:     Object buf = getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP);
 276: 
 277:     if (buf instanceof Boolean)
 278:       return ((Boolean) buf).booleanValue();
 279: 
 280:     throw new SocketException("unexpected type");
 281:   }
 282: 
 283:   /**
 284:    * Sets the "Time to Live" value for a socket.  The value must be between
 285:    * 1 and 255.
 286:    *
 287:    * @param ttl The new TTL value
 288:    *
 289:    * @exception IOException If an error occurs
 290:    *
 291:    * @deprecated 1.2 Replaced by <code>setTimeToLive</code>
 292:    *
 293:    * @see MulticastSocket#setTimeToLive(int ttl)
 294:    */
 295:   public void setTTL(byte ttl) throws IOException
 296:   {
 297:     if (isClosed())
 298:       throw new SocketException("socket is closed");
 299: 
 300:     // Use setTTL here rather than setTimeToLive in case we're using an impl
 301:     // other than the default PlainDatagramSocketImpl and it doesn't have
 302:     // setTimeToLive yet.
 303:     getImpl().setTTL(ttl);
 304:   }
 305: 
 306:   /**
 307:    * Sets the "Time to Live" value for a socket.  The value must be between
 308:    * 1 and 255.
 309:    *
 310:    * @param ttl The new TTL value
 311:    *
 312:    * @exception IOException If an error occurs
 313:    *
 314:    * @since 1.2
 315:    */
 316:   public void setTimeToLive(int ttl) throws IOException
 317:   {
 318:     if (isClosed())
 319:       throw new SocketException("socket is closed");
 320: 
 321:     if (ttl <= 0 || ttl > 255)
 322:       throw new IllegalArgumentException("Invalid ttl: " + ttl);
 323: 
 324:     getImpl().setTimeToLive(ttl);
 325:   }
 326: 
 327:   /**
 328:    * Joins the specified multicast group.
 329:    *
 330:    * @param mcastaddr The address of the group to join
 331:    *
 332:    * @exception IOException If an error occurs
 333:    * @exception SecurityException If a security manager exists and its
 334:    * checkMulticast method doesn't allow the operation
 335:    */
 336:   public void joinGroup(InetAddress mcastaddr) throws IOException
 337:   {
 338:     if (isClosed())
 339:       throw new SocketException("socket is closed");
 340: 
 341:     if (! mcastaddr.isMulticastAddress())
 342:       throw new IOException("Not a Multicast address");
 343: 
 344:     SecurityManager s = System.getSecurityManager();
 345:     if (s != null)
 346:       s.checkMulticast(mcastaddr);
 347: 
 348:     getImpl().join(mcastaddr);
 349:   }
 350: 
 351:   /**
 352:    * Leaves the specified multicast group
 353:    *
 354:    * @param mcastaddr The address of the group to leave
 355:    *
 356:    * @exception IOException If an error occurs
 357:    * @exception SecurityException If a security manager exists and its
 358:    * checkMulticast method doesn't allow the operation
 359:    */
 360:   public void leaveGroup(InetAddress mcastaddr) throws IOException
 361:   {
 362:     if (isClosed())
 363:       throw new SocketException("socket is closed");
 364: 
 365:     if (! mcastaddr.isMulticastAddress())
 366:       throw new IOException("Not a Multicast address");
 367: 
 368:     SecurityManager s = System.getSecurityManager();
 369:     if (s != null)
 370:       s.checkMulticast(mcastaddr);
 371: 
 372:     getImpl().leave(mcastaddr);
 373:   }
 374: 
 375:   /**
 376:    * Joins the specified mulitcast group on a specified interface.
 377:    *
 378:    * @param mcastaddr The multicast address to join
 379:    * @param netIf The local network interface to receive the multicast
 380:    * messages on or null to defer the interface set by #setInterface or
 381:    * #setNetworkInterface
 382:    *
 383:    * @exception IOException If an error occurs
 384:    * @exception IllegalArgumentException If address type is not supported
 385:    * @exception SecurityException If a security manager exists and its
 386:    * checkMulticast method doesn't allow the operation
 387:    *
 388:    * @see MulticastSocket#setInterface(InetAddress addr)
 389:    * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
 390:    *
 391:    * @since 1.4
 392:    */
 393:   public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
 394:     throws IOException
 395:   {
 396:     if (isClosed())
 397:       throw new SocketException("socket is closed");
 398: 
 399:     if (! (mcastaddr instanceof InetSocketAddress))
 400:       throw new IllegalArgumentException("SocketAddress type not supported");
 401: 
 402:     InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
 403: 
 404:     if (! tmp.getAddress().isMulticastAddress())
 405:       throw new IOException("Not a Multicast address");
 406: 
 407:     SecurityManager s = System.getSecurityManager();
 408:     if (s != null)
 409:       s.checkMulticast(tmp.getAddress());
 410: 
 411:     getImpl().joinGroup(mcastaddr, netIf);
 412:   }
 413: 
 414:   /**
 415:    * Leaves the specified mulitcast group on a specified interface.
 416:    *
 417:    * @param mcastaddr The multicast address to leave
 418:    * @param netIf The local networki interface or null to defer to the
 419:    * interface set by setInterface or setNetworkInterface
 420:    *
 421:    * @exception IOException If an error occurs
 422:    * @exception IllegalArgumentException If address type is not supported
 423:    * @exception SecurityException If a security manager exists and its
 424:    * checkMulticast method doesn't allow the operation
 425:    *
 426:    * @see MulticastSocket#setInterface(InetAddress addr)
 427:    * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
 428:    *
 429:    * @since 1.4
 430:    */
 431:   public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
 432:     throws IOException
 433:   {
 434:     if (isClosed())
 435:       throw new SocketException("socket is closed");
 436: 
 437:     InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
 438: 
 439:     if (! tmp.getAddress().isMulticastAddress())
 440:       throw new IOException("Not a Multicast address");
 441: 
 442:     SecurityManager s = System.getSecurityManager();
 443:     if (s != null)
 444:       s.checkMulticast(tmp.getAddress());
 445: 
 446:     getImpl().leaveGroup(mcastaddr, netIf);
 447:   }
 448: 
 449:   /**
 450:    * Sends a packet of data to a multicast address with a TTL that is
 451:    * different from the default TTL on this socket.  The default TTL for
 452:    * the socket is not changed.
 453:    *
 454:    * @param packet The packet of data to send
 455:    * @param ttl The TTL for this packet
 456:    *
 457:    * @exception IOException If an error occurs
 458:    * @exception SecurityException If a security manager exists and its
 459:    * checkConnect or checkMulticast method doesn't allow the operation
 460:    *
 461:    * @deprecated
 462:    */
 463:   public synchronized void send(DatagramPacket packet, byte ttl)
 464:     throws IOException
 465:   {
 466:     if (isClosed())
 467:       throw new SocketException("socket is closed");
 468: 
 469:     SecurityManager s = System.getSecurityManager();
 470:     if (s != null)
 471:       {
 472:     InetAddress addr = packet.getAddress();
 473:     if (addr.isMulticastAddress())
 474:       s.checkPermission(new SocketPermission(addr.getHostName()
 475:                                              + packet.getPort(),
 476:                                              "accept,connect"));
 477:     else
 478:       s.checkConnect(addr.getHostAddress(), packet.getPort());
 479:       }
 480: 
 481:     int oldttl = getImpl().getTimeToLive();
 482:     getImpl().setTimeToLive(((int) ttl) & 0xFF);
 483:     getImpl().send(packet);
 484:     getImpl().setTimeToLive(oldttl);
 485:   }
 486: }