GNU Classpath (0.95) | |
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: 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: }
GNU Classpath (0.95) |