/jdk/src/share/classes/java/net/DatagramSocket.java
Java | 1197 lines | 437 code | 61 blank | 699 comment | 107 complexity | 809bc1a72b069ff3a89b95073d71d14d MD5 | raw file
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 26package java.net; 27 28import java.io.FileDescriptor; 29import java.io.IOException; 30import java.io.InterruptedIOException; 31import java.nio.channels.DatagramChannel; 32import java.security.AccessController; 33import java.security.PrivilegedExceptionAction; 34 35/** 36 * This class represents a socket for sending and receiving datagram packets. 37 * 38 * <p>A datagram socket is the sending or receiving point for a packet 39 * delivery service. Each packet sent or received on a datagram socket 40 * is individually addressed and routed. Multiple packets sent from 41 * one machine to another may be routed differently, and may arrive in 42 * any order. 43 * 44 * <p>UDP broadcasts sends are always enabled on a DatagramSocket. 45 * In order to receive broadcast packets a DatagramSocket 46 * should be bound to the wildcard address. In some 47 * implementations, broadcast packets may also be received when 48 * a DatagramSocket is bound to a more specific address. 49 * <p> 50 * Example: 51 * <code> 52 * DatagramSocket s = new DatagramSocket(null); 53 * s.bind(new InetSocketAddress(8888)); 54 * </code> 55 * Which is equivalent to: 56 * <code> 57 * DatagramSocket s = new DatagramSocket(8888); 58 * </code> 59 * Both cases will create a DatagramSocket able to receive broadcasts on 60 * UDP port 8888. 61 * 62 * @author Pavani Diwanji 63 * @see java.net.DatagramPacket 64 * @see java.nio.channels.DatagramChannel 65 * @since JDK1.0 66 */ 67public 68class DatagramSocket { 69 /** 70 * Various states of this socket. 71 */ 72 private boolean created = false; 73 private boolean bound = false; 74 private boolean closed = false; 75 private Object closeLock = new Object(); 76 77 /* 78 * The implementation of this DatagramSocket. 79 */ 80 DatagramSocketImpl impl; 81 82 /** 83 * Are we using an older DatagramSocketImpl? 84 */ 85 boolean oldImpl = false; 86 87 /* 88 * Connection state: 89 * ST_NOT_CONNECTED = socket not connected 90 * ST_CONNECTED = socket connected 91 * ST_CONNECTED_NO_IMPL = socket connected but not at impl level 92 */ 93 static final int ST_NOT_CONNECTED = 0; 94 static final int ST_CONNECTED = 1; 95 static final int ST_CONNECTED_NO_IMPL = 2; 96 97 int connectState = ST_NOT_CONNECTED; 98 99 /* 100 * Connected address & port 101 */ 102 InetAddress connectedAddress = null; 103 int connectedPort = -1; 104 105 /** 106 * Connects this socket to a remote socket address (IP address + port number). 107 * Binds socket if not already bound. 108 * <p> 109 * @param addr The remote address. 110 * @param port The remote port 111 * @throws SocketException if binding the socket fails. 112 */ 113 private synchronized void connectInternal(InetAddress address, int port) throws SocketException { 114 if (port < 0 || port > 0xFFFF) { 115 throw new IllegalArgumentException("connect: " + port); 116 } 117 if (address == null) { 118 throw new IllegalArgumentException("connect: null address"); 119 } 120 checkAddress (address, "connect"); 121 if (isClosed()) 122 return; 123 SecurityManager security = System.getSecurityManager(); 124 if (security != null) { 125 if (address.isMulticastAddress()) { 126 security.checkMulticast(address); 127 } else { 128 security.checkConnect(address.getHostAddress(), port); 129 security.checkAccept(address.getHostAddress(), port); 130 } 131 } 132 133 if (!isBound()) 134 bind(new InetSocketAddress(0)); 135 136 // old impls do not support connect/disconnect 137 if (oldImpl) { 138 connectState = ST_CONNECTED_NO_IMPL; 139 } else { 140 try { 141 getImpl().connect(address, port); 142 143 // socket is now connected by the impl 144 connectState = ST_CONNECTED; 145 } catch (SocketException se) { 146 147 // connection will be emulated by DatagramSocket 148 connectState = ST_CONNECTED_NO_IMPL; 149 } 150 } 151 152 connectedAddress = address; 153 connectedPort = port; 154 } 155 156 157 /** 158 * Constructs a datagram socket and binds it to any available port 159 * on the local host machine. The socket will be bound to the 160 * {@link InetAddress#isAnyLocalAddress wildcard} address, 161 * an IP address chosen by the kernel. 162 * 163 * <p>If there is a security manager, 164 * its <code>checkListen</code> method is first called 165 * with 0 as its argument to ensure the operation is allowed. 166 * This could result in a SecurityException. 167 * 168 * @exception SocketException if the socket could not be opened, 169 * or the socket could not bind to the specified local port. 170 * @exception SecurityException if a security manager exists and its 171 * <code>checkListen</code> method doesn't allow the operation. 172 * 173 * @see SecurityManager#checkListen 174 */ 175 public DatagramSocket() throws SocketException { 176 // create a datagram socket. 177 createImpl(); 178 try { 179 bind(new InetSocketAddress(0)); 180 } catch (SocketException se) { 181 throw se; 182 } catch(IOException e) { 183 throw new SocketException(e.getMessage()); 184 } 185 } 186 187 /** 188 * Creates an unbound datagram socket with the specified 189 * DatagramSocketImpl. 190 * 191 * @param impl an instance of a <B>DatagramSocketImpl</B> 192 * the subclass wishes to use on the DatagramSocket. 193 * @since 1.4 194 */ 195 protected DatagramSocket(DatagramSocketImpl impl) { 196 if (impl == null) 197 throw new NullPointerException(); 198 this.impl = impl; 199 checkOldImpl(); 200 } 201 202 /** 203 * Creates a datagram socket, bound to the specified local 204 * socket address. 205 * <p> 206 * If, if the address is <code>null</code>, creates an unbound socket. 207 * <p> 208 * <p>If there is a security manager, 209 * its <code>checkListen</code> method is first called 210 * with the port from the socket address 211 * as its argument to ensure the operation is allowed. 212 * This could result in a SecurityException. 213 * 214 * @param bindaddr local socket address to bind, or <code>null</code> 215 * for an unbound socket. 216 * 217 * @exception SocketException if the socket could not be opened, 218 * or the socket could not bind to the specified local port. 219 * @exception SecurityException if a security manager exists and its 220 * <code>checkListen</code> method doesn't allow the operation. 221 * 222 * @see SecurityManager#checkListen 223 * @since 1.4 224 */ 225 public DatagramSocket(SocketAddress bindaddr) throws SocketException { 226 // create a datagram socket. 227 createImpl(); 228 if (bindaddr != null) { 229 bind(bindaddr); 230 } 231 } 232 233 /** 234 * Constructs a datagram socket and binds it to the specified port 235 * on the local host machine. The socket will be bound to the 236 * {@link InetAddress#isAnyLocalAddress wildcard} address, 237 * an IP address chosen by the kernel. 238 * 239 * <p>If there is a security manager, 240 * its <code>checkListen</code> method is first called 241 * with the <code>port</code> argument 242 * as its argument to ensure the operation is allowed. 243 * This could result in a SecurityException. 244 * 245 * @param port port to use. 246 * @exception SocketException if the socket could not be opened, 247 * or the socket could not bind to the specified local port. 248 * @exception SecurityException if a security manager exists and its 249 * <code>checkListen</code> method doesn't allow the operation. 250 * 251 * @see SecurityManager#checkListen 252 */ 253 public DatagramSocket(int port) throws SocketException { 254 this(port, null); 255 } 256 257 /** 258 * Creates a datagram socket, bound to the specified local 259 * address. The local port must be between 0 and 65535 inclusive. 260 * If the IP address is 0.0.0.0, the socket will be bound to the 261 * {@link InetAddress#isAnyLocalAddress wildcard} address, 262 * an IP address chosen by the kernel. 263 * 264 * <p>If there is a security manager, 265 * its <code>checkListen</code> method is first called 266 * with the <code>port</code> argument 267 * as its argument to ensure the operation is allowed. 268 * This could result in a SecurityException. 269 * 270 * @param port local port to use 271 * @param laddr local address to bind 272 * 273 * @exception SocketException if the socket could not be opened, 274 * or the socket could not bind to the specified local port. 275 * @exception SecurityException if a security manager exists and its 276 * <code>checkListen</code> method doesn't allow the operation. 277 * 278 * @see SecurityManager#checkListen 279 * @since JDK1.1 280 */ 281 public DatagramSocket(int port, InetAddress laddr) throws SocketException { 282 this(new InetSocketAddress(laddr, port)); 283 } 284 285 private void checkOldImpl() { 286 if (impl == null) 287 return; 288 // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use 289 // getDeclaredMethod, therefore we need permission to access the member 290 try { 291 AccessController.doPrivileged(new PrivilegedExceptionAction() { 292 public Object run() throws NoSuchMethodException { 293 Class[] cl = new Class[1]; 294 cl[0] = DatagramPacket.class; 295 impl.getClass().getDeclaredMethod("peekData", cl); 296 return null; 297 } 298 }); 299 } catch (java.security.PrivilegedActionException e) { 300 oldImpl = true; 301 } 302 } 303 304 static Class implClass = null; 305 306 void createImpl() throws SocketException { 307 if (impl == null) { 308 if (factory != null) { 309 impl = factory.createDatagramSocketImpl(); 310 checkOldImpl(); 311 } else { 312 boolean isMulticast = (this instanceof MulticastSocket) ? true : false; 313 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast); 314 315 checkOldImpl(); 316 } 317 } 318 // creates a udp socket 319 impl.create(); 320 created = true; 321 } 322 323 /** 324 * Get the <code>DatagramSocketImpl</code> attached to this socket, 325 * creating it if necessary. 326 * 327 * @return the <code>DatagramSocketImpl</code> attached to that 328 * DatagramSocket 329 * @throws SocketException if creation fails. 330 * @since 1.4 331 */ 332 DatagramSocketImpl getImpl() throws SocketException { 333 if (!created) 334 createImpl(); 335 return impl; 336 } 337 338 /** 339 * Binds this DatagramSocket to a specific address & port. 340 * <p> 341 * If the address is <code>null</code>, then the system will pick up 342 * an ephemeral port and a valid local address to bind the socket. 343 *<p> 344 * @param addr The address & port to bind to. 345 * @throws SocketException if any error happens during the bind, or if the 346 * socket is already bound. 347 * @throws SecurityException if a security manager exists and its 348 * <code>checkListen</code> method doesn't allow the operation. 349 * @throws IllegalArgumentException if addr is a SocketAddress subclass 350 * not supported by this socket. 351 * @since 1.4 352 */ 353 public synchronized void bind(SocketAddress addr) throws SocketException { 354 if (isClosed()) 355 throw new SocketException("Socket is closed"); 356 if (isBound()) 357 throw new SocketException("already bound"); 358 if (addr == null) 359 addr = new InetSocketAddress(0); 360 if (!(addr instanceof InetSocketAddress)) 361 throw new IllegalArgumentException("Unsupported address type!"); 362 InetSocketAddress epoint = (InetSocketAddress) addr; 363 if (epoint.isUnresolved()) 364 throw new SocketException("Unresolved address"); 365 InetAddress iaddr = epoint.getAddress(); 366 int port = epoint.getPort(); 367 checkAddress(iaddr, "bind"); 368 SecurityManager sec = System.getSecurityManager(); 369 if (sec != null) { 370 sec.checkListen(port); 371 } 372 try { 373 getImpl().bind(port, iaddr); 374 } catch (SocketException e) { 375 getImpl().close(); 376 throw e; 377 } 378 bound = true; 379 } 380 381 void checkAddress (InetAddress addr, String op) { 382 if (addr == null) { 383 return; 384 } 385 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { 386 throw new IllegalArgumentException(op + ": invalid address type"); 387 } 388 } 389 390 /** 391 * Connects the socket to a remote address for this socket. When a 392 * socket is connected to a remote address, packets may only be 393 * sent to or received from that address. By default a datagram 394 * socket is not connected. 395 * 396 * <p>If the remote destination to which the socket is connected does not 397 * exist, or is otherwise unreachable, and if an ICMP destination unreachable 398 * packet has been received for that address, then a subsequent call to 399 * send or receive may throw a PortUnreachableException. Note, there is no 400 * guarantee that the exception will be thrown. 401 * 402 * <p>A caller's permission to send and receive datagrams to a 403 * given host and port are checked at connect time. When a socket 404 * is connected, receive and send <b>will not 405 * perform any security checks</b> on incoming and outgoing 406 * packets, other than matching the packet's and the socket's 407 * address and port. On a send operation, if the packet's address 408 * is set and the packet's address and the socket's address do not 409 * match, an IllegalArgumentException will be thrown. A socket 410 * connected to a multicast address may only be used to send packets. 411 * 412 * @param address the remote address for the socket 413 * 414 * @param port the remote port for the socket. 415 * 416 * @exception IllegalArgumentException if the address is null, 417 * or the port is out of range. 418 * 419 * @exception SecurityException if the caller is not allowed to 420 * send datagrams to and receive datagrams from the address and port. 421 * 422 * @see #disconnect 423 * @see #send 424 * @see #receive 425 */ 426 public void connect(InetAddress address, int port) { 427 try { 428 connectInternal(address, port); 429 } catch (SocketException se) { 430 throw new Error("connect failed", se); 431 } 432 } 433 434 /** 435 * Connects this socket to a remote socket address (IP address + port number). 436 * <p> 437 * @param addr The remote address. 438 * @throws SocketException if the connect fails 439 * @throws IllegalArgumentException if addr is null or addr is a SocketAddress 440 * subclass not supported by this socket 441 * @since 1.4 442 * @see #connect 443 */ 444 public void connect(SocketAddress addr) throws SocketException { 445 if (addr == null) 446 throw new IllegalArgumentException("Address can't be null"); 447 if (!(addr instanceof InetSocketAddress)) 448 throw new IllegalArgumentException("Unsupported address type"); 449 InetSocketAddress epoint = (InetSocketAddress) addr; 450 if (epoint.isUnresolved()) 451 throw new SocketException("Unresolved address"); 452 connectInternal(epoint.getAddress(), epoint.getPort()); 453 } 454 455 /** 456 * Disconnects the socket. This does nothing if the socket is not 457 * connected. 458 * 459 * @see #connect 460 */ 461 public void disconnect() { 462 synchronized (this) { 463 if (isClosed()) 464 return; 465 if (connectState == ST_CONNECTED) { 466 impl.disconnect (); 467 } 468 connectedAddress = null; 469 connectedPort = -1; 470 connectState = ST_NOT_CONNECTED; 471 } 472 } 473 474 /** 475 * Returns the binding state of the socket. 476 * 477 * @return true if the socket successfully bound to an address 478 * @since 1.4 479 */ 480 public boolean isBound() { 481 return bound; 482 } 483 484 /** 485 * Returns the connection state of the socket. 486 * 487 * @return true if the socket successfully connected to a server 488 * @since 1.4 489 */ 490 public boolean isConnected() { 491 return connectState != ST_NOT_CONNECTED; 492 } 493 494 /** 495 * Returns the address to which this socket is connected. Returns 496 * <code>null</code> if the socket is not connected. 497 * 498 * @return the address to which this socket is connected. 499 */ 500 public InetAddress getInetAddress() { 501 return connectedAddress; 502 } 503 504 /** 505 * Returns the port number to which this socket is connected. 506 * Returns <code>-1</code> if the socket is not connected. 507 * 508 * @return the port number to which this socket is connected. 509 */ 510 public int getPort() { 511 return connectedPort; 512 } 513 514 /** 515 * Returns the address of the endpoint this socket is connected to, or 516 * <code>null</code> if it is unconnected. 517 * 518 * @return a <code>SocketAddress</code> representing the remote 519 * endpoint of this socket, or <code>null</code> if it is 520 * not connected yet. 521 * @see #getInetAddress() 522 * @see #getPort() 523 * @see #connect(SocketAddress) 524 * @since 1.4 525 */ 526 public SocketAddress getRemoteSocketAddress() { 527 if (!isConnected()) 528 return null; 529 return new InetSocketAddress(getInetAddress(), getPort()); 530 } 531 532 /** 533 * Returns the address of the endpoint this socket is bound to, or 534 * <code>null</code> if it is not bound yet. 535 * 536 * @return a <code>SocketAddress</code> representing the local endpoint of this 537 * socket, or <code>null</code> if it is not bound yet. 538 * @see #getLocalAddress() 539 * @see #getLocalPort() 540 * @see #bind(SocketAddress) 541 * @since 1.4 542 */ 543 544 public SocketAddress getLocalSocketAddress() { 545 if (isClosed()) 546 return null; 547 if (!isBound()) 548 return null; 549 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 550 } 551 552 /** 553 * Sends a datagram packet from this socket. The 554 * <code>DatagramPacket</code> includes information indicating the 555 * data to be sent, its length, the IP address of the remote host, 556 * and the port number on the remote host. 557 * 558 * <p>If there is a security manager, and the socket is not currently 559 * connected to a remote address, this method first performs some 560 * security checks. First, if <code>p.getAddress().isMulticastAddress()</code> 561 * is true, this method calls the 562 * security manager's <code>checkMulticast</code> method 563 * with <code>p.getAddress()</code> as its argument. 564 * If the evaluation of that expression is false, 565 * this method instead calls the security manager's 566 * <code>checkConnect</code> method with arguments 567 * <code>p.getAddress().getHostAddress()</code> and 568 * <code>p.getPort()</code>. Each call to a security manager method 569 * could result in a SecurityException if the operation is not allowed. 570 * 571 * @param p the <code>DatagramPacket</code> to be sent. 572 * 573 * @exception IOException if an I/O error occurs. 574 * @exception SecurityException if a security manager exists and its 575 * <code>checkMulticast</code> or <code>checkConnect</code> 576 * method doesn't allow the send. 577 * @exception PortUnreachableException may be thrown if the socket is connected 578 * to a currently unreachable destination. Note, there is no 579 * guarantee that the exception will be thrown. 580 * @exception java.nio.channels.IllegalBlockingModeException 581 * if this socket has an associated channel, 582 * and the channel is in non-blocking mode. 583 * 584 * @see java.net.DatagramPacket 585 * @see SecurityManager#checkMulticast(InetAddress) 586 * @see SecurityManager#checkConnect 587 * @revised 1.4 588 * @spec JSR-51 589 */ 590 public void send(DatagramPacket p) throws IOException { 591 InetAddress packetAddress = null; 592 synchronized (p) { 593 if (isClosed()) 594 throw new SocketException("Socket is closed"); 595 checkAddress (p.getAddress(), "send"); 596 if (connectState == ST_NOT_CONNECTED) { 597 // check the address is ok wiht the security manager on every send. 598 SecurityManager security = System.getSecurityManager(); 599 600 // The reason you want to synchronize on datagram packet 601 // is because you dont want an applet to change the address 602 // while you are trying to send the packet for example 603 // after the security check but before the send. 604 if (security != null) { 605 if (p.getAddress().isMulticastAddress()) { 606 security.checkMulticast(p.getAddress()); 607 } else { 608 security.checkConnect(p.getAddress().getHostAddress(), 609 p.getPort()); 610 } 611 } 612 } else { 613 // we're connected 614 packetAddress = p.getAddress(); 615 if (packetAddress == null) { 616 p.setAddress(connectedAddress); 617 p.setPort(connectedPort); 618 } else if ((!packetAddress.equals(connectedAddress)) || 619 p.getPort() != connectedPort) { 620 throw new IllegalArgumentException("connected address " + 621 "and packet address" + 622 " differ"); 623 } 624 } 625 // Check whether the socket is bound 626 if (!isBound()) 627 bind(new InetSocketAddress(0)); 628 // call the method to send 629 getImpl().send(p); 630 } 631 } 632 633 /** 634 * Receives a datagram packet from this socket. When this method 635 * returns, the <code>DatagramPacket</code>'s buffer is filled with 636 * the data received. The datagram packet also contains the sender's 637 * IP address, and the port number on the sender's machine. 638 * <p> 639 * This method blocks until a datagram is received. The 640 * <code>length</code> field of the datagram packet object contains 641 * the length of the received message. If the message is longer than 642 * the packet's length, the message is truncated. 643 * <p> 644 * If there is a security manager, a packet cannot be received if the 645 * security manager's <code>checkAccept</code> method 646 * does not allow it. 647 * 648 * @param p the <code>DatagramPacket</code> into which to place 649 * the incoming data. 650 * @exception IOException if an I/O error occurs. 651 * @exception SocketTimeoutException if setSoTimeout was previously called 652 * and the timeout has expired. 653 * @exception PortUnreachableException may be thrown if the socket is connected 654 * to a currently unreachable destination. Note, there is no guarantee that the 655 * exception will be thrown. 656 * @exception java.nio.channels.IllegalBlockingModeException 657 * if this socket has an associated channel, 658 * and the channel is in non-blocking mode. 659 * @see java.net.DatagramPacket 660 * @see java.net.DatagramSocket 661 * @revised 1.4 662 * @spec JSR-51 663 */ 664 public synchronized void receive(DatagramPacket p) throws IOException { 665 synchronized (p) { 666 if (!isBound()) 667 bind(new InetSocketAddress(0)); 668 if (connectState == ST_NOT_CONNECTED) { 669 // check the address is ok with the security manager before every recv. 670 SecurityManager security = System.getSecurityManager(); 671 if (security != null) { 672 while(true) { 673 String peekAd = null; 674 int peekPort = 0; 675 // peek at the packet to see who it is from. 676 if (!oldImpl) { 677 // We can use the new peekData() API 678 DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1); 679 peekPort = getImpl().peekData(peekPacket); 680 peekAd = peekPacket.getAddress().getHostAddress(); 681 } else { 682 InetAddress adr = new InetAddress(); 683 peekPort = getImpl().peek(adr); 684 peekAd = adr.getHostAddress(); 685 } 686 try { 687 security.checkAccept(peekAd, peekPort); 688 // security check succeeded - so now break 689 // and recv the packet. 690 break; 691 } catch (SecurityException se) { 692 // Throw away the offending packet by consuming 693 // it in a tmp buffer. 694 DatagramPacket tmp = new DatagramPacket(new byte[1], 1); 695 getImpl().receive(tmp); 696 697 // silently discard the offending packet 698 // and continue: unknown/malicious 699 // entities on nets should not make 700 // runtime throw security exception and 701 // disrupt the applet by sending random 702 // datagram packets. 703 continue; 704 } 705 } // end of while 706 } 707 } 708 if (connectState == ST_CONNECTED_NO_IMPL) { 709 // We have to do the filtering the old fashioned way since 710 // the native impl doesn't support connect or the connect 711 // via the impl failed. 712 boolean stop = false; 713 while (!stop) { 714 // peek at the packet to see who it is from. 715 InetAddress peekAddress = new InetAddress(); 716 int peekPort = getImpl().peek(peekAddress); 717 if ((!connectedAddress.equals(peekAddress)) || 718 (connectedPort != peekPort)) { 719 // throw the packet away and silently continue 720 DatagramPacket tmp = new DatagramPacket(new byte[1], 1); 721 getImpl().receive(tmp); 722 } else { 723 stop = true; 724 } 725 } 726 } 727 // If the security check succeeds, or the datagram is 728 // connected then receive the packet 729 getImpl().receive(p); 730 } 731 } 732 733 /** 734 * Gets the local address to which the socket is bound. 735 * 736 * <p>If there is a security manager, its 737 * <code>checkConnect</code> method is first called 738 * with the host address and <code>-1</code> 739 * as its arguments to see if the operation is allowed. 740 * 741 * @see SecurityManager#checkConnect 742 * @return the local address to which the socket is bound, or 743 * an <code>InetAddress</code> representing any local 744 * address if either the socket is not bound, or 745 * the security manager <code>checkConnect</code> 746 * method does not allow the operation 747 * @since 1.1 748 */ 749 public InetAddress getLocalAddress() { 750 if (isClosed()) 751 return null; 752 InetAddress in = null; 753 try { 754 in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 755 if (in.isAnyLocalAddress()) { 756 in = InetAddress.anyLocalAddress(); 757 } 758 SecurityManager s = System.getSecurityManager(); 759 if (s != null) { 760 s.checkConnect(in.getHostAddress(), -1); 761 } 762 } catch (Exception e) { 763 in = InetAddress.anyLocalAddress(); // "0.0.0.0" 764 } 765 return in; 766 } 767 768 /** 769 * Returns the port number on the local host to which this socket 770 * is bound. 771 * 772 * @return the port number on the local host to which this socket is bound. 773 */ 774 public int getLocalPort() { 775 if (isClosed()) 776 return -1; 777 try { 778 return getImpl().getLocalPort(); 779 } catch (Exception e) { 780 return 0; 781 } 782 } 783 784 /** Enable/disable SO_TIMEOUT with the specified timeout, in 785 * milliseconds. With this option set to a non-zero timeout, 786 * a call to receive() for this DatagramSocket 787 * will block for only this amount of time. If the timeout expires, 788 * a <B>java.net.SocketTimeoutException</B> is raised, though the 789 * DatagramSocket is still valid. The option <B>must</B> be enabled 790 * prior to entering the blocking operation to have effect. The 791 * timeout must be > 0. 792 * A timeout of zero is interpreted as an infinite timeout. 793 * 794 * @param timeout the specified timeout in milliseconds. 795 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. 796 * @since JDK1.1 797 * @see #getSoTimeout() 798 */ 799 public synchronized void setSoTimeout(int timeout) throws SocketException { 800 if (isClosed()) 801 throw new SocketException("Socket is closed"); 802 getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); 803 } 804 805 /** 806 * Retrieve setting for SO_TIMEOUT. 0 returns implies that the 807 * option is disabled (i.e., timeout of infinity). 808 * 809 * @return the setting for SO_TIMEOUT 810 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. 811 * @since JDK1.1 812 * @see #setSoTimeout(int) 813 */ 814 public synchronized int getSoTimeout() throws SocketException { 815 if (isClosed()) 816 throw new SocketException("Socket is closed"); 817 if (getImpl() == null) 818 return 0; 819 Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT); 820 /* extra type safety */ 821 if (o instanceof Integer) { 822 return ((Integer) o).intValue(); 823 } else { 824 return 0; 825 } 826 } 827 828 /** 829 * Sets the SO_SNDBUF option to the specified value for this 830 * <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the 831 * network implementation as a hint to size the underlying 832 * network I/O buffers. The SO_SNDBUF setting may also be used 833 * by the network implementation to determine the maximum size 834 * of the packet that can be sent on this socket. 835 * <p> 836 * As SO_SNDBUF is a hint, applications that want to verify 837 * what size the buffer is should call {@link #getSendBufferSize()}. 838 * <p> 839 * Increasing the buffer size may allow multiple outgoing packets 840 * to be queued by the network implementation when the send rate 841 * is high. 842 * <p> 843 * Note: If {@link #send(DatagramPacket)} is used to send a 844 * <code>DatagramPacket</code> that is larger than the setting 845 * of SO_SNDBUF then it is implementation specific if the 846 * packet is sent or discarded. 847 * 848 * @param size the size to which to set the send buffer 849 * size. This value must be greater than 0. 850 * 851 * @exception SocketException if there is an error 852 * in the underlying protocol, such as an UDP error. 853 * @exception IllegalArgumentException if the value is 0 or is 854 * negative. 855 * @see #getSendBufferSize() 856 */ 857 public synchronized void setSendBufferSize(int size) 858 throws SocketException{ 859 if (!(size > 0)) { 860 throw new IllegalArgumentException("negative send size"); 861 } 862 if (isClosed()) 863 throw new SocketException("Socket is closed"); 864 getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size)); 865 } 866 867 /** 868 * Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that is the 869 * buffer size used by the platform for output on this <tt>DatagramSocket</tt>. 870 * 871 * @return the value of the SO_SNDBUF option for this <tt>DatagramSocket</tt> 872 * @exception SocketException if there is an error in 873 * the underlying protocol, such as an UDP error. 874 * @see #setSendBufferSize 875 */ 876 public synchronized int getSendBufferSize() throws SocketException { 877 if (isClosed()) 878 throw new SocketException("Socket is closed"); 879 int result = 0; 880 Object o = getImpl().getOption(SocketOptions.SO_SNDBUF); 881 if (o instanceof Integer) { 882 result = ((Integer)o).intValue(); 883 } 884 return result; 885 } 886 887 /** 888 * Sets the SO_RCVBUF option to the specified value for this 889 * <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the 890 * the network implementation as a hint to size the underlying 891 * network I/O buffers. The SO_RCVBUF setting may also be used 892 * by the network implementation to determine the maximum size 893 * of the packet that can be received on this socket. 894 * <p> 895 * Because SO_RCVBUF is a hint, applications that want to 896 * verify what size the buffers were set to should call 897 * {@link #getReceiveBufferSize()}. 898 * <p> 899 * Increasing SO_RCVBUF may allow the network implementation 900 * to buffer multiple packets when packets arrive faster than 901 * are being received using {@link #receive(DatagramPacket)}. 902 * <p> 903 * Note: It is implementation specific if a packet larger 904 * than SO_RCVBUF can be received. 905 * 906 * @param size the size to which to set the receive buffer 907 * size. This value must be greater than 0. 908 * 909 * @exception SocketException if there is an error in 910 * the underlying protocol, such as an UDP error. 911 * @exception IllegalArgumentException if the value is 0 or is 912 * negative. 913 * @see #getReceiveBufferSize() 914 */ 915 public synchronized void setReceiveBufferSize(int size) 916 throws SocketException{ 917 if (size <= 0) { 918 throw new IllegalArgumentException("invalid receive size"); 919 } 920 if (isClosed()) 921 throw new SocketException("Socket is closed"); 922 getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size)); 923 } 924 925 /** 926 * Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that is the 927 * buffer size used by the platform for input on this <tt>DatagramSocket</tt>. 928 * 929 * @return the value of the SO_RCVBUF option for this <tt>DatagramSocket</tt> 930 * @exception SocketException if there is an error in the underlying protocol, such as an UDP error. 931 * @see #setReceiveBufferSize(int) 932 */ 933 public synchronized int getReceiveBufferSize() 934 throws SocketException{ 935 if (isClosed()) 936 throw new SocketException("Socket is closed"); 937 int result = 0; 938 Object o = getImpl().getOption(SocketOptions.SO_RCVBUF); 939 if (o instanceof Integer) { 940 result = ((Integer)o).intValue(); 941 } 942 return result; 943 } 944 945 /** 946 * Enable/disable the SO_REUSEADDR socket option. 947 * <p> 948 * For UDP sockets it may be necessary to bind more than one 949 * socket to the same socket address. This is typically for the 950 * purpose of receiving multicast packets 951 * (See {@link java.net.MulticastSocket}). The 952 * <tt>SO_REUSEADDR</tt> socket option allows multiple 953 * sockets to be bound to the same socket address if the 954 * <tt>SO_REUSEADDR</tt> socket option is enabled prior 955 * to binding the socket using {@link #bind(SocketAddress)}. 956 * <p> 957 * Note: This functionality is not supported by all existing platforms, 958 * so it is implementation specific whether this option will be ignored 959 * or not. However, if it is not supported then 960 * {@link #getReuseAddress()} will always return <code>false</code>. 961 * <p> 962 * When a <tt>DatagramSocket</tt> is created the initial setting 963 * of <tt>SO_REUSEADDR</tt> is disabled. 964 * <p> 965 * The behaviour when <tt>SO_REUSEADDR</tt> is enabled or 966 * disabled after a socket is bound (See {@link #isBound()}) 967 * is not defined. 968 * 969 * @param on whether to enable or disable the 970 * @exception SocketException if an error occurs enabling or 971 * disabling the <tt>SO_RESUEADDR</tt> socket option, 972 * or the socket is closed. 973 * @since 1.4 974 * @see #getReuseAddress() 975 * @see #bind(SocketAddress) 976 * @see #isBound() 977 * @see #isClosed() 978 */ 979 public synchronized void setReuseAddress(boolean on) throws SocketException { 980 if (isClosed()) 981 throw new SocketException("Socket is closed"); 982 // Integer instead of Boolean for compatibility with older DatagramSocketImpl 983 if (oldImpl) 984 getImpl().setOption(SocketOptions.SO_REUSEADDR, new Integer(on?-1:0)); 985 else 986 getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); 987 } 988 989 /** 990 * Tests if SO_REUSEADDR is enabled. 991 * 992 * @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is enabled. 993 * @exception SocketException if there is an error 994 * in the underlying protocol, such as an UDP error. 995 * @since 1.4 996 * @see #setReuseAddress(boolean) 997 */ 998 public synchronized boolean getReuseAddress() throws SocketException { 999 if (isClosed()) 1000 throw new SocketException("Socket is closed"); 1001 Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR); 1002 return ((Boolean)o).booleanValue(); 1003 } 1004 1005 /** 1006 * Enable/disable SO_BROADCAST. 1007 * @param on whether or not to have broadcast turned on. 1008 * @exception SocketException if there is an error 1009 * in the underlying protocol, such as an UDP error. 1010 * @since 1.4 1011 * @see #getBroadcast() 1012 */ 1013 public synchronized void setBroadcast(boolean on) throws SocketException { 1014 if (isClosed()) 1015 throw new SocketException("Socket is closed"); 1016 getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on)); 1017 } 1018 1019 /** 1020 * Tests if SO_BROADCAST is enabled. 1021 * @return a <code>boolean</code> indicating whether or not SO_BROADCAST is enabled. 1022 * @exception SocketException if there is an error 1023 * in the underlying protocol, such as an UDP error. 1024 * @since 1.4 1025 * @see #setBroadcast(boolean) 1026 */ 1027 public synchronized boolean getBroadcast() throws SocketException { 1028 if (isClosed()) 1029 throw new SocketException("Socket is closed"); 1030 return ((Boolean)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue(); 1031 } 1032 1033 /** 1034 * Sets traffic class or type-of-service octet in the IP 1035 * datagram header for datagrams sent from this DatagramSocket. 1036 * As the underlying network implementation may ignore this 1037 * value applications should consider it a hint. 1038 * 1039 * <P> The tc <B>must</B> be in the range <code> 0 <= tc <= 1040 * 255</code> or an IllegalArgumentException will be thrown. 1041 * <p>Notes: 1042 * <p> for Internet Protocol v4 the value consists of an octet 1043 * with precedence and TOS fields as detailed in RFC 1349. The 1044 * TOS field is bitset created by bitwise-or'ing values such 1045 * the following :- 1046 * <p> 1047 * <UL> 1048 * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI> 1049 * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI> 1050 * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI> 1051 * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI> 1052 * </UL> 1053 * The last low order bit is always ignored as this 1054 * corresponds to the MBZ (must be zero) bit. 1055 * <p> 1056 * Setting bits in the precedence field may result in a 1057 * SocketException indicating that the operation is not 1058 * permitted. 1059 * <p> 1060 * for Internet Protocol v6 <code>tc</code> is the value that 1061 * would be placed into the sin6_flowinfo field of the IP header. 1062 * 1063 * @param tc an <code>int</code> value for the bitset. 1064 * @throws SocketException if there is an error setting the 1065 * traffic class or type-of-service 1066 * @since 1.4 1067 * @see #getTrafficClass 1068 */ 1069 public synchronized void setTrafficClass(int tc) throws SocketException { 1070 if (tc < 0 || tc > 255) 1071 throw new IllegalArgumentException("tc is not in range 0 -- 255"); 1072 1073 if (isClosed()) 1074 throw new SocketException("Socket is closed"); 1075 getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); 1076 } 1077 1078 /** 1079 * Gets traffic class or type-of-service in the IP datagram 1080 * header for packets sent from this DatagramSocket. 1081 * <p> 1082 * As the underlying network implementation may ignore the 1083 * traffic class or type-of-service set using {@link #setTrafficClass(int)} 1084 * this method may return a different value than was previously 1085 * set using the {@link #setTrafficClass(int)} method on this 1086 * DatagramSocket. 1087 * 1088 * @return the traffic class or type-of-service already set 1089 * @throws SocketException if there is an error obtaining the 1090 * traffic class or type-of-service value. 1091 * @since 1.4 1092 * @see #setTrafficClass(int) 1093 */ 1094 public synchronized int getTrafficClass() throws SocketException { 1095 if (isClosed()) 1096 throw new SocketException("Socket is closed"); 1097 return ((Integer)(getImpl().getOption(SocketOptions.IP_TOS))).intValue(); 1098 } 1099 1100 /** 1101 * Closes this datagram socket. 1102 * <p> 1103 * Any thread currently blocked in {@link #receive} upon this socket 1104 * will throw a {@link SocketException}. 1105 * 1106 * <p> If this socket has an associated channel then the channel is closed 1107 * as well. 1108 * 1109 * @revised 1.4 1110 * @spec JSR-51 1111 */ 1112 public void close() { 1113 synchronized(closeLock) { 1114 if (isClosed()) 1115 return; 1116 impl.close(); 1117 closed = true; 1118 } 1119 } 1120 1121 /** 1122 * Returns whether the socket is closed or not. 1123 * 1124 * @return true if the socket has been closed 1125 * @since 1.4 1126 */ 1127 public boolean isClosed() { 1128 synchronized(closeLock) { 1129 return closed; 1130 } 1131 } 1132 1133 /** 1134 * Returns the unique {@link java.nio.channels.DatagramChannel} object 1135 * associated with this datagram socket, if any. 1136 * 1137 * <p> A datagram socket will have a channel if, and only if, the channel 1138 * itself was created via the {@link java.nio.channels.DatagramChannel#open 1139 * DatagramChannel.open} method. 1140 * 1141 * @return the datagram channel associated with this datagram socket, 1142 * or <tt>null</tt> if this socket was not created for a channel 1143 * 1144 * @since 1.4 1145 * @spec JSR-51 1146 */ 1147 public DatagramChannel getChannel() { 1148 return null; 1149 } 1150 1151 /** 1152 * User defined factory for all datagram sockets. 1153 */ 1154 static DatagramSocketImplFactory factory; 1155 1156 /** 1157 * Sets the datagram socket implementation factory for the 1158 * application. The factory can be specified only once. 1159 * <p> 1160 * When an application creates a new datagram socket, the socket 1161 * implementation factory's <code>createDatagramSocketImpl</code> method is 1162 * called to create the actual datagram socket implementation. 1163 * <p> 1164 * Passing <code>null</code> to the method is a no-op unless the factory 1165 * was already set. 1166 * 1167 * <p>If there is a security manager, this method first calls 1168 * the security manager's <code>checkSetFactory</code> method 1169 * to ensure the operation is allowed. 1170 * This could result in a SecurityException. 1171 * 1172 * @param fac the desired factory. 1173 * @exception IOException if an I/O error occurs when setting the 1174 * datagram socket factory. 1175 * @exception SocketException if the factory is already defined. 1176 * @exception SecurityException if a security manager exists and its 1177 * <code>checkSetFactory</code> method doesn't allow the 1178 operation. 1179 * @see 1180 java.net.DatagramSocketImplFactory#createDatagramSocketImpl() 1181 * @see SecurityManager#checkSetFactory 1182 * @since 1.3 1183 */ 1184 public static synchronized void 1185 setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 1186 throws IOException 1187 { 1188 if (factory != null) { 1189 throw new SocketException("factory already defined"); 1190 } 1191 SecurityManager security = System.getSecurityManager(); 1192 if (security != null) { 1193 security.checkSetFactory(); 1194 } 1195 factory = fac; 1196 } 1197}