1 /* 2 * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net; 27 28 import java.io.IOException; 29 import java.util.Collections; 30 import java.util.Enumeration; 31 import java.util.Set; 32 33 /** 34 * The multicast datagram socket class is useful for sending 35 * and receiving IP multicast packets. A MulticastSocket is 36 * a (UDP) DatagramSocket, with additional capabilities for 37 * joining "groups" of other multicast hosts on the internet. 38 * <P> 39 * A multicast group is specified by a class D IP address 40 * and by a standard UDP port number. Class D IP addresses 41 * are in the range {@code 224.0.0.0} to {@code 239.255.255.255}, 42 * inclusive. The address 224.0.0.0 is reserved and should not be used. 43 * <P> 44 * One would join a multicast group by first creating a MulticastSocket 45 * with the desired port, then invoking the 46 * <CODE>joinGroup(InetAddress groupAddr)</CODE> 47 * method: 48 * <PRE> 49 * // join a Multicast group and send the group salutations 50 * ... 51 * String msg = "Hello"; 52 * InetAddress mcastaddr = InetAddress.getByName("228.5.6.7"); 53 * InetSocketAddress group = new InetSocketAddress(mcastaddr, port); 54 * NetworkInterface netIf = NetworkInterface.getByName("bge0"); 55 * MulticastSocket s = new MulticastSocket(6789); 56 * 57 * s.joinGroup(group, netIf); 58 * byte[] msgBytes = msg.getBytes(StandardCharsets.UTF_8); 59 * DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, 60 * group, 6789); 61 * s.send(hi); 62 * // get their responses! 63 * byte[] buf = new byte[1000]; 64 * DatagramPacket recv = new DatagramPacket(buf, buf.length); 65 * s.receive(recv); 66 * ... 67 * // OK, I'm done talking - leave the group... 68 * s.leaveGroup(group, netIf); 69 * </PRE> 70 * 71 * When one sends a message to a multicast group, <B>all</B> subscribing 72 * recipients to that host and port receive the message (within the 73 * time-to-live range of the packet, see below). The socket needn't 74 * be a member of the multicast group to send messages to it. 75 * <P> 76 * When a socket subscribes to a multicast group/port, it receives 77 * datagrams sent by other hosts to the group/port, as do all other 78 * members of the group and port. A socket relinquishes membership 79 * in a group by the leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) 80 * method. 81 * <B>Multiple MulticastSockets</B> may subscribe to a multicast group 82 * and port concurrently, and they will all receive group datagrams. 83 * 84 * <p> The {@code DatagramSocket} and {@code MulticastSocket} 85 * classes define convenience methods to set and get several 86 * socket options. Like {@code DatagramSocket} this class also 87 * supports the {@link #setOption(SocketOption, Object) setOption} 88 * and {@link #getOption(SocketOption) getOption} methods to set 89 * and query socket options. 90 * In addition to the socket options supported by 91 * <a href="DatagramSocket.html#SocketOptions">{@code DatagramSocket}</a>, a 92 * {@code MulticastSocket} supports the following socket options: 93 * <blockquote> 94 * <a id="MulticastOptions"></a> 95 * <table class="striped"> 96 * <caption style="display:none">Socket options</caption> 97 * <thead> 98 * <tr> 99 * <th scope="col">Option Name</th> 100 * <th scope="col">Description</th> 101 * </tr> 102 * </thead> 103 * <tbody> 104 * <tr> 105 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_MULTICAST_IF IP_MULTICAST_IF} </th> 106 * <td> The network interface for Internet Protocol (IP) multicast datagrams </td> 107 * </tr> 108 * <tr> 109 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_MULTICAST_TTL 110 * IP_MULTICAST_TTL} </th> 111 * <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast 112 * datagrams </td> 113 * </tr> 114 * <tr> 115 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP 116 * IP_MULTICAST_LOOP} </th> 117 * <td> Loopback for Internet Protocol (IP) multicast datagrams </td> 118 * </tr> 119 * </tbody> 120 * </table> 121 * </blockquote> 122 * Additional (implementation specific) options may also be supported. 123 * 124 * @author Pavani Diwanji 125 * @since 1.1 126 */ 127 public class MulticastSocket extends DatagramSocket { 128 129 /** 130 * Used on some platforms to record if an outgoing interface 131 * has been set for this socket. 132 */ 133 private boolean interfaceSet; 134 135 /** 136 * Create a multicast socket. 137 * 138 * <p> 139 * If there is a security manager, its {@code checkListen} method is first 140 * called with 0 as its argument to ensure the operation is allowed. This 141 * could result in a SecurityException. 142 * <p> 143 * When the socket is created the 144 * {@link DatagramSocket#setReuseAddress(boolean)} method is called to 145 * enable the SO_REUSEADDR socket option. 146 * 147 * @throws IOException if an I/O exception occurs while creating the 148 * MulticastSocket 149 * @throws SecurityException if a security manager exists and its 150 * {@code checkListen} method doesn't allow the operation. 151 * @see SecurityManager#checkListen 152 * @see java.net.DatagramSocket#setReuseAddress(boolean) 153 * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object) 154 */ 155 public MulticastSocket() throws IOException { 156 this(new InetSocketAddress(0)); 157 } 158 159 /** 160 * Create a multicast socket and bind it to a specific port. 161 * 162 * <p>If there is a security manager, 163 * its {@code checkListen} method is first called 164 * with the {@code port} argument 165 * as its argument to ensure the operation is allowed. 166 * This could result in a SecurityException. 167 * <p> 168 * When the socket is created the 169 * {@link DatagramSocket#setReuseAddress(boolean)} method is 170 * called to enable the SO_REUSEADDR socket option. 171 * 172 * @param port port to use 173 * @throws IOException if an I/O exception occurs 174 * while creating the MulticastSocket 175 * @throws SecurityException if a security manager exists and its 176 * {@code checkListen} method doesn't allow the operation. 177 * @see SecurityManager#checkListen 178 * @see java.net.DatagramSocket#setReuseAddress(boolean) 179 */ 180 public MulticastSocket(int port) throws IOException { 181 this(new InetSocketAddress(port)); 182 } 183 184 /** 185 * Create a MulticastSocket bound to the specified socket address. 186 * <p> 187 * Or, if the address is {@code null}, create an unbound socket. 188 * 189 * <p>If there is a security manager, 190 * its {@code checkListen} method is first called 191 * with the SocketAddress port as its argument to ensure the operation is allowed. 192 * This could result in a SecurityException. 193 * <p> 194 * When the socket is created the 195 * {@link DatagramSocket#setReuseAddress(boolean)} method is 196 * called to enable the SO_REUSEADDR socket option. 197 * 198 * @param bindaddr Socket address to bind to, or {@code null} for 199 * an unbound socket. 200 * @throws IOException if an I/O exception occurs 201 * while creating the MulticastSocket 202 * @throws SecurityException if a security manager exists and its 203 * {@code checkListen} method doesn't allow the operation. 204 * @see SecurityManager#checkListen 205 * @see java.net.DatagramSocket#setReuseAddress(boolean) 206 * 207 * @since 1.4 208 */ 209 public MulticastSocket(SocketAddress bindaddr) throws IOException { 210 super((SocketAddress) null); 211 212 // No further initialization when this is a DatagramChannel socket adaptor 213 if (this instanceof sun.nio.ch.DatagramSocketAdaptor) 214 return; 215 216 // Enable SO_REUSEADDR before binding 217 setReuseAddress(true); 218 219 if (bindaddr != null) { 220 try { 221 bind(bindaddr); 222 } finally { 223 if (!isBound()) { 224 close(); 225 } 226 } 227 } 228 } 229 230 /** 231 * The lock on the socket's TTL. This is for set/getTTL and 232 * send(packet,ttl). 233 */ 234 private Object ttlLock = new Object(); 235 236 /** 237 * The lock on the socket's interface - used by setInterface 238 * and getInterface 239 */ 240 private Object infLock = new Object(); 241 242 /** 243 * The "last" interface set by setInterface on this MulticastSocket 244 */ 245 private InetAddress infAddress = null; 246 247 248 /** 249 * Set the default time-to-live for multicast packets sent out 250 * on this {@code MulticastSocket} in order to control the 251 * scope of the multicasts. 252 * 253 * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be 254 * in the range {@code 0 <= ttl <= 0xFF }. 255 * 256 * @param ttl the time-to-live 257 * @throws IOException if an I/O exception occurs 258 * while setting the default time-to-live value 259 * @deprecated use the setTimeToLive method instead, which uses 260 * <b>int</b> instead of <b>byte</b> as the type for ttl. 261 * @see #getTTL() 262 */ 263 @Deprecated 264 public void setTTL(byte ttl) throws IOException { 265 if (isClosed()) 266 throw new SocketException("Socket is closed"); 267 getImpl().setTTL(ttl); 268 } 269 270 /** 271 * Set the default time-to-live for multicast packets sent out 272 * on this {@code MulticastSocket} in order to control the 273 * scope of the multicasts. 274 * 275 * <P> The ttl <B>must</B> be in the range {@code 0 <= ttl <= 276 * 255} or an {@code IllegalArgumentException} will be thrown. 277 * Multicast packets sent with a TTL of {@code 0} are not transmitted 278 * on the network but may be delivered locally. 279 * 280 * @param ttl 281 * the time-to-live 282 * 283 * @throws IOException 284 * if an I/O exception occurs while setting the 285 * default time-to-live value 286 * 287 * @see #getTimeToLive() 288 */ 289 public void setTimeToLive(int ttl) throws IOException { 290 if (ttl < 0 || ttl > 255) { 291 throw new IllegalArgumentException("ttl out of range"); 292 } 293 if (isClosed()) 294 throw new SocketException("Socket is closed"); 295 getImpl().setTimeToLive(ttl); 296 } 297 298 /** 299 * Get the default time-to-live for multicast packets sent out on 300 * the socket. 301 * 302 * @throws IOException if an I/O exception occurs 303 * while getting the default time-to-live value 304 * @return the default time-to-live value 305 * @deprecated use the getTimeToLive method instead, which returns 306 * an <b>int</b> instead of a <b>byte</b>. 307 * @see #setTTL(byte) 308 */ 309 @Deprecated 310 public byte getTTL() throws IOException { 311 if (isClosed()) 312 throw new SocketException("Socket is closed"); 313 return getImpl().getTTL(); 314 } 315 316 /** 317 * Get the default time-to-live for multicast packets sent out on 318 * the socket. 319 * @throws IOException if an I/O exception occurs while 320 * getting the default time-to-live value 321 * @return the default time-to-live value 322 * @see #setTimeToLive(int) 323 */ 324 public int getTimeToLive() throws IOException { 325 if (isClosed()) 326 throw new SocketException("Socket is closed"); 327 return getImpl().getTimeToLive(); 328 } 329 330 /** 331 * Joins a multicast group. Its behavior may be affected by 332 * {@code setInterface} or {@code setNetworkInterface}. 333 * 334 * <p>If there is a security manager, this method first 335 * calls its {@code checkMulticast} method with the 336 * {@code mcastaddr} argument as its argument. 337 * 338 * @param mcastaddr is the multicast address to join 339 * @throws IOException if there is an error joining, 340 * or when the address is not a multicast address, 341 * or the platform does not support multicasting 342 * @throws SecurityException if a security manager exists and its 343 * {@code checkMulticast} method doesn't allow the join. 344 * @deprecated This method does not accept the network interface on 345 * which to join the multicast group. Use 346 * {@link #joinGroup(SocketAddress, NetworkInterface)} instead. 347 * @see SecurityManager#checkMulticast(InetAddress) 348 */ 349 @Deprecated(since="14") 350 public void joinGroup(InetAddress mcastaddr) throws IOException { 351 if (isClosed()) { 352 throw new SocketException("Socket is closed"); 353 } 354 355 checkAddress(mcastaddr, "joinGroup"); 356 SecurityManager security = System.getSecurityManager(); 357 if (security != null) { 358 security.checkMulticast(mcastaddr); 359 } 360 361 if (!mcastaddr.isMulticastAddress()) { 362 throw new SocketException("Not a multicast address"); 363 } 364 365 /** 366 * required for some platforms where it's not possible to join 367 * a group without setting the interface first. 368 */ 369 NetworkInterface defaultInterface = NetworkInterface.getDefault(); 370 371 if (!interfaceSet && defaultInterface != null) { 372 setNetworkInterface(defaultInterface); 373 } 374 375 getImpl().join(mcastaddr); 376 } 377 378 /** 379 * Leave a multicast group. Its behavior may be affected by 380 * {@code setInterface} or {@code setNetworkInterface}. 381 * 382 * <p>If there is a security manager, this method first 383 * calls its {@code checkMulticast} method with the 384 * {@code mcastaddr} argument as its argument. 385 * 386 * @param mcastaddr is the multicast address to leave 387 * @throws IOException if there is an error leaving 388 * or when the address is not a multicast address. 389 * @throws SecurityException if a security manager exists and its 390 * {@code checkMulticast} method doesn't allow the operation. 391 * @deprecated This method does not accept the network interface on which 392 * to leave the multicast group. Use 393 * {@link #leaveGroup(SocketAddress, NetworkInterface)} instead. 394 * @see SecurityManager#checkMulticast(InetAddress) 395 */ 396 @Deprecated(since="14") 397 public void leaveGroup(InetAddress mcastaddr) throws IOException { 398 if (isClosed()) { 399 throw new SocketException("Socket is closed"); 400 } 401 402 checkAddress(mcastaddr, "leaveGroup"); 403 SecurityManager security = System.getSecurityManager(); 404 if (security != null) { 405 security.checkMulticast(mcastaddr); 406 } 407 408 if (!mcastaddr.isMulticastAddress()) { 409 throw new SocketException("Not a multicast address"); 410 } 411 412 getImpl().leave(mcastaddr); 413 } 414 415 /** 416 * Joins the specified multicast group at the specified interface. 417 * 418 * <p>If there is a security manager, this method first 419 * calls its {@code checkMulticast} method 420 * with the {@code mcastaddr} argument 421 * as its argument. 422 * 423 * @param mcastaddr is the multicast address to join 424 * @param netIf specifies the local interface to receive multicast 425 * datagram packets, or {@code null} to defer to the interface set by 426 * {@link MulticastSocket#setInterface(InetAddress)} or 427 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. 428 * If {@code null}, and no interface has been set, the behaviour is 429 * unspecified: any interface may be selected or the operation may fail 430 * with a {@code SocketException}. 431 * @throws IOException if there is an error joining, or when the address 432 * is not a multicast address, or the platform does not support 433 * multicasting 434 * @throws SecurityException if a security manager exists and its 435 * {@code checkMulticast} method doesn't allow the join. 436 * @throws IllegalArgumentException if mcastaddr is {@code null} or is a 437 * SocketAddress subclass not supported by this socket 438 * @see SecurityManager#checkMulticast(InetAddress) 439 * @since 1.4 440 */ 441 public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) 442 throws IOException { 443 if (isClosed()) 444 throw new SocketException("Socket is closed"); 445 446 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) 447 throw new IllegalArgumentException("Unsupported address type"); 448 449 if (oldImpl) 450 throw new UnsupportedOperationException(); 451 452 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "joinGroup"); 453 SecurityManager security = System.getSecurityManager(); 454 if (security != null) { 455 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress()); 456 } 457 458 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) { 459 throw new SocketException("Not a multicast address"); 460 } 461 462 getImpl().joinGroup(mcastaddr, netIf); 463 } 464 465 /** 466 * Leave a multicast group on a specified local interface. 467 * 468 * <p>If there is a security manager, this method first 469 * calls its {@code checkMulticast} method with the 470 * {@code mcastaddr} argument as its argument. 471 * 472 * @param mcastaddr is the multicast address to leave 473 * @param netIf specifies the local interface or {@code null} to defer 474 * to the interface set by 475 * {@link MulticastSocket#setInterface(InetAddress)} or 476 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. 477 * If {@code null}, and no interface has been set, the behaviour 478 * is unspecified: any interface may be selected or the operation 479 * may fail with a {@code SocketException}. 480 * @throws IOException if there is an error leaving or when the address 481 * is not a multicast address. 482 * @throws SecurityException if a security manager exists and its 483 * {@code checkMulticast} method doesn't allow the operation. 484 * @throws IllegalArgumentException if mcastaddr is {@code null} or is a 485 * SocketAddress subclass not supported by this socket. 486 * @see SecurityManager#checkMulticast(InetAddress) 487 * @since 1.4 488 */ 489 public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) 490 throws IOException { 491 if (isClosed()) 492 throw new SocketException("Socket is closed"); 493 494 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) 495 throw new IllegalArgumentException("Unsupported address type"); 496 497 if (oldImpl) 498 throw new UnsupportedOperationException(); 499 500 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "leaveGroup"); 501 SecurityManager security = System.getSecurityManager(); 502 if (security != null) { 503 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress()); 504 } 505 506 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) { 507 throw new SocketException("Not a multicast address"); 508 } 509 510 getImpl().leaveGroup(mcastaddr, netIf); 511 } 512 513 /** 514 * Set the multicast network interface used by methods 515 * whose behavior would be affected by the value of the 516 * network interface. Useful for multihomed hosts. 517 * 518 * @param inf the InetAddress 519 * @throws SocketException if there is an error in 520 * the underlying protocol, such as a TCP error. 521 * @deprecated The InetAddress may not uniquely identify 522 * the network interface. Use 523 * {@link #setNetworkInterface(NetworkInterface)} instead. 524 * @see #getInterface() 525 */ 526 @Deprecated(since="14") 527 public void setInterface(InetAddress inf) throws SocketException { 528 if (isClosed()) { 529 throw new SocketException("Socket is closed"); 530 } 531 checkAddress(inf, "setInterface"); 532 synchronized (infLock) { 533 getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf); 534 infAddress = inf; 535 interfaceSet = true; 536 } 537 } 538 539 /** 540 * Retrieve the address of the network interface used for 541 * multicast packets. 542 * 543 * @return An {@code InetAddress} representing the address 544 * of the network interface used for multicast packets, 545 * or if no interface has been set, an {@code InetAddress} 546 * representing any local address. 547 * @throws SocketException if there is an error in the 548 * underlying protocol, such as a TCP error. 549 * @deprecated The network interface may not be uniquely identified by 550 * the InetAddress returned. 551 * Use {@link #getNetworkInterface()} instead. 552 * @see #setInterface(java.net.InetAddress) 553 */ 554 @Deprecated(since="14") 555 public InetAddress getInterface() throws SocketException { 556 if (isClosed()) { 557 throw new SocketException("Socket is closed"); 558 } 559 synchronized (infLock) { 560 InetAddress ia = 561 (InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF); 562 563 /** 564 * No previous setInterface or interface can be 565 * set using setNetworkInterface 566 */ 567 if (infAddress == null) { 568 return ia; 569 } 570 571 /** 572 * Same interface set with setInterface? 573 */ 574 if (ia.equals(infAddress)) { 575 return ia; 576 } 577 578 /** 579 * Different InetAddress from what we set with setInterface 580 * so enumerate the current interface to see if the 581 * address set by setInterface is bound to this interface. 582 */ 583 try { 584 NetworkInterface ni = NetworkInterface.getByInetAddress(ia); 585 Enumeration<InetAddress> addrs = ni.getInetAddresses(); 586 while (addrs.hasMoreElements()) { 587 InetAddress addr = addrs.nextElement(); 588 if (addr.equals(infAddress)) { 589 return infAddress; 590 } 591 } 592 593 /** 594 * No match so reset infAddress to indicate that the 595 * interface has changed via means 596 */ 597 infAddress = null; 598 return ia; 599 } catch (Exception e) { 600 return ia; 601 } 602 } 603 } 604 605 /** 606 * Specify the network interface for outgoing multicast datagrams 607 * sent on this socket. 608 * 609 * @param netIf the interface 610 * @throws SocketException if there is an error in 611 * the underlying protocol, such as a TCP error. 612 * @see #getNetworkInterface() 613 * @since 1.4 614 */ 615 public void setNetworkInterface(NetworkInterface netIf) 616 throws SocketException { 617 618 synchronized (infLock) { 619 getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf); 620 infAddress = null; 621 interfaceSet = true; 622 } 623 } 624 625 /** 626 * Get the multicast network interface set. 627 * 628 * @throws SocketException if there is an error in 629 * the underlying protocol, such as a TCP error. 630 * @return The multicast {@code NetworkInterface} currently set. A placeholder 631 * NetworkInterface is returned when there is no interface set; it has 632 * a single InetAddress to represent any local address. 633 * @see #setNetworkInterface(NetworkInterface) 634 * @since 1.4 635 */ 636 public NetworkInterface getNetworkInterface() throws SocketException { 637 NetworkInterface ni 638 = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2); 639 if (ni == null) { 640 InetAddress[] addrs = new InetAddress[1]; 641 addrs[0] = InetAddress.anyLocalAddress(); 642 return new NetworkInterface(addrs[0].getHostName(), 0, addrs); 643 } else { 644 return ni; 645 } 646 } 647 648 /** 649 * Disable/Enable local loopback of multicast datagrams 650 * The option is used by the platform's networking code as a hint 651 * for setting whether multicast data will be looped back to 652 * the local socket. 653 * 654 * <p>Because this option is a hint, applications that want to 655 * verify what loopback mode is set to should call 656 * {@link #getLoopbackMode()} 657 * @param disable {@code true} to disable the LoopbackMode 658 * @throws SocketException if an error occurs while setting the value 659 * @since 1.4 660 * @deprecated Use {@link #setOption(SocketOption, Object)} with 661 * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} 662 * instead. The loopback mode is enabled by default, 663 * {@code MulticastSocket.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false)} 664 * disables it. 665 * @see #getLoopbackMode 666 */ 667 @Deprecated(since="14") 668 public void setLoopbackMode(boolean disable) throws SocketException { 669 getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable)); 670 } 671 672 /** 673 * Get the setting for local loopback of multicast datagrams. 674 * 675 * @throws SocketException if an error occurs while getting the value 676 * @return true if the LoopbackMode has been disabled 677 * @since 1.4 678 * @deprecated Use {@link #getOption(SocketOption)} with 679 * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} 680 * instead. 681 * @see #setLoopbackMode 682 */ 683 @Deprecated(since="14") 684 public boolean getLoopbackMode() throws SocketException { 685 return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue(); 686 } 687 688 /** 689 * Sends a datagram packet to the destination, with a TTL (time- 690 * to-live) other than the default for the socket. This method 691 * need only be used in instances where a particular TTL is desired; 692 * otherwise it is preferable to set a TTL once on the socket, and 693 * use that default TTL for all packets. This method does <B>not 694 * </B> alter the default TTL for the socket. Its behavior may be 695 * affected by {@code setInterface}. 696 * 697 * <p>If there is a security manager, this method first performs some 698 * security checks. First, if {@code p.getAddress().isMulticastAddress()} 699 * is true, this method calls the 700 * security manager's {@code checkMulticast} method 701 * with {@code p.getAddress()} and {@code ttl} as its arguments. 702 * If the evaluation of that expression is false, 703 * this method instead calls the security manager's 704 * {@code checkConnect} method with arguments 705 * {@code p.getAddress().getHostAddress()} and 706 * {@code p.getPort()}. Each call to a security manager method 707 * could result in a SecurityException if the operation is not allowed. 708 * 709 * @param p is the packet to be sent. The packet should contain 710 * the destination multicast ip address and the data to be sent. 711 * One does not need to be the member of the group to send 712 * packets to a destination multicast address. 713 * @param ttl optional time to live for multicast packet. 714 * default ttl is 1. 715 * 716 * @throws IOException is raised if an error occurs i.e 717 * error while setting ttl. 718 * @throws SecurityException if a security manager exists and its 719 * {@code checkMulticast} or {@code checkConnect} 720 * method doesn't allow the send. 721 * @throws PortUnreachableException may be thrown if the socket is connected 722 * to a currently unreachable destination. Note, there is no 723 * guarantee that the exception will be thrown. 724 * @throws IllegalArgumentException if the socket is connected, 725 * and connected address and packet address differ, or 726 * if the socket is not connected and the packet address 727 * is not set. 728 * 729 * 730 * @deprecated Use the following code or its equivalent instead: 731 * ...... 732 * int ttl = mcastSocket.getTimeToLive(); 733 * mcastSocket.setTimeToLive(newttl); 734 * mcastSocket.send(p); 735 * mcastSocket.setTimeToLive(ttl); 736 * ...... 737 * 738 * @see DatagramSocket#send 739 * @see DatagramSocket#receive 740 * @see SecurityManager#checkMulticast(java.net.InetAddress, byte) 741 * @see SecurityManager#checkConnect 742 */ 743 @Deprecated 744 public void send(DatagramPacket p, byte ttl) 745 throws IOException { 746 if (isClosed()) 747 throw new SocketException("Socket is closed"); 748 synchronized(ttlLock) { 749 synchronized(p) { 750 InetAddress packetAddress = p.getAddress(); 751 checkAddress(packetAddress, "send"); 752 if (connectState == ST_NOT_CONNECTED) { 753 if (packetAddress == null) { 754 throw new IllegalArgumentException("Address not set"); 755 } 756 // Security manager makes sure that the multicast address 757 // is allowed one and that the ttl used is less 758 // than the allowed maxttl. 759 SecurityManager security = System.getSecurityManager(); 760 if (security != null) { 761 if (packetAddress.isMulticastAddress()) { 762 security.checkMulticast(packetAddress, ttl); 763 } else { 764 security.checkConnect(packetAddress.getHostAddress(), 765 p.getPort()); 766 } 767 } 768 } else { 769 // we're connected 770 if (packetAddress == null) { 771 p.setAddress(connectedAddress); 772 p.setPort(connectedPort); 773 } else if ((!packetAddress.equals(connectedAddress)) || 774 p.getPort() != connectedPort) { 775 throw new IllegalArgumentException("connected address and packet address" + 776 " differ"); 777 } 778 } 779 byte dttl = getTTL(); 780 try { 781 if (ttl != dttl) { 782 // set the ttl 783 getImpl().setTTL(ttl); 784 } 785 // call the datagram method to send 786 getImpl().send(p); 787 } finally { 788 // set it back to default 789 if (ttl != dttl) { 790 getImpl().setTTL(dttl); 791 } 792 } 793 } // synch p 794 } //synch ttl 795 } //method 796 797 private static Set<SocketOption<?>> options; 798 private static boolean optionsSet = false; 799 800 @Override 801 public Set<SocketOption<?>> supportedOptions() { 802 synchronized (MulticastSocket.class) { 803 if (optionsSet) { 804 return options; 805 } 806 try { 807 DatagramSocketImpl impl = getImpl(); 808 options = Collections.unmodifiableSet(impl.supportedOptions()); 809 } catch (SocketException ex) { 810 options = Collections.emptySet(); 811 } 812 optionsSet = true; 813 return options; 814 } 815 } 816 }