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