| /* | 
 |  * Copyright (C) 2014 The Android Open Source Project | 
 |  * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. | 
 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
 |  * | 
 |  * This code is free software; you can redistribute it and/or modify it | 
 |  * under the terms of the GNU General Public License version 2 only, as | 
 |  * published by the Free Software Foundation.  Oracle designates this | 
 |  * particular file as subject to the "Classpath" exception as provided | 
 |  * by Oracle in the LICENSE file that accompanied this code. | 
 |  * | 
 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
 |  * version 2 for more details (a copy is included in the LICENSE file that | 
 |  * accompanied this code). | 
 |  * | 
 |  * You should have received a copy of the GNU General Public License version | 
 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
 |  * | 
 |  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
 |  * or visit www.oracle.com if you need additional information or have any | 
 |  * questions. | 
 |  */ | 
 |  | 
 | package java.net; | 
 |  | 
 | import java.io.FileDescriptor; | 
 | import java.io.InputStream; | 
 | import java.io.OutputStream; | 
 | import java.io.IOException; | 
 | import java.nio.channels.SocketChannel; | 
 | import java.security.AccessController; | 
 | import java.security.PrivilegedExceptionAction; | 
 | import java.security.PrivilegedAction; | 
 |  | 
 | /** | 
 |  * This class implements client sockets (also called just | 
 |  * "sockets"). A socket is an endpoint for communication | 
 |  * between two machines. | 
 |  * <p> | 
 |  * The actual work of the socket is performed by an instance of the | 
 |  * {@code SocketImpl} class. An application, by changing | 
 |  * the socket factory that creates the socket implementation, | 
 |  * can configure itself to create sockets appropriate to the local | 
 |  * firewall. | 
 |  * | 
 |  * @author  unascribed | 
 |  * @see     java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) | 
 |  * @see     java.net.SocketImpl | 
 |  * @see     java.nio.channels.SocketChannel | 
 |  * @since   JDK1.0 | 
 |  */ | 
 | public | 
 | class Socket implements java.io.Closeable { | 
 |     /** | 
 |      * Various states of this socket. | 
 |      */ | 
 |     private boolean created = false; | 
 |     private boolean bound = false; | 
 |     private boolean connected = false; | 
 |     private boolean closed = false; | 
 |     private Object closeLock = new Object(); | 
 |     private boolean shutIn = false; | 
 |     private boolean shutOut = false; | 
 |  | 
 |     /** | 
 |      * The implementation of this Socket. | 
 |      */ | 
 |     SocketImpl impl; | 
 |  | 
 |     /** | 
 |      * Are we using an older SocketImpl? | 
 |      */ | 
 |     private boolean oldImpl = false; | 
 |  | 
 |     /** | 
 |      * Creates an unconnected socket, with the | 
 |      * system-default type of SocketImpl. | 
 |      * | 
 |      * @since   JDK1.1 | 
 |      * @revised 1.4 | 
 |      */ | 
 |     public Socket() { | 
 |         setImpl(); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates an unconnected socket, specifying the type of proxy, if any, | 
 |      * that should be used regardless of any other settings. | 
 |      * <P> | 
 |      * If there is a security manager, its {@code checkConnect} method | 
 |      * is called with the proxy host address and port number | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * <P> | 
 |      * Examples: | 
 |      * <UL> <LI>{@code Socket s = new Socket(Proxy.NO_PROXY);} will create | 
 |      * a plain socket ignoring any other proxy configuration.</LI> | 
 |      * <LI>{@code Socket s = new Socket(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("socks.mydom.com", 1080)));} | 
 |      * will create a socket connecting through the specified SOCKS proxy | 
 |      * server.</LI> | 
 |      * </UL> | 
 |      * | 
 |      * @param proxy a {@link java.net.Proxy Proxy} object specifying what kind | 
 |      *              of proxying should be used. | 
 |      * @throws IllegalArgumentException if the proxy is of an invalid type | 
 |      *          or {@code null}. | 
 |      * @throws SecurityException if a security manager is present and | 
 |      *                           permission to connect to the proxy is | 
 |      *                           denied. | 
 |      * @see java.net.ProxySelector | 
 |      * @see java.net.Proxy | 
 |      * | 
 |      * @since   1.5 | 
 |      */ | 
 |     public Socket(Proxy proxy) { | 
 |         // Create a copy of Proxy as a security measure | 
 |         if (proxy == null) { | 
 |             throw new IllegalArgumentException("Invalid Proxy"); | 
 |         } | 
 |         Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY | 
 |                                           : sun.net.ApplicationProxy.create(proxy); | 
 |         Proxy.Type type = p.type(); | 
 |         // Android-changed: Removed HTTP proxy support. | 
 |         // if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) { | 
 |         if (type == Proxy.Type.SOCKS) { | 
 |             SecurityManager security = System.getSecurityManager(); | 
 |             InetSocketAddress epoint = (InetSocketAddress) p.address(); | 
 |             if (epoint.getAddress() != null) { | 
 |                 checkAddress (epoint.getAddress(), "Socket"); | 
 |             } | 
 |             if (security != null) { | 
 |                 if (epoint.isUnresolved()) | 
 |                     epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort()); | 
 |                 if (epoint.isUnresolved()) | 
 |                     security.checkConnect(epoint.getHostName(), epoint.getPort()); | 
 |                 else | 
 |                     security.checkConnect(epoint.getAddress().getHostAddress(), | 
 |                                   epoint.getPort()); | 
 |             } | 
 |             // Android-changed: Removed HTTP proxy support. | 
 |             // impl = type == Proxy.Type.SOCKS ? new SocksSocketImpl(p) | 
 |             //                                : new HttpConnectSocketImpl(p); | 
 |             impl = new SocksSocketImpl(p); | 
 |             impl.setSocket(this); | 
 |         } else { | 
 |             if (p == Proxy.NO_PROXY) { | 
 |                 if (factory == null) { | 
 |                     impl = new PlainSocketImpl(); | 
 |                     impl.setSocket(this); | 
 |                 } else | 
 |                     setImpl(); | 
 |             } else | 
 |                 throw new IllegalArgumentException("Invalid Proxy"); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates an unconnected Socket with a user-specified | 
 |      * SocketImpl. | 
 |      * <P> | 
 |      * @param impl an instance of a <B>SocketImpl</B> | 
 |      * the subclass wishes to use on the Socket. | 
 |      * | 
 |      * @exception SocketException if there is an error in the underlying protocol, | 
 |      * such as a TCP error. | 
 |      * @since   JDK1.1 | 
 |      */ | 
 |     protected Socket(SocketImpl impl) throws SocketException { | 
 |         this.impl = impl; | 
 |         if (impl != null) { | 
 |             checkOldImpl(); | 
 |             this.impl.setSocket(this); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates a stream socket and connects it to the specified port | 
 |      * number on the named host. | 
 |      * <p> | 
 |      * If the specified host is {@code null} it is the equivalent of | 
 |      * specifying the address as | 
 |      * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}. | 
 |      * In other words, it is equivalent to specifying an address of the | 
 |      * loopback interface. </p> | 
 |      * <p> | 
 |      * If the application has specified a server socket factory, that | 
 |      * factory's {@code createSocketImpl} method is called to create | 
 |      * the actual socket implementation. Otherwise a "plain" socket is created. | 
 |      * <p> | 
 |      * If there is a security manager, its | 
 |      * {@code checkConnect} method is called | 
 |      * with the host address and {@code port} | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * | 
 |      * @param      host   the host name, or {@code null} for the loopback address. | 
 |      * @param      port   the port number. | 
 |      * | 
 |      * @exception  UnknownHostException if the IP address of | 
 |      * the host could not be determined. | 
 |      * | 
 |      * @exception  IOException  if an I/O error occurs when creating the socket. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkConnect} method doesn't allow the operation. | 
 |      * @exception  IllegalArgumentException if the port parameter is outside | 
 |      *             the specified range of valid port values, which is between | 
 |      *             0 and 65535, inclusive. | 
 |      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) | 
 |      * @see        java.net.SocketImpl | 
 |      * @see        java.net.SocketImplFactory#createSocketImpl() | 
 |      * @see        SecurityManager#checkConnect | 
 |      */ | 
 |     public Socket(String host, int port) | 
 |         throws UnknownHostException, IOException | 
 |     { | 
 |         // Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |         this(InetAddress.getAllByName(host), port, (SocketAddress) null, true); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates a stream socket and connects it to the specified port | 
 |      * number at the specified IP address. | 
 |      * <p> | 
 |      * If the application has specified a socket factory, that factory's | 
 |      * {@code createSocketImpl} method is called to create the | 
 |      * actual socket implementation. Otherwise a "plain" socket is created. | 
 |      * <p> | 
 |      * If there is a security manager, its | 
 |      * {@code checkConnect} method is called | 
 |      * with the host address and {@code port} | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * | 
 |      * @param      address   the IP address. | 
 |      * @param      port      the port number. | 
 |      * @exception  IOException  if an I/O error occurs when creating the socket. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkConnect} method doesn't allow the operation. | 
 |      * @exception  IllegalArgumentException if the port parameter is outside | 
 |      *             the specified range of valid port values, which is between | 
 |      *             0 and 65535, inclusive. | 
 |      * @exception  NullPointerException if {@code address} is null. | 
 |      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) | 
 |      * @see        java.net.SocketImpl | 
 |      * @see        java.net.SocketImplFactory#createSocketImpl() | 
 |      * @see        SecurityManager#checkConnect | 
 |      */ | 
 |     public Socket(InetAddress address, int port) throws IOException { | 
 |         // Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |         this(nonNullAddress(address), port, (SocketAddress) null, true); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates a socket and connects it to the specified remote host on | 
 |      * the specified remote port. The Socket will also bind() to the local | 
 |      * address and port supplied. | 
 |      * <p> | 
 |      * If the specified host is {@code null} it is the equivalent of | 
 |      * specifying the address as | 
 |      * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}. | 
 |      * In other words, it is equivalent to specifying an address of the | 
 |      * loopback interface. </p> | 
 |      * <p> | 
 |      * A local port number of {@code zero} will let the system pick up a | 
 |      * free port in the {@code bind} operation.</p> | 
 |      * <p> | 
 |      * If there is a security manager, its | 
 |      * {@code checkConnect} method is called | 
 |      * with the host address and {@code port} | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * | 
 |      * @param host the name of the remote host, or {@code null} for the loopback address. | 
 |      * @param port the remote port | 
 |      * @param localAddr the local address the socket is bound to, or | 
 |      *        {@code null} for the {@code anyLocal} address. | 
 |      * @param localPort the local port the socket is bound to, or | 
 |      *        {@code zero} for a system selected free port. | 
 |      * @exception  IOException  if an I/O error occurs when creating the socket. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkConnect} method doesn't allow the connection | 
 |      *             to the destination, or if its {@code checkListen} method | 
 |      *             doesn't allow the bind to the local port. | 
 |      * @exception  IllegalArgumentException if the port parameter or localPort | 
 |      *             parameter is outside the specified range of valid port values, | 
 |      *             which is between 0 and 65535, inclusive. | 
 |      * @see        SecurityManager#checkConnect | 
 |      * @since   JDK1.1 | 
 |      */ | 
 |     public Socket(String host, int port, InetAddress localAddr, | 
 |                   int localPort) throws IOException { | 
 |         // Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |         this(InetAddress.getAllByName(host), port, | 
 |              new InetSocketAddress(localAddr, localPort), true); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates a socket and connects it to the specified remote address on | 
 |      * the specified remote port. The Socket will also bind() to the local | 
 |      * address and port supplied. | 
 |      * <p> | 
 |      * If the specified local address is {@code null} it is the equivalent of | 
 |      * specifying the address as the AnyLocal address | 
 |      * (see {@link java.net.InetAddress#isAnyLocalAddress InetAddress.isAnyLocalAddress}{@code ()}). | 
 |      * <p> | 
 |      * A local port number of {@code zero} will let the system pick up a | 
 |      * free port in the {@code bind} operation.</p> | 
 |      * <p> | 
 |      * If there is a security manager, its | 
 |      * {@code checkConnect} method is called | 
 |      * with the host address and {@code port} | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * | 
 |      * @param address the remote address | 
 |      * @param port the remote port | 
 |      * @param localAddr the local address the socket is bound to, or | 
 |      *        {@code null} for the {@code anyLocal} address. | 
 |      * @param localPort the local port the socket is bound to or | 
 |      *        {@code zero} for a system selected free port. | 
 |      * @exception  IOException  if an I/O error occurs when creating the socket. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkConnect} method doesn't allow the connection | 
 |      *             to the destination, or if its {@code checkListen} method | 
 |      *             doesn't allow the bind to the local port. | 
 |      * @exception  IllegalArgumentException if the port parameter or localPort | 
 |      *             parameter is outside the specified range of valid port values, | 
 |      *             which is between 0 and 65535, inclusive. | 
 |      * @exception  NullPointerException if {@code address} is null. | 
 |      * @see        SecurityManager#checkConnect | 
 |      * @since   JDK1.1 | 
 |      */ | 
 |     public Socket(InetAddress address, int port, InetAddress localAddr, | 
 |                   int localPort) throws IOException { | 
 |         // Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |         this(nonNullAddress(address), port, | 
 |              new InetSocketAddress(localAddr, localPort), true); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates a stream socket and connects it to the specified port | 
 |      * number on the named host. | 
 |      * <p> | 
 |      * If the specified host is {@code null} it is the equivalent of | 
 |      * specifying the address as | 
 |      * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}. | 
 |      * In other words, it is equivalent to specifying an address of the | 
 |      * loopback interface. </p> | 
 |      * <p> | 
 |      * If the stream argument is {@code true}, this creates a | 
 |      * stream socket. If the stream argument is {@code false}, it | 
 |      * creates a datagram socket. | 
 |      * <p> | 
 |      * If the application has specified a server socket factory, that | 
 |      * factory's {@code createSocketImpl} method is called to create | 
 |      * the actual socket implementation. Otherwise a "plain" socket is created. | 
 |      * <p> | 
 |      * If there is a security manager, its | 
 |      * {@code checkConnect} method is called | 
 |      * with the host address and {@code port} | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * <p> | 
 |      * If a UDP socket is used, TCP/IP related socket options will not apply. | 
 |      * | 
 |      * @param      host     the host name, or {@code null} for the loopback address. | 
 |      * @param      port     the port number. | 
 |      * @param      stream   a {@code boolean} indicating whether this is | 
 |      *                      a stream socket or a datagram socket. | 
 |      * @exception  IOException  if an I/O error occurs when creating the socket. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkConnect} method doesn't allow the operation. | 
 |      * @exception  IllegalArgumentException if the port parameter is outside | 
 |      *             the specified range of valid port values, which is between | 
 |      *             0 and 65535, inclusive. | 
 |      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) | 
 |      * @see        java.net.SocketImpl | 
 |      * @see        java.net.SocketImplFactory#createSocketImpl() | 
 |      * @see        SecurityManager#checkConnect | 
 |      * @deprecated Use DatagramSocket instead for UDP transport. | 
 |      */ | 
 |     @Deprecated | 
 |     public Socket(String host, int port, boolean stream) throws IOException { | 
 |         // Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |         this(InetAddress.getAllByName(host), port, (SocketAddress) null, stream); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Creates a socket and connects it to the specified port number at | 
 |      * the specified IP address. | 
 |      * <p> | 
 |      * If the stream argument is {@code true}, this creates a | 
 |      * stream socket. If the stream argument is {@code false}, it | 
 |      * creates a datagram socket. | 
 |      * <p> | 
 |      * If the application has specified a server socket factory, that | 
 |      * factory's {@code createSocketImpl} method is called to create | 
 |      * the actual socket implementation. Otherwise a "plain" socket is created. | 
 |      * | 
 |      * <p>If there is a security manager, its | 
 |      * {@code checkConnect} method is called | 
 |      * with {@code host.getHostAddress()} and {@code port} | 
 |      * as its arguments. This could result in a SecurityException. | 
 |      * <p> | 
 |      * If UDP socket is used, TCP/IP related socket options will not apply. | 
 |      * | 
 |      * @param      host     the IP address. | 
 |      * @param      port      the port number. | 
 |      * @param      stream    if {@code true}, create a stream socket; | 
 |      *                       otherwise, create a datagram socket. | 
 |      * @exception  IOException  if an I/O error occurs when creating the socket. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkConnect} method doesn't allow the operation. | 
 |      * @exception  IllegalArgumentException if the port parameter is outside | 
 |      *             the specified range of valid port values, which is between | 
 |      *             0 and 65535, inclusive. | 
 |      * @exception  NullPointerException if {@code host} is null. | 
 |      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) | 
 |      * @see        java.net.SocketImpl | 
 |      * @see        java.net.SocketImplFactory#createSocketImpl() | 
 |      * @see        SecurityManager#checkConnect | 
 |      * @deprecated Use DatagramSocket instead for UDP transport. | 
 |      */ | 
 |     @Deprecated | 
 |     public Socket(InetAddress host, int port, boolean stream) throws IOException { | 
 |         // Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |         this(nonNullAddress(host), port, new InetSocketAddress(0), stream); | 
 |     } | 
 |  | 
 |     // BEGIN Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |     private static InetAddress[] nonNullAddress(InetAddress address) { | 
 |         // backward compatibility | 
 |         if (address == null) | 
 |             throw new NullPointerException(); | 
 |  | 
 |         return new InetAddress[] { address }; | 
 |     } | 
 |  | 
 |     private Socket(InetAddress[] addresses, int port, SocketAddress localAddr, | 
 |             boolean stream) throws IOException { | 
 |         if (addresses == null || addresses.length == 0) { | 
 |             throw new SocketException("Impossible: empty address list"); | 
 |         } | 
 |  | 
 |         for (int i = 0; i < addresses.length; i++) { | 
 |             setImpl(); | 
 |             try { | 
 |                 InetSocketAddress address = new InetSocketAddress(addresses[i], port); | 
 |                 createImpl(stream); | 
 |                 if (localAddr != null) { | 
 |                     bind(localAddr); | 
 |                 } | 
 |                 connect(address); | 
 |                 break; | 
 |             } catch (IOException | IllegalArgumentException | SecurityException e) { | 
 |                 try { | 
 |                     // Android-changed: Let ctor call impl.close() instead of overridable close(). | 
 |                     // Subclasses may not expect a call to close() coming from this constructor. | 
 |                     impl.close(); | 
 |                     closed = true; | 
 |                 } catch (IOException ce) { | 
 |                     e.addSuppressed(ce); | 
 |                 } | 
 |  | 
 |                 // Only stop on the last address. | 
 |                 if (i == addresses.length - 1) { | 
 |                     throw e; | 
 |                 } | 
 |             } | 
 |  | 
 |             // Discard the connection state and try again. | 
 |             impl = null; | 
 |             created = false; | 
 |             bound = false; | 
 |             closed = false; | 
 |         } | 
 |     } | 
 |     // END Android-changed: App compat. Socket ctor should try all addresses. http://b/30007735 | 
 |  | 
 |     /** | 
 |      * Creates the socket implementation. | 
 |      * | 
 |      * @param stream a {@code boolean} value : {@code true} for a TCP socket, | 
 |      *               {@code false} for UDP. | 
 |      * @throws IOException if creation fails | 
 |      * @since 1.4 | 
 |      */ | 
 |      void createImpl(boolean stream) throws SocketException { | 
 |         if (impl == null) | 
 |             setImpl(); | 
 |         try { | 
 |             impl.create(stream); | 
 |             created = true; | 
 |         } catch (IOException e) { | 
 |             throw new SocketException(e.getMessage()); | 
 |         } | 
 |     } | 
 |  | 
 |     private void checkOldImpl() { | 
 |         if (impl == null) | 
 |             return; | 
 |         // SocketImpl.connect() is a protected method, therefore we need to use | 
 |         // getDeclaredMethod, therefore we need permission to access the member | 
 |  | 
 |         oldImpl = AccessController.doPrivileged | 
 |                                 (new PrivilegedAction<Boolean>() { | 
 |             public Boolean run() { | 
 |                 Class<?> clazz = impl.getClass(); | 
 |                 while (true) { | 
 |                     try { | 
 |                         clazz.getDeclaredMethod("connect", SocketAddress.class, int.class); | 
 |                         return Boolean.FALSE; | 
 |                     } catch (NoSuchMethodException e) { | 
 |                         clazz = clazz.getSuperclass(); | 
 |                         // java.net.SocketImpl class will always have this abstract method. | 
 |                         // If we have not found it by now in the hierarchy then it does not | 
 |                         // exist, we are an old style impl. | 
 |                         if (clazz.equals(java.net.SocketImpl.class)) { | 
 |                             return Boolean.TRUE; | 
 |                         } | 
 |                     } | 
 |                 } | 
 |             } | 
 |         }); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets impl to the system-default type of SocketImpl. | 
 |      * @since 1.4 | 
 |      */ | 
 |     void setImpl() { | 
 |         if (factory != null) { | 
 |             impl = factory.createSocketImpl(); | 
 |             checkOldImpl(); | 
 |         } else { | 
 |             // No need to do a checkOldImpl() here, we know it's an up to date | 
 |             // SocketImpl! | 
 |             impl = new SocksSocketImpl(); | 
 |         } | 
 |         if (impl != null) | 
 |             impl.setSocket(this); | 
 |     } | 
 |  | 
 |  | 
 |     /** | 
 |      * Get the {@code SocketImpl} attached to this socket, creating | 
 |      * it if necessary. | 
 |      * | 
 |      * @return  the {@code SocketImpl} attached to that ServerSocket. | 
 |      * @throws SocketException if creation fails | 
 |      * @since 1.4 | 
 |      */ | 
 |     SocketImpl getImpl() throws SocketException { | 
 |         if (!created) | 
 |             createImpl(true); | 
 |         return impl; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Connects this socket to the server. | 
 |      * | 
 |      * @param   endpoint the {@code SocketAddress} | 
 |      * @throws  IOException if an error occurs during the connection | 
 |      * @throws  java.nio.channels.IllegalBlockingModeException | 
 |      *          if this socket has an associated channel, | 
 |      *          and the channel is in non-blocking mode | 
 |      * @throws  IllegalArgumentException if endpoint is null or is a | 
 |      *          SocketAddress subclass not supported by this socket | 
 |      * @since 1.4 | 
 |      * @spec JSR-51 | 
 |      */ | 
 |     public void connect(SocketAddress endpoint) throws IOException { | 
 |         connect(endpoint, 0); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Connects this socket to the server with a specified timeout value. | 
 |      * A timeout of zero is interpreted as an infinite timeout. The connection | 
 |      * will then block until established or an error occurs. | 
 |      * | 
 |      * @param   endpoint the {@code SocketAddress} | 
 |      * @param   timeout  the timeout value to be used in milliseconds. | 
 |      * @throws  IOException if an error occurs during the connection | 
 |      * @throws  SocketTimeoutException if timeout expires before connecting | 
 |      * @throws  java.nio.channels.IllegalBlockingModeException | 
 |      *          if this socket has an associated channel, | 
 |      *          and the channel is in non-blocking mode | 
 |      * @throws  IllegalArgumentException if endpoint is null or is a | 
 |      *          SocketAddress subclass not supported by this socket | 
 |      * @since 1.4 | 
 |      * @spec JSR-51 | 
 |      */ | 
 |     public void connect(SocketAddress endpoint, int timeout) throws IOException { | 
 |         if (endpoint == null) | 
 |             throw new IllegalArgumentException("connect: The address can't be null"); | 
 |  | 
 |         if (timeout < 0) | 
 |           throw new IllegalArgumentException("connect: timeout can't be negative"); | 
 |  | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |  | 
 |         if (!oldImpl && isConnected()) | 
 |             throw new SocketException("already connected"); | 
 |  | 
 |         if (!(endpoint instanceof InetSocketAddress)) | 
 |             throw new IllegalArgumentException("Unsupported address type"); | 
 |  | 
 |         InetSocketAddress epoint = (InetSocketAddress) endpoint; | 
 |         InetAddress addr = epoint.getAddress (); | 
 |         int port = epoint.getPort(); | 
 |         checkAddress(addr, "connect"); | 
 |  | 
 |         SecurityManager security = System.getSecurityManager(); | 
 |         if (security != null) { | 
 |             if (epoint.isUnresolved()) | 
 |                 security.checkConnect(epoint.getHostName(), port); | 
 |             else | 
 |                 security.checkConnect(addr.getHostAddress(), port); | 
 |         } | 
 |         if (!created) | 
 |             createImpl(true); | 
 |         if (!oldImpl) | 
 |             impl.connect(epoint, timeout); | 
 |         else if (timeout == 0) { | 
 |             if (epoint.isUnresolved()) | 
 |                 impl.connect(addr.getHostName(), port); | 
 |             else | 
 |                 impl.connect(addr, port); | 
 |         } else | 
 |             throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)"); | 
 |         connected = true; | 
 |         /* | 
 |          * If the socket was not bound before the connect, it is now because | 
 |          * the kernel will have picked an ephemeral port & a local address | 
 |          */ | 
 |         bound = true; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Binds the socket to a local address. | 
 |      * <P> | 
 |      * If the address is {@code null}, then the system will pick up | 
 |      * an ephemeral port and a valid local address to bind the socket. | 
 |      * | 
 |      * @param   bindpoint the {@code SocketAddress} to bind to | 
 |      * @throws  IOException if the bind operation fails, or if the socket | 
 |      *                     is already bound. | 
 |      * @throws  IllegalArgumentException if bindpoint is a | 
 |      *          SocketAddress subclass not supported by this socket | 
 |      * @throws  SecurityException  if a security manager exists and its | 
 |      *          {@code checkListen} method doesn't allow the bind | 
 |      *          to the local port. | 
 |      * | 
 |      * @since   1.4 | 
 |      * @see #isBound | 
 |      */ | 
 |     public void bind(SocketAddress bindpoint) throws IOException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (!oldImpl && isBound()) | 
 |             throw new SocketException("Already bound"); | 
 |  | 
 |         if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress))) | 
 |             throw new IllegalArgumentException("Unsupported address type"); | 
 |         InetSocketAddress epoint = (InetSocketAddress) bindpoint; | 
 |         if (epoint != null && epoint.isUnresolved()) | 
 |             throw new SocketException("Unresolved address"); | 
 |         if (epoint == null) { | 
 |             epoint = new InetSocketAddress(0); | 
 |         } | 
 |         InetAddress addr = epoint.getAddress(); | 
 |         int port = epoint.getPort(); | 
 |         checkAddress (addr, "bind"); | 
 |         SecurityManager security = System.getSecurityManager(); | 
 |         if (security != null) { | 
 |             security.checkListen(port); | 
 |         } | 
 |         getImpl().bind (addr, port); | 
 |         bound = true; | 
 |     } | 
 |  | 
 |     private void checkAddress (InetAddress addr, String op) { | 
 |         if (addr == null) { | 
 |             return; | 
 |         } | 
 |         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { | 
 |             throw new IllegalArgumentException(op + ": invalid address type"); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * set the flags after an accept() call. | 
 |      */ | 
 |     final void postAccept() { | 
 |         connected = true; | 
 |         created = true; | 
 |         bound = true; | 
 |     } | 
 |  | 
 |     void setCreated() { | 
 |         created = true; | 
 |     } | 
 |  | 
 |     void setBound() { | 
 |         bound = true; | 
 |     } | 
 |  | 
 |     void setConnected() { | 
 |         connected = true; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the address to which the socket is connected. | 
 |      * <p> | 
 |      * If the socket was connected prior to being {@link #close closed}, | 
 |      * then this method will continue to return the connected address | 
 |      * after the socket is closed. | 
 |      * | 
 |      * @return  the remote IP address to which this socket is connected, | 
 |      *          or {@code null} if the socket is not connected. | 
 |      */ | 
 |     public InetAddress getInetAddress() { | 
 |         if (!isConnected()) | 
 |             return null; | 
 |         try { | 
 |             return getImpl().getInetAddress(); | 
 |         } catch (SocketException e) { | 
 |         } | 
 |         return null; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Gets the local address to which the socket is bound. | 
 |      * <p> | 
 |      * If there is a security manager set, its {@code checkConnect} method is | 
 |      * called with the local address and {@code -1} as its arguments to see | 
 |      * if the operation is allowed. If the operation is not allowed, | 
 |      * the {@link InetAddress#getLoopbackAddress loopback} address is returned. | 
 |      * | 
 |      * @return the local address to which the socket is bound, | 
 |      *         the loopback address if denied by the security manager, or | 
 |      *         the wildcard address if the socket is closed or not bound yet. | 
 |      * @since   JDK1.1 | 
 |      * | 
 |      * @see SecurityManager#checkConnect | 
 |      */ | 
 |     public InetAddress getLocalAddress() { | 
 |         // This is for backward compatibility | 
 |         if (!isBound()) | 
 |             return InetAddress.anyLocalAddress(); | 
 |         InetAddress in = null; | 
 |         try { | 
 |             in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); | 
 |             SecurityManager sm = System.getSecurityManager(); | 
 |             if (sm != null) | 
 |                 sm.checkConnect(in.getHostAddress(), -1); | 
 |             if (in.isAnyLocalAddress()) { | 
 |                 in = InetAddress.anyLocalAddress(); | 
 |             } | 
 |         } catch (SecurityException e) { | 
 |             in = InetAddress.getLoopbackAddress(); | 
 |         } catch (Exception e) { | 
 |             in = InetAddress.anyLocalAddress(); // "0.0.0.0" | 
 |         } | 
 |         return in; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the remote port number to which this socket is connected. | 
 |      * <p> | 
 |      * If the socket was connected prior to being {@link #close closed}, | 
 |      * then this method will continue to return the connected port number | 
 |      * after the socket is closed. | 
 |      * | 
 |      * @return  the remote port number to which this socket is connected, or | 
 |      *          0 if the socket is not connected yet. | 
 |      */ | 
 |     public int getPort() { | 
 |         if (!isConnected()) | 
 |             return 0; | 
 |         try { | 
 |             return getImpl().getPort(); | 
 |         } catch (SocketException e) { | 
 |             // Shouldn't happen as we're connected | 
 |         } | 
 |         return -1; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the local port number to which this socket is bound. | 
 |      * <p> | 
 |      * If the socket was bound prior to being {@link #close closed}, | 
 |      * then this method will continue to return the local port number | 
 |      * after the socket is closed. | 
 |      * | 
 |      * @return  the local port number to which this socket is bound or -1 | 
 |      *          if the socket is not bound yet. | 
 |      */ | 
 |     public int getLocalPort() { | 
 |         if (!isBound()) | 
 |             return -1; | 
 |         try { | 
 |             return getImpl().getLocalPort(); | 
 |         } catch(SocketException e) { | 
 |             // shouldn't happen as we're bound | 
 |         } | 
 |         return -1; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the address of the endpoint this socket is connected to, or | 
 |      * {@code null} if it is unconnected. | 
 |      * <p> | 
 |      * If the socket was connected prior to being {@link #close closed}, | 
 |      * then this method will continue to return the connected address | 
 |      * after the socket is closed. | 
 |      * | 
 |  | 
 |      * @return a {@code SocketAddress} representing the remote endpoint of this | 
 |      *         socket, or {@code null} if it is not connected yet. | 
 |      * @see #getInetAddress() | 
 |      * @see #getPort() | 
 |      * @see #connect(SocketAddress, int) | 
 |      * @see #connect(SocketAddress) | 
 |      * @since 1.4 | 
 |      */ | 
 |     public SocketAddress getRemoteSocketAddress() { | 
 |         if (!isConnected()) | 
 |             return null; | 
 |         return new InetSocketAddress(getInetAddress(), getPort()); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the address of the endpoint this socket is bound to. | 
 |      * <p> | 
 |      * If a socket bound to an endpoint represented by an | 
 |      * {@code InetSocketAddress } is {@link #close closed}, | 
 |      * then this method will continue to return an {@code InetSocketAddress} | 
 |      * after the socket is closed. In that case the returned | 
 |      * {@code InetSocketAddress}'s address is the | 
 |      * {@link InetAddress#isAnyLocalAddress wildcard} address | 
 |      * and its port is the local port that it was bound to. | 
 |      * <p> | 
 |      * If there is a security manager set, its {@code checkConnect} method is | 
 |      * called with the local address and {@code -1} as its arguments to see | 
 |      * if the operation is allowed. If the operation is not allowed, | 
 |      * a {@code SocketAddress} representing the | 
 |      * {@link InetAddress#getLoopbackAddress loopback} address and the local | 
 |      * port to which this socket is bound is returned. | 
 |      * | 
 |      * @return a {@code SocketAddress} representing the local endpoint of | 
 |      *         this socket, or a {@code SocketAddress} representing the | 
 |      *         loopback address if denied by the security manager, or | 
 |      *         {@code null} if the socket is not bound yet. | 
 |      * | 
 |      * @see #getLocalAddress() | 
 |      * @see #getLocalPort() | 
 |      * @see #bind(SocketAddress) | 
 |      * @see SecurityManager#checkConnect | 
 |      * @since 1.4 | 
 |      */ | 
 |  | 
 |     public SocketAddress getLocalSocketAddress() { | 
 |         if (!isBound()) | 
 |             return null; | 
 |         return new InetSocketAddress(getLocalAddress(), getLocalPort()); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the unique {@link java.nio.channels.SocketChannel SocketChannel} | 
 |      * object associated with this socket, if any. | 
 |      * | 
 |      * <p> A socket will have a channel if, and only if, the channel itself was | 
 |      * created via the {@link java.nio.channels.SocketChannel#open | 
 |      * SocketChannel.open} or {@link | 
 |      * java.nio.channels.ServerSocketChannel#accept ServerSocketChannel.accept} | 
 |      * methods. | 
 |      * | 
 |      * @return  the socket channel associated with this socket, | 
 |      *          or {@code null} if this socket was not created | 
 |      *          for a channel | 
 |      * | 
 |      * @since 1.4 | 
 |      * @spec JSR-51 | 
 |      */ | 
 |     public SocketChannel getChannel() { | 
 |         return null; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns an input stream for this socket. | 
 |      * | 
 |      * <p> If this socket has an associated channel then the resulting input | 
 |      * stream delegates all of its operations to the channel.  If the channel | 
 |      * is in non-blocking mode then the input stream's {@code read} operations | 
 |      * will throw an {@link java.nio.channels.IllegalBlockingModeException}. | 
 |      * | 
 |      * <p>Under abnormal conditions the underlying connection may be | 
 |      * broken by the remote host or the network software (for example | 
 |      * a connection reset in the case of TCP connections). When a | 
 |      * broken connection is detected by the network software the | 
 |      * following applies to the returned input stream :- | 
 |      * | 
 |      * <ul> | 
 |      * | 
 |      *   <li><p>The network software may discard bytes that are buffered | 
 |      *   by the socket. Bytes that aren't discarded by the network | 
 |      *   software can be read using {@link java.io.InputStream#read read}. | 
 |      * | 
 |      *   <li><p>If there are no bytes buffered on the socket, or all | 
 |      *   buffered bytes have been consumed by | 
 |      *   {@link java.io.InputStream#read read}, then all subsequent | 
 |      *   calls to {@link java.io.InputStream#read read} will throw an | 
 |      *   {@link java.io.IOException IOException}. | 
 |      * | 
 |      *   <li><p>If there are no bytes buffered on the socket, and the | 
 |      *   socket has not been closed using {@link #close close}, then | 
 |      *   {@link java.io.InputStream#available available} will | 
 |      *   return {@code 0}. | 
 |      * | 
 |      * </ul> | 
 |      * | 
 |      * <p> Closing the returned {@link java.io.InputStream InputStream} | 
 |      * will close the associated socket. | 
 |      * | 
 |      * @return     an input stream for reading bytes from this socket. | 
 |      * @exception  IOException  if an I/O error occurs when creating the | 
 |      *             input stream, the socket is closed, the socket is | 
 |      *             not connected, or the socket input has been shutdown | 
 |      *             using {@link #shutdownInput()} | 
 |      * | 
 |      * @revised 1.4 | 
 |      * @spec JSR-51 | 
 |      */ | 
 |     public InputStream getInputStream() throws IOException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (!isConnected()) | 
 |             throw new SocketException("Socket is not connected"); | 
 |         if (isInputShutdown()) | 
 |             throw new SocketException("Socket input is shutdown"); | 
 |         final Socket s = this; | 
 |         InputStream is = null; | 
 |         try { | 
 |             is = AccessController.doPrivileged( | 
 |                 new PrivilegedExceptionAction<InputStream>() { | 
 |                     public InputStream run() throws IOException { | 
 |                         return impl.getInputStream(); | 
 |                     } | 
 |                 }); | 
 |         } catch (java.security.PrivilegedActionException e) { | 
 |             throw (IOException) e.getException(); | 
 |         } | 
 |         return is; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns an output stream for this socket. | 
 |      * | 
 |      * <p> If this socket has an associated channel then the resulting output | 
 |      * stream delegates all of its operations to the channel.  If the channel | 
 |      * is in non-blocking mode then the output stream's {@code write} | 
 |      * operations will throw an {@link | 
 |      * java.nio.channels.IllegalBlockingModeException}. | 
 |      * | 
 |      * <p> Closing the returned {@link java.io.OutputStream OutputStream} | 
 |      * will close the associated socket. | 
 |      * | 
 |      * @return     an output stream for writing bytes to this socket. | 
 |      * @exception  IOException  if an I/O error occurs when creating the | 
 |      *               output stream or if the socket is not connected. | 
 |      * @revised 1.4 | 
 |      * @spec JSR-51 | 
 |      */ | 
 |     public OutputStream getOutputStream() throws IOException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (!isConnected()) | 
 |             throw new SocketException("Socket is not connected"); | 
 |         if (isOutputShutdown()) | 
 |             throw new SocketException("Socket output is shutdown"); | 
 |         final Socket s = this; | 
 |         OutputStream os = null; | 
 |         try { | 
 |             os = AccessController.doPrivileged( | 
 |                 new PrivilegedExceptionAction<OutputStream>() { | 
 |                     public OutputStream run() throws IOException { | 
 |                         return impl.getOutputStream(); | 
 |                     } | 
 |                 }); | 
 |         } catch (java.security.PrivilegedActionException e) { | 
 |             throw (IOException) e.getException(); | 
 |         } | 
 |         return os; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Enable/disable {@link SocketOptions#TCP_NODELAY TCP_NODELAY} | 
 |      * (disable/enable Nagle's algorithm). | 
 |      * | 
 |      * @param on {@code true} to enable TCP_NODELAY, | 
 |      * {@code false} to disable. | 
 |      * | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * | 
 |      * @since   JDK1.1 | 
 |      * | 
 |      * @see #getTcpNoDelay() | 
 |      */ | 
 |     public void setTcpNoDelay(boolean on) throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Tests if {@link SocketOptions#TCP_NODELAY TCP_NODELAY} is enabled. | 
 |      * | 
 |      * @return a {@code boolean} indicating whether or not | 
 |      *         {@link SocketOptions#TCP_NODELAY TCP_NODELAY} is enabled. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since   JDK1.1 | 
 |      * @see #setTcpNoDelay(boolean) | 
 |      */ | 
 |     public boolean getTcpNoDelay() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         return ((Boolean) getImpl().getOption(SocketOptions.TCP_NODELAY)).booleanValue(); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Enable/disable {@link SocketOptions#SO_LINGER SO_LINGER} with the | 
 |      * specified linger time in seconds. The maximum timeout value is platform | 
 |      * specific. | 
 |      * | 
 |      * The setting only affects socket close. | 
 |      * | 
 |      * @param on     whether or not to linger on. | 
 |      * @param linger how long to linger for, if on is true. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @exception IllegalArgumentException if the linger value is negative. | 
 |      * @since JDK1.1 | 
 |      * @see #getSoLinger() | 
 |      */ | 
 |     public void setSoLinger(boolean on, int linger) throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (!on) { | 
 |             getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on)); | 
 |         } else { | 
 |             if (linger < 0) { | 
 |                 throw new IllegalArgumentException("invalid value for SO_LINGER"); | 
 |             } | 
 |             if (linger > 65535) | 
 |                 linger = 65535; | 
 |             getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger)); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns setting for {@link SocketOptions#SO_LINGER SO_LINGER}. | 
 |      * -1 returns implies that the | 
 |      * option is disabled. | 
 |      * | 
 |      * The setting only affects socket close. | 
 |      * | 
 |      * @return the setting for {@link SocketOptions#SO_LINGER SO_LINGER}. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since   JDK1.1 | 
 |      * @see #setSoLinger(boolean, int) | 
 |      */ | 
 |     public int getSoLinger() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         Object o = getImpl().getOption(SocketOptions.SO_LINGER); | 
 |         if (o instanceof Integer) { | 
 |             return ((Integer) o).intValue(); | 
 |         } else { | 
 |             return -1; | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Send one byte of urgent data on the socket. The byte to be sent is the lowest eight | 
 |      * bits of the data parameter. The urgent byte is | 
 |      * sent after any preceding writes to the socket OutputStream | 
 |      * and before any future writes to the OutputStream. | 
 |      * @param data The byte of data to send | 
 |      * @exception IOException if there is an error | 
 |      *  sending the data. | 
 |      * @since 1.4 | 
 |      */ | 
 |     public void sendUrgentData (int data) throws IOException  { | 
 |         // Android-changed: If the socket is closed, sendUrgentData should not create a new impl. | 
 |         // Fail early to avoid leaking resources. | 
 |         // http://b/31818400 | 
 |         if (isClosed()) { | 
 |             throw new SocketException("Socket is closed"); | 
 |         } | 
 |  | 
 |         if (!getImpl().supportsUrgentData ()) { | 
 |             throw new SocketException ("Urgent data not supported"); | 
 |         } | 
 |         getImpl().sendUrgentData (data); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Enable/disable {@link SocketOptions#SO_OOBINLINE SO_OOBINLINE} | 
 |      * (receipt of TCP urgent data) | 
 |      * | 
 |      * By default, this option is disabled and TCP urgent data received on a | 
 |      * socket is silently discarded. If the user wishes to receive urgent data, then | 
 |      * this option must be enabled. When enabled, urgent data is received | 
 |      * inline with normal data. | 
 |      * <p> | 
 |      * Note, only limited support is provided for handling incoming urgent | 
 |      * data. In particular, no notification of incoming urgent data is provided | 
 |      * and there is no capability to distinguish between normal data and urgent | 
 |      * data unless provided by a higher level protocol. | 
 |      * | 
 |      * @param on {@code true} to enable | 
 |      *           {@link SocketOptions#SO_OOBINLINE SO_OOBINLINE}, | 
 |      *           {@code false} to disable. | 
 |      * | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * | 
 |      * @since   1.4 | 
 |      * | 
 |      * @see #getOOBInline() | 
 |      */ | 
 |     public void setOOBInline(boolean on) throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Tests if {@link SocketOptions#SO_OOBINLINE SO_OOBINLINE} is enabled. | 
 |      * | 
 |      * @return a {@code boolean} indicating whether or not | 
 |      *         {@link SocketOptions#SO_OOBINLINE SO_OOBINLINE}is enabled. | 
 |      * | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since   1.4 | 
 |      * @see #setOOBInline(boolean) | 
 |      */ | 
 |     public boolean getOOBInline() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         return ((Boolean) getImpl().getOption(SocketOptions.SO_OOBINLINE)).booleanValue(); | 
 |     } | 
 |  | 
 |     /** | 
 |      *  Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} | 
 |      *  with the specified timeout, in milliseconds. With this option set | 
 |      *  to a non-zero timeout, a read() call on the InputStream associated with | 
 |      *  this Socket will block for only this amount of time.  If the timeout | 
 |      *  expires, a <B>java.net.SocketTimeoutException</B> is raised, though the | 
 |      *  Socket is still valid. The option <B>must</B> be enabled | 
 |      *  prior to entering the blocking operation to have effect. The | 
 |      *  timeout must be {@code > 0}. | 
 |      *  A timeout of zero is interpreted as an infinite timeout. | 
 |      * | 
 |      * @param timeout the specified timeout, in milliseconds. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since   JDK 1.1 | 
 |      * @see #getSoTimeout() | 
 |      */ | 
 |     public synchronized void setSoTimeout(int timeout) throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (timeout < 0) | 
 |           throw new IllegalArgumentException("timeout can't be negative"); | 
 |  | 
 |         getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns setting for {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}. | 
 |      * 0 returns implies that the option is disabled (i.e., timeout of infinity). | 
 |      * | 
 |      * @return the setting for {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * | 
 |      * @since   JDK1.1 | 
 |      * @see #setSoTimeout(int) | 
 |      */ | 
 |     public synchronized int getSoTimeout() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT); | 
 |         /* extra type safety */ | 
 |         if (o instanceof Integer) { | 
 |             return ((Integer) o).intValue(); | 
 |         } else { | 
 |             return 0; | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets the {@link SocketOptions#SO_SNDBUF SO_SNDBUF} option to the | 
 |      * specified value for this {@code Socket}. | 
 |      * The {@link SocketOptions#SO_SNDBUF SO_SNDBUF} option is used by the | 
 |      * platform's networking code as a hint for the size to set the underlying | 
 |      * network I/O buffers. | 
 |      * | 
 |      * <p>Because {@link SocketOptions#SO_SNDBUF SO_SNDBUF} is a hint, | 
 |      * applications that want to verify what size the buffers were set to | 
 |      * should call {@link #getSendBufferSize()}. | 
 |      * | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * | 
 |      * @param size the size to which to set the send buffer | 
 |      * size. This value must be greater than 0. | 
 |      * | 
 |      * @exception IllegalArgumentException if the | 
 |      * value is 0 or is negative. | 
 |      * | 
 |      * @see #getSendBufferSize() | 
 |      * @since 1.2 | 
 |      */ | 
 |     public synchronized void setSendBufferSize(int size) | 
 |     throws SocketException{ | 
 |         if (!(size > 0)) { | 
 |             throw new IllegalArgumentException("negative send size"); | 
 |         } | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Get value of the {@link SocketOptions#SO_SNDBUF SO_SNDBUF} option | 
 |      * for this {@code Socket}, that is the buffer size used by the platform | 
 |      * for output on this {@code Socket}. | 
 |      * @return the value of the {@link SocketOptions#SO_SNDBUF SO_SNDBUF} | 
 |      *         option for this {@code Socket}. | 
 |      * | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * | 
 |      * @see #setSendBufferSize(int) | 
 |      * @since 1.2 | 
 |      */ | 
 |     public synchronized int getSendBufferSize() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         int result = 0; | 
 |         Object o = getImpl().getOption(SocketOptions.SO_SNDBUF); | 
 |         if (o instanceof Integer) { | 
 |             result = ((Integer)o).intValue(); | 
 |         } | 
 |         return result; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets the {@link SocketOptions#SO_RCVBUF SO_RCVBUF} option to the | 
 |      * specified value for this {@code Socket}. The | 
 |      * {@link SocketOptions#SO_RCVBUF SO_RCVBUF} option is | 
 |      * used by the platform's networking code as a hint for the size to set | 
 |      * the underlying network I/O buffers. | 
 |      * | 
 |      * <p>Increasing the receive buffer size can increase the performance of | 
 |      * network I/O for high-volume connection, while decreasing it can | 
 |      * help reduce the backlog of incoming data. | 
 |      * | 
 |      * <p>Because {@link SocketOptions#SO_RCVBUF SO_RCVBUF} is a hint, | 
 |      * applications that want to verify what size the buffers were set to | 
 |      * should call {@link #getReceiveBufferSize()}. | 
 |      * | 
 |      * <p>The value of {@link SocketOptions#SO_RCVBUF SO_RCVBUF} is also used | 
 |      * to set the TCP receive window that is advertized to the remote peer. | 
 |      * Generally, the window size can be modified at any time when a socket is | 
 |      * connected. However, if a receive window larger than 64K is required then | 
 |      * this must be requested <B>before</B> the socket is connected to the | 
 |      * remote peer. There are two cases to be aware of: | 
 |      * <ol> | 
 |      * <li>For sockets accepted from a ServerSocket, this must be done by calling | 
 |      * {@link ServerSocket#setReceiveBufferSize(int)} before the ServerSocket | 
 |      * is bound to a local address.<p></li> | 
 |      * <li>For client sockets, setReceiveBufferSize() must be called before | 
 |      * connecting the socket to its remote peer.</li></ol> | 
 |      * @param size the size to which to set the receive buffer | 
 |      * size. This value must be greater than 0. | 
 |      * | 
 |      * @exception IllegalArgumentException if the value is 0 or is | 
 |      * negative. | 
 |      * | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * | 
 |      * @see #getReceiveBufferSize() | 
 |      * @see ServerSocket#setReceiveBufferSize(int) | 
 |      * @since 1.2 | 
 |      */ | 
 |     public synchronized void setReceiveBufferSize(int size) | 
 |     throws SocketException{ | 
 |         if (size <= 0) { | 
 |             throw new IllegalArgumentException("invalid receive size"); | 
 |         } | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Gets the value of the {@link SocketOptions#SO_RCVBUF SO_RCVBUF} option | 
 |      * for this {@code Socket}, that is the buffer size used by the platform | 
 |      * for input on this {@code Socket}. | 
 |      * | 
 |      * @return the value of the {@link SocketOptions#SO_RCVBUF SO_RCVBUF} | 
 |      *         option for this {@code Socket}. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @see #setReceiveBufferSize(int) | 
 |      * @since 1.2 | 
 |      */ | 
 |     public synchronized int getReceiveBufferSize() | 
 |     throws SocketException{ | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         int result = 0; | 
 |         Object o = getImpl().getOption(SocketOptions.SO_RCVBUF); | 
 |         if (o instanceof Integer) { | 
 |             result = ((Integer)o).intValue(); | 
 |         } | 
 |         return result; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Enable/disable {@link SocketOptions#SO_KEEPALIVE SO_KEEPALIVE}. | 
 |      * | 
 |      * @param on  whether or not to have socket keep alive turned on. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since 1.3 | 
 |      * @see #getKeepAlive() | 
 |      */ | 
 |     public void setKeepAlive(boolean on) throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Tests if {@link SocketOptions#SO_KEEPALIVE SO_KEEPALIVE} is enabled. | 
 |      * | 
 |      * @return a {@code boolean} indicating whether or not | 
 |      *         {@link SocketOptions#SO_KEEPALIVE SO_KEEPALIVE} is enabled. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since   1.3 | 
 |      * @see #setKeepAlive(boolean) | 
 |      */ | 
 |     public boolean getKeepAlive() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         return ((Boolean) getImpl().getOption(SocketOptions.SO_KEEPALIVE)).booleanValue(); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets traffic class or type-of-service octet in the IP | 
 |      * header for packets sent from this Socket. | 
 |      * As the underlying network implementation may ignore this | 
 |      * value applications should consider it a hint. | 
 |      * | 
 |      * <P> The tc <B>must</B> be in the range {@code 0 <= tc <= | 
 |      * 255} or an IllegalArgumentException will be thrown. | 
 |      * <p>Notes: | 
 |      * <p>For Internet Protocol v4 the value consists of an | 
 |      * {@code integer}, the least significant 8 bits of which | 
 |      * represent the value of the TOS octet in IP packets sent by | 
 |      * the socket. | 
 |      * RFC 1349 defines the TOS values as follows: | 
 |      * | 
 |      * <UL> | 
 |      * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI> | 
 |      * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI> | 
 |      * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI> | 
 |      * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI> | 
 |      * </UL> | 
 |      * The last low order bit is always ignored as this | 
 |      * corresponds to the MBZ (must be zero) bit. | 
 |      * <p> | 
 |      * Setting bits in the precedence field may result in a | 
 |      * SocketException indicating that the operation is not | 
 |      * permitted. | 
 |      * <p> | 
 |      * As RFC 1122 section 4.2.4.2 indicates, a compliant TCP | 
 |      * implementation should, but is not required to, let application | 
 |      * change the TOS field during the lifetime of a connection. | 
 |      * So whether the type-of-service field can be changed after the | 
 |      * TCP connection has been established depends on the implementation | 
 |      * in the underlying platform. Applications should not assume that | 
 |      * they can change the TOS field after the connection. | 
 |      * <p> | 
 |      * For Internet Protocol v6 {@code tc} is the value that | 
 |      * would be placed into the sin6_flowinfo field of the IP header. | 
 |      * | 
 |      * @param tc        an {@code int} value for the bitset. | 
 |      * @throws SocketException if there is an error setting the | 
 |      * traffic class or type-of-service | 
 |      * @since 1.4 | 
 |      * @see #getTrafficClass | 
 |      * @see SocketOptions#IP_TOS | 
 |      */ | 
 |     public void setTrafficClass(int tc) throws SocketException { | 
 |         if (tc < 0 || tc > 255) | 
 |             throw new IllegalArgumentException("tc is not in range 0 -- 255"); | 
 |  | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         try { | 
 |             getImpl().setOption(SocketOptions.IP_TOS, tc); | 
 |         } catch (SocketException se) { | 
 |             // not supported if socket already connected | 
 |             // Solaris returns error in such cases | 
 |             if(!isConnected()) | 
 |                 throw se; | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Gets traffic class or type-of-service in the IP header | 
 |      * for packets sent from this Socket | 
 |      * <p> | 
 |      * As the underlying network implementation may ignore the | 
 |      * traffic class or type-of-service set using {@link #setTrafficClass(int)} | 
 |      * this method may return a different value than was previously | 
 |      * set using the {@link #setTrafficClass(int)} method on this Socket. | 
 |      * | 
 |      * @return the traffic class or type-of-service already set | 
 |      * @throws SocketException if there is an error obtaining the | 
 |      * traffic class or type-of-service value. | 
 |      * @since 1.4 | 
 |      * @see #setTrafficClass(int) | 
 |      * @see SocketOptions#IP_TOS | 
 |      */ | 
 |     public int getTrafficClass() throws SocketException { | 
 |         // Android-changed: throw SocketException if the socket is already closed. http://b/31818400 | 
 |         if (isClosed()) { | 
 |             throw new SocketException("Socket is closed"); | 
 |         } | 
 |  | 
 |         return ((Integer) (getImpl().getOption(SocketOptions.IP_TOS))).intValue(); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Enable/disable the {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} | 
 |      * socket option. | 
 |      * <p> | 
 |      * When a TCP connection is closed the connection may remain | 
 |      * in a timeout state for a period of time after the connection | 
 |      * is closed (typically known as the {@code TIME_WAIT} state | 
 |      * or {@code 2MSL} wait state). | 
 |      * For applications using a well known socket address or port | 
 |      * it may not be possible to bind a socket to the required | 
 |      * {@code SocketAddress} if there is a connection in the | 
 |      * timeout state involving the socket address or port. | 
 |      * <p> | 
 |      * Enabling {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} | 
 |      * prior to binding the socket using {@link #bind(SocketAddress)} allows | 
 |      * the socket to be bound even though a previous connection is in a timeout | 
 |      * state. | 
 |      * <p> | 
 |      * When a {@code Socket} is created the initial setting | 
 |      * of {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} is disabled. | 
 |      * <p> | 
 |      * The behaviour when {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} is | 
 |      * enabled or disabled after a socket is bound (See {@link #isBound()}) | 
 |      * is not defined. | 
 |      * | 
 |      * @param on  whether to enable or disable the socket option | 
 |      * @exception SocketException if an error occurs enabling or | 
 |      *            disabling the {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} | 
 |      *            socket option, or the socket is closed. | 
 |      * @since 1.4 | 
 |      * @see #getReuseAddress() | 
 |      * @see #bind(SocketAddress) | 
 |      * @see #isClosed() | 
 |      * @see #isBound() | 
 |      */ | 
 |     public void setReuseAddress(boolean on) throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Tests if {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} is enabled. | 
 |      * | 
 |      * @return a {@code boolean} indicating whether or not | 
 |      *         {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} is enabled. | 
 |      * @exception SocketException if there is an error | 
 |      * in the underlying protocol, such as a TCP error. | 
 |      * @since   1.4 | 
 |      * @see #setReuseAddress(boolean) | 
 |      */ | 
 |     public boolean getReuseAddress() throws SocketException { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         return ((Boolean) (getImpl().getOption(SocketOptions.SO_REUSEADDR))).booleanValue(); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Closes this socket. | 
 |      * <p> | 
 |      * Any thread currently blocked in an I/O operation upon this socket | 
 |      * will throw a {@link SocketException}. | 
 |      * <p> | 
 |      * Once a socket has been closed, it is not available for further networking | 
 |      * use (i.e. can't be reconnected or rebound). A new socket needs to be | 
 |      * created. | 
 |      * | 
 |      * <p> Closing this socket will also close the socket's | 
 |      * {@link java.io.InputStream InputStream} and | 
 |      * {@link java.io.OutputStream OutputStream}. | 
 |      * | 
 |      * <p> If this socket has an associated channel then the channel is closed | 
 |      * as well. | 
 |      * | 
 |      * @exception  IOException  if an I/O error occurs when closing this socket. | 
 |      * @revised 1.4 | 
 |      * @spec JSR-51 | 
 |      * @see #isClosed | 
 |      */ | 
 |     public synchronized void close() throws IOException { | 
 |         synchronized(closeLock) { | 
 |             if (isClosed()) | 
 |                 return; | 
 |             if (created) | 
 |                 impl.close(); | 
 |             closed = true; | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Places the input stream for this socket at "end of stream". | 
 |      * Any data sent to the input stream side of the socket is acknowledged | 
 |      * and then silently discarded. | 
 |      * <p> | 
 |      * If you read from a socket input stream after invoking this method on the | 
 |      * socket, the stream's {@code available} method will return 0, and its | 
 |      * {@code read} methods will return {@code -1} (end of stream). | 
 |      * | 
 |      * @exception IOException if an I/O error occurs when shutting down this | 
 |      * socket. | 
 |      * | 
 |      * @since 1.3 | 
 |      * @see java.net.Socket#shutdownOutput() | 
 |      * @see java.net.Socket#close() | 
 |      * @see java.net.Socket#setSoLinger(boolean, int) | 
 |      * @see #isInputShutdown | 
 |      */ | 
 |     public void shutdownInput() throws IOException | 
 |     { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (!isConnected()) | 
 |             throw new SocketException("Socket is not connected"); | 
 |         if (isInputShutdown()) | 
 |             throw new SocketException("Socket input is already shutdown"); | 
 |         getImpl().shutdownInput(); | 
 |         shutIn = true; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Disables the output stream for this socket. | 
 |      * For a TCP socket, any previously written data will be sent | 
 |      * followed by TCP's normal connection termination sequence. | 
 |      * | 
 |      * If you write to a socket output stream after invoking | 
 |      * shutdownOutput() on the socket, the stream will throw | 
 |      * an IOException. | 
 |      * | 
 |      * @exception IOException if an I/O error occurs when shutting down this | 
 |      * socket. | 
 |      * | 
 |      * @since 1.3 | 
 |      * @see java.net.Socket#shutdownInput() | 
 |      * @see java.net.Socket#close() | 
 |      * @see java.net.Socket#setSoLinger(boolean, int) | 
 |      * @see #isOutputShutdown | 
 |      */ | 
 |     public void shutdownOutput() throws IOException | 
 |     { | 
 |         if (isClosed()) | 
 |             throw new SocketException("Socket is closed"); | 
 |         if (!isConnected()) | 
 |             throw new SocketException("Socket is not connected"); | 
 |         if (isOutputShutdown()) | 
 |             throw new SocketException("Socket output is already shutdown"); | 
 |         getImpl().shutdownOutput(); | 
 |         shutOut = true; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Converts this socket to a {@code String}. | 
 |      * | 
 |      * @return  a string representation of this socket. | 
 |      */ | 
 |     public String toString() { | 
 |         try { | 
 |             // Android-changed: change localport to localPort, and addr to address. | 
 |             if (isConnected()) | 
 |                 return "Socket[address=" + getImpl().getInetAddress() + | 
 |                     ",port=" + getImpl().getPort() + | 
 |                     ",localPort=" + getImpl().getLocalPort() + "]"; | 
 |         } catch (SocketException e) { | 
 |         } | 
 |         return "Socket[unconnected]"; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the connection state of the socket. | 
 |      * <p> | 
 |      * Note: Closing a socket doesn't clear its connection state, which means | 
 |      * this method will return {@code true} for a closed socket | 
 |      * (see {@link #isClosed()}) if it was successfuly connected prior | 
 |      * to being closed. | 
 |      * | 
 |      * @return true if the socket was successfuly connected to a server | 
 |      * @since 1.4 | 
 |      */ | 
 |     public boolean isConnected() { | 
 |         // Before 1.3 Sockets were always connected during creation | 
 |         return connected || oldImpl; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the binding state of the socket. | 
 |      * <p> | 
 |      * Note: Closing a socket doesn't clear its binding state, which means | 
 |      * this method will return {@code true} for a closed socket | 
 |      * (see {@link #isClosed()}) if it was successfuly bound prior | 
 |      * to being closed. | 
 |      * | 
 |      * @return true if the socket was successfuly bound to an address | 
 |      * @since 1.4 | 
 |      * @see #bind | 
 |      */ | 
 |     public boolean isBound() { | 
 |         // Before 1.3 Sockets were always bound during creation | 
 |         return bound || oldImpl; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the closed state of the socket. | 
 |      * | 
 |      * @return true if the socket has been closed | 
 |      * @since 1.4 | 
 |      * @see #close | 
 |      */ | 
 |     public boolean isClosed() { | 
 |         synchronized(closeLock) { | 
 |             return closed; | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns whether the read-half of the socket connection is closed. | 
 |      * | 
 |      * @return true if the input of the socket has been shutdown | 
 |      * @since 1.4 | 
 |      * @see #shutdownInput | 
 |      */ | 
 |     public boolean isInputShutdown() { | 
 |         return shutIn; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns whether the write-half of the socket connection is closed. | 
 |      * | 
 |      * @return true if the output of the socket has been shutdown | 
 |      * @since 1.4 | 
 |      * @see #shutdownOutput | 
 |      */ | 
 |     public boolean isOutputShutdown() { | 
 |         return shutOut; | 
 |     } | 
 |  | 
 |     /** | 
 |      * The factory for all client sockets. | 
 |      */ | 
 |     private static SocketImplFactory factory = null; | 
 |  | 
 |     /** | 
 |      * Sets the client socket implementation factory for the | 
 |      * application. The factory can be specified only once. | 
 |      * <p> | 
 |      * When an application creates a new client socket, the socket | 
 |      * implementation factory's {@code createSocketImpl} method is | 
 |      * called to create the actual socket implementation. | 
 |      * <p> | 
 |      * Passing {@code null} to the method is a no-op unless the factory | 
 |      * was already set. | 
 |      * <p>If there is a security manager, this method first calls | 
 |      * the security manager's {@code checkSetFactory} method | 
 |      * to ensure the operation is allowed. | 
 |      * This could result in a SecurityException. | 
 |      * | 
 |      * @param      fac   the desired factory. | 
 |      * @exception  IOException  if an I/O error occurs when setting the | 
 |      *               socket factory. | 
 |      * @exception  SocketException  if the factory is already defined. | 
 |      * @exception  SecurityException  if a security manager exists and its | 
 |      *             {@code checkSetFactory} method doesn't allow the operation. | 
 |      * @see        java.net.SocketImplFactory#createSocketImpl() | 
 |      * @see        SecurityManager#checkSetFactory | 
 |      */ | 
 |     public static synchronized void setSocketImplFactory(SocketImplFactory fac) | 
 |         throws IOException | 
 |     { | 
 |         if (factory != null) { | 
 |             throw new SocketException("factory already defined"); | 
 |         } | 
 |         SecurityManager security = System.getSecurityManager(); | 
 |         if (security != null) { | 
 |             security.checkSetFactory(); | 
 |         } | 
 |         factory = fac; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets performance preferences for this socket. | 
 |      * | 
 |      * <p> Sockets use the TCP/IP protocol by default.  Some implementations | 
 |      * may offer alternative protocols which have different performance | 
 |      * characteristics than TCP/IP.  This method allows the application to | 
 |      * express its own preferences as to how these tradeoffs should be made | 
 |      * when the implementation chooses from the available protocols. | 
 |      * | 
 |      * <p> Performance preferences are described by three integers | 
 |      * whose values indicate the relative importance of short connection time, | 
 |      * low latency, and high bandwidth.  The absolute values of the integers | 
 |      * are irrelevant; in order to choose a protocol the values are simply | 
 |      * compared, with larger values indicating stronger preferences. Negative | 
 |      * values represent a lower priority than positive values. If the | 
 |      * application prefers short connection time over both low latency and high | 
 |      * bandwidth, for example, then it could invoke this method with the values | 
 |      * {@code (1, 0, 0)}.  If the application prefers high bandwidth above low | 
 |      * latency, and low latency above short connection time, then it could | 
 |      * invoke this method with the values {@code (0, 1, 2)}. | 
 |      * | 
 |      * <p> Invoking this method after this socket has been connected | 
 |      * will have no effect. | 
 |      * | 
 |      * @param  connectionTime | 
 |      *         An {@code int} expressing the relative importance of a short | 
 |      *         connection time | 
 |      * | 
 |      * @param  latency | 
 |      *         An {@code int} expressing the relative importance of low | 
 |      *         latency | 
 |      * | 
 |      * @param  bandwidth | 
 |      *         An {@code int} expressing the relative importance of high | 
 |      *         bandwidth | 
 |      * | 
 |      * @since 1.5 | 
 |      */ | 
 |     public void setPerformancePreferences(int connectionTime, | 
 |                                           int latency, | 
 |                                           int bandwidth) | 
 |     { | 
 |         /* Not implemented yet */ | 
 |     } | 
 |  | 
 |     // Android-added: getFileDescriptor$() method for testing and internal use. | 
 |     /** | 
 |      * Gets socket's underlying {@link FileDescriptor}. | 
 |      * | 
 |      * @hide internal use only | 
 |      * | 
 |      * @return socket's underlying {@link FileDescriptor}. | 
 |      */ | 
 |     public FileDescriptor getFileDescriptor$() { | 
 |         return impl.getFileDescriptor(); | 
 |     } | 
 | } |