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