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