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 java.io.FileDescriptor;
30 import java.io.IOException;
31 import java.nio.channels.DatagramChannel;
32 import java.security.AccessController;
33 import java.security.PrivilegedExceptionAction;
34 import android.system.ErrnoException;
35 import libcore.io.Libcore;
36 import static android.system.OsConstants.*;
37 
38 /**
39  * This class represents a socket for sending and receiving datagram packets.
40  *
41  * <p>A datagram socket is the sending or receiving point for a packet
42  * delivery service. Each packet sent or received on a datagram socket
43  * is individually addressed and routed. Multiple packets sent from
44  * one machine to another may be routed differently, and may arrive in
45  * any order.
46  *
47  * <p> Where possible, a newly constructed {@code DatagramSocket} has the
48  * {@link SocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
49  * to allow the transmission of broadcast datagrams. In order to receive
50  * broadcast packets a DatagramSocket should be bound to the wildcard address.
51  * In some implementations, broadcast packets may also be received when
52  * a DatagramSocket is bound to a more specific address.
53  * <p>
54  * Example:
55  * {@code
56  *              DatagramSocket s = new DatagramSocket(null);
57  *              s.bind(new InetSocketAddress(8888));
58  * }
59  * Which is equivalent to:
60  * {@code
61  *              DatagramSocket s = new DatagramSocket(8888);
62  * }
63  * Both cases will create a DatagramSocket able to receive broadcasts on
64  * UDP port 8888.
65  *
66  * @author  Pavani Diwanji
67  * @see     java.net.DatagramPacket
68  * @see     java.nio.channels.DatagramChannel
69  * @since JDK1.0
70  */
71 public
72 class DatagramSocket implements java.io.Closeable {
73     /**
74      * Various states of this socket.
75      */
76     private boolean created = false;
77     private boolean bound = false;
78     private boolean closed = false;
79     private Object closeLock = new Object();
80 
81     /*
82      * The implementation of this DatagramSocket.
83      */
84     DatagramSocketImpl impl;
85 
86     /**
87      * Are we using an older DatagramSocketImpl?
88      */
89     boolean oldImpl = false;
90 
91     /**
92      * Set when a socket is ST_CONNECTED until we are certain
93      * that any packets which might have been received prior
94      * to calling connect() but not read by the application
95      * have been read. During this time we check the source
96      * address of all packets received to be sure they are from
97      * the connected destination. Other packets are read but
98      * silently dropped.
99      */
100     private boolean explicitFilter = false;
101     private int bytesLeftToFilter;
102     /*
103      * Connection state:
104      * ST_NOT_CONNECTED = socket not connected
105      * ST_CONNECTED = socket connected
106      * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
107      */
108     static final int ST_NOT_CONNECTED = 0;
109     static final int ST_CONNECTED = 1;
110     static final int ST_CONNECTED_NO_IMPL = 2;
111 
112     int connectState = ST_NOT_CONNECTED;
113 
114     /*
115      * Connected address & port
116      */
117     InetAddress connectedAddress = null;
118     int connectedPort = -1;
119 
120     // BEGIN Android-changed
121     private SocketException pendingConnectException;
122     // END Android-changed
123 
124     /**
125      * Connects this socket to a remote socket address (IP address + port number).
126      * Binds socket if not already bound.
127      * <p>
128      * @param   address The remote address.
129      * @param   port    The remote port
130      * @throws  SocketException if binding the socket fails.
131      */
connectInternal(InetAddress address, int port)132     private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
133         if (port < 0 || port > 0xFFFF) {
134             throw new IllegalArgumentException("connect: " + port);
135         }
136         if (address == null) {
137             throw new IllegalArgumentException("connect: null address");
138         }
139         checkAddress (address, "connect");
140         if (isClosed())
141             return;
142         SecurityManager security = System.getSecurityManager();
143         if (security != null) {
144             if (address.isMulticastAddress()) {
145                 security.checkMulticast(address);
146             } else {
147                 security.checkConnect(address.getHostAddress(), port);
148                 security.checkAccept(address.getHostAddress(), port);
149             }
150         }
151 
152         if (!isBound())
153           bind(new InetSocketAddress(0));
154 
155         // Android-changed: This section now throws any SocketException generated by connect()
156         // to enable it to be recorded as the pendingConnectException. It has been enclosed in a
157         // try-finally to ensure connectedAddress and connectedPort are set when the exception
158         // is thrown.
159         try {
160             // old impls do not support connect/disconnect
161             // Android-changed: Added special handling for AbstractPlainDatagramSocketImpl in
162             // the condition below.
163             if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
164                     ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
165                 connectState = ST_CONNECTED_NO_IMPL;
166             } else {
167                 try {
168                     getImpl().connect(address, port);
169 
170                     // socket is now connected by the impl
171                     connectState = ST_CONNECTED;
172 
173                     // Do we need to filter some packets?
174                     int avail = getImpl().dataAvailable();
175                     if (avail == -1) {
176                         throw new SocketException();
177                     }
178                     explicitFilter = avail > 0;
179                     if (explicitFilter) {
180                         bytesLeftToFilter = getReceiveBufferSize();
181                     }
182                 } catch (SocketException se) {
183                     // connection will be emulated by DatagramSocket
184                     connectState = ST_CONNECTED_NO_IMPL;
185                     // Android-changed: Propagate the SocketException so connect() can store it.
186                     throw se;
187                 }
188            }
189         } finally {
190             connectedAddress = address;
191             connectedPort = port;
192         }
193     }
194 
195 
196     /**
197      * Constructs a datagram socket and binds it to any available port
198      * on the local host machine.  The socket will be bound to the
199      * {@link InetAddress#isAnyLocalAddress wildcard} address,
200      * an IP address chosen by the kernel.
201      *
202      * <p>If there is a security manager,
203      * its {@code checkListen} method is first called
204      * with 0 as its argument to ensure the operation is allowed.
205      * This could result in a SecurityException.
206      *
207      * @exception  SocketException  if the socket could not be opened,
208      *               or the socket could not bind to the specified local port.
209      * @exception  SecurityException  if a security manager exists and its
210      *             {@code checkListen} method doesn't allow the operation.
211      *
212      * @see SecurityManager#checkListen
213      */
DatagramSocket()214     public DatagramSocket() throws SocketException {
215         this(new InetSocketAddress(0));
216     }
217 
218     /**
219      * Creates an unbound datagram socket with the specified
220      * DatagramSocketImpl.
221      *
222      * @param impl an instance of a <B>DatagramSocketImpl</B>
223      *        the subclass wishes to use on the DatagramSocket.
224      * @since   1.4
225      */
DatagramSocket(DatagramSocketImpl impl)226     protected DatagramSocket(DatagramSocketImpl impl) {
227         if (impl == null)
228             throw new NullPointerException();
229         this.impl = impl;
230         checkOldImpl();
231     }
232 
233     /**
234      * Creates a datagram socket, bound to the specified local
235      * socket address.
236      * <p>
237      * If, if the address is {@code null}, creates an unbound socket.
238      *
239      * <p>If there is a security manager,
240      * its {@code checkListen} method is first called
241      * with the port from the socket address
242      * as its argument to ensure the operation is allowed.
243      * This could result in a SecurityException.
244      *
245      * @param bindaddr local socket address to bind, or {@code null}
246      *                 for an unbound socket.
247      *
248      * @exception  SocketException  if the socket could not be opened,
249      *               or the socket could not bind to the specified local port.
250      * @exception  SecurityException  if a security manager exists and its
251      *             {@code checkListen} method doesn't allow the operation.
252      *
253      * @see SecurityManager#checkListen
254      * @since   1.4
255      */
DatagramSocket(SocketAddress bindaddr)256     public DatagramSocket(SocketAddress bindaddr) throws SocketException {
257         // create a datagram socket.
258         createImpl();
259         if (bindaddr != null) {
260             try {
261                 bind(bindaddr);
262             } finally {
263                 if (!isBound())
264                     close();
265             }
266         }
267     }
268 
269     /**
270      * Constructs a datagram socket and binds it to the specified port
271      * on the local host machine.  The socket will be bound to the
272      * {@link InetAddress#isAnyLocalAddress wildcard} address,
273      * an IP address chosen by the kernel.
274      *
275      * <p>If there is a security manager,
276      * its {@code checkListen} method is first called
277      * with the {@code port} argument
278      * as its argument to ensure the operation is allowed.
279      * This could result in a SecurityException.
280      *
281      * @param      port port to use.
282      * @exception  SocketException  if the socket could not be opened,
283      *               or the socket could not bind to the specified local port.
284      * @exception  SecurityException  if a security manager exists and its
285      *             {@code checkListen} method doesn't allow the operation.
286      *
287      * @see SecurityManager#checkListen
288      */
DatagramSocket(int port)289     public DatagramSocket(int port) throws SocketException {
290         this(port, null);
291     }
292 
293     /**
294      * Creates a datagram socket, bound to the specified local
295      * address.  The local port must be between 0 and 65535 inclusive.
296      * If the IP address is 0.0.0.0, the socket will be bound to the
297      * {@link InetAddress#isAnyLocalAddress wildcard} address,
298      * an IP address chosen by the kernel.
299      *
300      * <p>If there is a security manager,
301      * its {@code checkListen} method is first called
302      * with the {@code port} argument
303      * as its argument to ensure the operation is allowed.
304      * This could result in a SecurityException.
305      *
306      * @param port local port to use
307      * @param laddr local address to bind
308      *
309      * @exception  SocketException  if the socket could not be opened,
310      *               or the socket could not bind to the specified local port.
311      * @exception  SecurityException  if a security manager exists and its
312      *             {@code checkListen} method doesn't allow the operation.
313      *
314      * @see SecurityManager#checkListen
315      * @since   JDK1.1
316      */
DatagramSocket(int port, InetAddress laddr)317     public DatagramSocket(int port, InetAddress laddr) throws SocketException {
318         this(new InetSocketAddress(laddr, port));
319     }
320 
checkOldImpl()321     private void checkOldImpl() {
322         if (impl == null)
323             return;
324         // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
325         // getDeclaredMethod, therefore we need permission to access the member
326         try {
327             AccessController.doPrivileged(
328                 new PrivilegedExceptionAction<Void>() {
329                     public Void run() throws NoSuchMethodException {
330                         Class<?>[] cl = new Class<?>[1];
331                         cl[0] = DatagramPacket.class;
332                         impl.getClass().getDeclaredMethod("peekData", cl);
333                         return null;
334                     }
335                 });
336         } catch (java.security.PrivilegedActionException e) {
337             oldImpl = true;
338         }
339     }
340 
341     static Class<?> implClass = null;
342 
createImpl()343     void createImpl() throws SocketException {
344         if (impl == null) {
345             if (factory != null) {
346                 impl = factory.createDatagramSocketImpl();
347                 checkOldImpl();
348             } else {
349                 boolean isMulticast = (this instanceof MulticastSocket) ? true : false;
350                 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast);
351 
352                 checkOldImpl();
353             }
354         }
355         // creates a udp socket
356         impl.create();
357         impl.setDatagramSocket(this);
358         created = true;
359     }
360 
361     /**
362      * Get the {@code DatagramSocketImpl} attached to this socket,
363      * creating it if necessary.
364      *
365      * @return  the {@code DatagramSocketImpl} attached to that
366      *          DatagramSocket
367      * @throws SocketException if creation fails.
368      * @since 1.4
369      */
getImpl()370     DatagramSocketImpl getImpl() throws SocketException {
371         if (!created)
372             createImpl();
373         return impl;
374     }
375 
376     /**
377      * Binds this DatagramSocket to a specific address and port.
378      * <p>
379      * If the address is {@code null}, then the system will pick up
380      * an ephemeral port and a valid local address to bind the socket.
381      *<p>
382      * @param   addr The address and port to bind to.
383      * @throws  SocketException if any error happens during the bind, or if the
384      *          socket is already bound.
385      * @throws  SecurityException  if a security manager exists and its
386      *             {@code checkListen} method doesn't allow the operation.
387      * @throws IllegalArgumentException if addr is a SocketAddress subclass
388      *         not supported by this socket.
389      * @since 1.4
390      */
bind(SocketAddress addr)391     public synchronized void bind(SocketAddress addr) throws SocketException {
392         if (isClosed())
393             throw new SocketException("Socket is closed");
394         if (isBound())
395             throw new SocketException("already bound");
396         if (addr == null)
397             addr = new InetSocketAddress(0);
398         if (!(addr instanceof InetSocketAddress))
399             throw new IllegalArgumentException("Unsupported address type!");
400         InetSocketAddress epoint = (InetSocketAddress) addr;
401         if (epoint.isUnresolved())
402             throw new SocketException("Unresolved address");
403         InetAddress iaddr = epoint.getAddress();
404         int port = epoint.getPort();
405         checkAddress(iaddr, "bind");
406         SecurityManager sec = System.getSecurityManager();
407         if (sec != null) {
408             sec.checkListen(port);
409         }
410         try {
411             getImpl().bind(port, iaddr);
412         } catch (SocketException e) {
413             getImpl().close();
414             throw e;
415         }
416         bound = true;
417     }
418 
checkAddress(InetAddress addr, String op)419     void checkAddress (InetAddress addr, String op) {
420         if (addr == null) {
421             return;
422         }
423         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
424             throw new IllegalArgumentException(op + ": invalid address type");
425         }
426     }
427 
428     /**
429      * Connects the socket to a remote address for this socket. When a
430      * socket is connected to a remote address, packets may only be
431      * sent to or received from that address. By default a datagram
432      * socket is not connected.
433      *
434      * <p>If the remote destination to which the socket is connected does not
435      * exist, or is otherwise unreachable, and if an ICMP destination unreachable
436      * packet has been received for that address, then a subsequent call to
437      * send or receive may throw a PortUnreachableException. Note, there is no
438      * guarantee that the exception will be thrown.
439      *
440      * <p> If a security manager has been installed then it is invoked to check
441      * access to the remote address. Specifically, if the given {@code address}
442      * is a {@link InetAddress#isMulticastAddress multicast address},
443      * the security manager's {@link
444      * java.lang.SecurityManager#checkMulticast(InetAddress)
445      * checkMulticast} method is invoked with the given {@code address}.
446      * Otherwise, the security manager's {@link
447      * java.lang.SecurityManager#checkConnect(String,int) checkConnect}
448      * and {@link java.lang.SecurityManager#checkAccept checkAccept} methods
449      * are invoked, with the given {@code address} and {@code port}, to
450      * verify that datagrams are permitted to be sent and received
451      * respectively.
452      *
453      * <p> When a socket is connected, {@link #receive receive} and
454      * {@link #send send} <b>will not perform any security checks</b>
455      * on incoming and outgoing packets, other than matching the packet's
456      * and the socket's address and port. On a send operation, if the
457      * packet's address is set and the packet's address and the socket's
458      * address do not match, an {@code IllegalArgumentException} will be
459      * thrown. A socket connected to a multicast address may only be used
460      * to send packets.
461      *
462      * @param address the remote address for the socket
463      *
464      * @param port the remote port for the socket.
465      *
466      * @throws IllegalArgumentException
467      *         if the address is null, or the port is out of range.
468      *
469      * @throws SecurityException
470      *         if a security manager has been installed and it does
471      *         not permit access to the given remote address
472      *
473      * @see #disconnect
474      */
connect(InetAddress address, int port)475     public void connect(InetAddress address, int port) {
476         try {
477             connectInternal(address, port);
478         } catch (SocketException se) {
479             // BEGIN Android-changed
480             //throw new Error("connect failed", se);
481             // TODO: or just use SneakyThrow? There's a clear API bug here.
482             pendingConnectException = se;
483             // END Android-changed
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      */
connect(SocketAddress addr)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      */
disconnect()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      */
isBound()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      */
isConnected()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      */
getInetAddress()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      */
getPort()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      */
getRemoteSocketAddress()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 
getLocalSocketAddress()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      */
send(DatagramPacket p)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      */
receive(DatagramPacket p)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 
checkFiltering(DatagramPacket p)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      */
getLocalAddress()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      */
getLocalPort()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      */
setSoTimeout(int timeout)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      */
getSoTimeout()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      */
setSendBufferSize(int size)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      */
getSendBufferSize()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      */
setReceiveBufferSize(int size)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      */
getReceiveBufferSize()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      */
setReuseAddress(boolean on)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      */
getReuseAddress()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      */
setBroadcast(boolean on)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      */
getBroadcast()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      */
setTrafficClass(int tc)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      */
getTrafficClass()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      */
close()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      */
isClosed()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      */
getChannel()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
setDatagramSocketImplFactory(DatagramSocketImplFactory fac)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     /**
1351      * Android-added: for testing and internal use.
1352      *
1353      * @hide internal use only
1354      */
getFileDescriptor$()1355     public FileDescriptor getFileDescriptor$() {
1356         return impl.fd;
1357     }
1358 
1359     /**
1360      * Android-added:
1361      * Sets the network interface used by this socket.  Any packets sent
1362      * via this socket are transmitted via the specified interface.  Any
1363      * packets received by this socket will come from the specified
1364      * interface.  Broadcast datagrams received on this interface will
1365      * be processed by this socket. This corresponds to Linux's SO_BINDTODEVICE.
1366      *
1367      * @hide used by GoogleTV for DHCP
1368      */
setNetworkInterface(NetworkInterface netInterface)1369     public void setNetworkInterface(NetworkInterface netInterface) throws SocketException {
1370         if (netInterface == null) {
1371             throw new NullPointerException("netInterface == null");
1372         }
1373         try {
1374             Libcore.os.setsockoptIfreq(impl.fd, SOL_SOCKET, SO_BINDTODEVICE, netInterface.getName());
1375         } catch (ErrnoException errnoException) {
1376             throw errnoException.rethrowAsSocketException();
1377         }
1378     }
1379 }
1380