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