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