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