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