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