|  | /* | 
|  | * 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(); | 
|  | } | 
|  | } |