Source for java.net.MulticastSocket

   1: /* MulticastSocket.java -- Class for using multicast sockets
   2:    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2007
   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:     InetAddress address;
 207:     if (netIf != null)
 208:       out:
 209:       {
 210:         Enumeration e = netIf.getInetAddresses();
 211:         if (getLocalAddress() instanceof Inet4Address)
 212:           {
 213:             // Search for a IPv4 address.
 214:             while (e.hasMoreElements())
 215:               {
 216:                 address = (InetAddress) e.nextElement();
 217:                 if (address instanceof Inet4Address)
 218:                   break out;
 219:               }
 220:             throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
 221:           }
 222:         else if (getLocalAddress() instanceof Inet6Address)
 223:           {
 224:             // Search for a IPv6 address.
 225:             while (e.hasMoreElements())
 226:               {
 227:                 address = (InetAddress) e.nextElement();
 228:                 if (address instanceof Inet6Address)
 229:                   break out;
 230:               }
 231:             throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
 232:           }
 233:         else
 234:           throw new SocketException("interface " + netIf.getName() + " has no suitable IP address");
 235:       }
 236:     else
 237:       address = InetAddress.ANY_IF;
 238:     
 239:     
 240:     getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
 241:   }
 242: 
 243:   /**
 244:    * Gets the local network interface which is used to send multicast messages
 245:    *
 246:    * @return The local network interface to send multicast messages
 247:    *
 248:    * @exception SocketException If an error occurs
 249:    *
 250:    * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
 251:    *
 252:    * @since 1.4
 253:    */
 254:   public NetworkInterface getNetworkInterface() throws SocketException
 255:   {
 256:     if (isClosed())
 257:       throw new SocketException("socket is closed");
 258: 
 259:     InetAddress address =
 260:       (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
 261:     
 262:     if (address.isAnyLocalAddress())
 263:       return NetworkInterface.createAnyInterface();
 264:     
 265:     NetworkInterface netIf = NetworkInterface.getByInetAddress(address);
 266: 
 267:     return netIf;
 268:   }
 269: 
 270:   /**
 271:    * Disable/Enable local loopback of multicast packets.  The option is used by
 272:    * the platform's networking code as a hint for setting whether multicast
 273:    * data will be looped back to the local socket.
 274:    *
 275:    * Because this option is a hint, applications that want to verify what
 276:    * loopback mode is set to should call #getLoopbackMode
 277:    *
 278:    * @param disable True to disable loopback mode
 279:    *
 280:    * @exception SocketException If an error occurs
 281:    *
 282:    * @since 1.4
 283:    */
 284:   public void setLoopbackMode(boolean disable) throws SocketException
 285:   {
 286:     if (isClosed())
 287:       throw new SocketException("socket is closed");
 288: 
 289:     getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP,
 290:                         Boolean.valueOf(disable));
 291:   }
 292: 
 293:   /**
 294:    * Checks if local loopback mode is enabled
 295:    *
 296:    * @return true if loopback mode is enabled, false otherwise
 297:    * 
 298:    * @exception SocketException If an error occurs
 299:    *
 300:    * @since 1.4
 301:    */
 302:   public boolean getLoopbackMode() throws SocketException
 303:   {
 304:     if (isClosed())
 305:       throw new SocketException("socket is closed");
 306: 
 307:     Object buf = getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP);
 308: 
 309:     if (buf instanceof Boolean)
 310:       return ((Boolean) buf).booleanValue();
 311: 
 312:     throw new SocketException("unexpected type");
 313:   }
 314: 
 315:   /**
 316:    * Sets the "Time to Live" value for a socket.  The value must be between
 317:    * 1 and 255.
 318:    *
 319:    * @param ttl The new TTL value
 320:    *
 321:    * @exception IOException If an error occurs
 322:    *
 323:    * @deprecated 1.2 Replaced by <code>setTimeToLive</code>
 324:    *
 325:    * @see MulticastSocket#setTimeToLive(int ttl)
 326:    */
 327:   public void setTTL(byte ttl) throws IOException
 328:   {
 329:     if (isClosed())
 330:       throw new SocketException("socket is closed");
 331: 
 332:     // Use setTTL here rather than setTimeToLive in case we're using an impl
 333:     // other than the default PlainDatagramSocketImpl and it doesn't have
 334:     // setTimeToLive yet.
 335:     getImpl().setTTL(ttl);
 336:   }
 337: 
 338:   /**
 339:    * Sets the "Time to Live" value for a socket.  The value must be between
 340:    * 0 and 255, inclusive.
 341:    *
 342:    * @param ttl The new TTL value
 343:    *
 344:    * @exception IOException If an error occurs
 345:    *
 346:    * @since 1.2
 347:    */
 348:   public void setTimeToLive(int ttl) throws IOException
 349:   {
 350:     if (isClosed())
 351:       throw new SocketException("socket is closed");
 352: 
 353:     if (ttl < 0 || ttl > 255)
 354:       throw new IllegalArgumentException("Invalid ttl: " + ttl);
 355: 
 356:     getImpl().setTimeToLive(ttl);
 357:   }
 358: 
 359:   /**
 360:    * Joins the specified multicast group.
 361:    *
 362:    * @param mcastaddr The address of the group to join
 363:    *
 364:    * @exception IOException If an error occurs
 365:    * @exception SecurityException If a security manager exists and its
 366:    * checkMulticast method doesn't allow the operation
 367:    */
 368:   public void joinGroup(InetAddress mcastaddr) throws IOException
 369:   {
 370:     if (isClosed())
 371:       throw new SocketException("socket is closed");
 372: 
 373:     if (! mcastaddr.isMulticastAddress())
 374:       throw new IOException("Not a Multicast address");
 375: 
 376:     SecurityManager s = System.getSecurityManager();
 377:     if (s != null)
 378:       s.checkMulticast(mcastaddr);
 379: 
 380:     getImpl().join(mcastaddr);
 381:   }
 382: 
 383:   /**
 384:    * Leaves the specified multicast group
 385:    *
 386:    * @param mcastaddr The address of the group to leave
 387:    *
 388:    * @exception IOException If an error occurs
 389:    * @exception SecurityException If a security manager exists and its
 390:    * checkMulticast method doesn't allow the operation
 391:    */
 392:   public void leaveGroup(InetAddress mcastaddr) throws IOException
 393:   {
 394:     if (isClosed())
 395:       throw new SocketException("socket is closed");
 396: 
 397:     if (! mcastaddr.isMulticastAddress())
 398:       throw new IOException("Not a Multicast address");
 399: 
 400:     SecurityManager s = System.getSecurityManager();
 401:     if (s != null)
 402:       s.checkMulticast(mcastaddr);
 403: 
 404:     getImpl().leave(mcastaddr);
 405:   }
 406: 
 407:   /**
 408:    * Joins the specified mulitcast group on a specified interface.
 409:    *
 410:    * @param mcastaddr The multicast address to join
 411:    * @param netIf The local network interface to receive the multicast
 412:    * messages on or null to defer the interface set by #setInterface or
 413:    * #setNetworkInterface
 414:    *
 415:    * @exception IOException If an error occurs
 416:    * @exception IllegalArgumentException If address type is not supported
 417:    * @exception SecurityException If a security manager exists and its
 418:    * checkMulticast method doesn't allow the operation
 419:    *
 420:    * @see MulticastSocket#setInterface(InetAddress addr)
 421:    * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
 422:    *
 423:    * @since 1.4
 424:    */
 425:   public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
 426:     throws IOException
 427:   {
 428:     if (isClosed())
 429:       throw new SocketException("socket is closed");
 430: 
 431:     if (! (mcastaddr instanceof InetSocketAddress))
 432:       throw new IllegalArgumentException("SocketAddress type not supported");
 433: 
 434:     InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
 435: 
 436:     if (! tmp.getAddress().isMulticastAddress())
 437:       throw new IOException("Not a Multicast address");
 438: 
 439:     SecurityManager s = System.getSecurityManager();
 440:     if (s != null)
 441:       s.checkMulticast(tmp.getAddress());
 442: 
 443:     getImpl().joinGroup(mcastaddr, netIf);
 444:   }
 445: 
 446:   /**
 447:    * Leaves the specified mulitcast group on a specified interface.
 448:    *
 449:    * @param mcastaddr The multicast address to leave
 450:    * @param netIf The local networki interface or null to defer to the
 451:    * interface set by setInterface or setNetworkInterface
 452:    *
 453:    * @exception IOException If an error occurs
 454:    * @exception IllegalArgumentException If address type is not supported
 455:    * @exception SecurityException If a security manager exists and its
 456:    * checkMulticast method doesn't allow the operation
 457:    *
 458:    * @see MulticastSocket#setInterface(InetAddress addr)
 459:    * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
 460:    *
 461:    * @since 1.4
 462:    */
 463:   public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
 464:     throws IOException
 465:   {
 466:     if (isClosed())
 467:       throw new SocketException("socket is closed");
 468: 
 469:     InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
 470: 
 471:     if (! tmp.getAddress().isMulticastAddress())
 472:       throw new IOException("Not a Multicast address");
 473: 
 474:     SecurityManager s = System.getSecurityManager();
 475:     if (s != null)
 476:       s.checkMulticast(tmp.getAddress());
 477: 
 478:     getImpl().leaveGroup(mcastaddr, netIf);
 479:   }
 480: 
 481:   /**
 482:    * Sends a packet of data to a multicast address with a TTL that is
 483:    * different from the default TTL on this socket.  The default TTL for
 484:    * the socket is not changed.
 485:    *
 486:    * @param packet The packet of data to send
 487:    * @param ttl The TTL for this packet
 488:    *
 489:    * @exception IOException If an error occurs
 490:    * @exception SecurityException If a security manager exists and its
 491:    * checkConnect or checkMulticast method doesn't allow the operation
 492:    *
 493:    * @deprecated
 494:    */
 495:   public synchronized void send(DatagramPacket packet, byte ttl)
 496:     throws IOException
 497:   {
 498:     if (isClosed())
 499:       throw new SocketException("socket is closed");
 500: 
 501:     SecurityManager s = System.getSecurityManager();
 502:     if (s != null)
 503:       {
 504:     InetAddress addr = packet.getAddress();
 505:     if (addr.isMulticastAddress())
 506:       s.checkPermission(new SocketPermission(addr.getHostName()
 507:                                              + packet.getPort(),
 508:                                              "accept,connect"));
 509:     else
 510:       s.checkConnect(addr.getHostAddress(), packet.getPort());
 511:       }
 512: 
 513:     int oldttl = getImpl().getTimeToLive();
 514:     getImpl().setTimeToLive(((int) ttl) & 0xFF);
 515:     getImpl().send(packet);
 516:     getImpl().setTimeToLive(oldttl);
 517:   }
 518: }