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