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