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