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