Frames | No Frames |
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: }