1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.net;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughesimport java.io.FileDescriptor;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SocketChannel;
250b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Provides a client-side TCP socket.
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class Socket {
318cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private static SocketImplFactory factory;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
338cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    final SocketImpl impl;
348cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private final Proxy proxy;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
360371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    volatile boolean isCreated = false;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isBound = false;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isConnected = false;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isClosed = false;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isInputShutdown = false;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isOutputShutdown = false;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
438cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private InetAddress localAddress = Inet4Address.ANY;
448cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
455e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes    private final Object connectLock = new Object();
461f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new unconnected socket. When a SocketImplFactory is defined it
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * creates the internal socket implementation, otherwise the default socket
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * implementation will be used for this socket.
51f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see SocketImplFactory
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see SocketImpl
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Socket() {
568cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
578cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.proxy = null;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new unconnected socket using the given proxy type. When a
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code SocketImplFactory} is defined it creates the internal socket
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * implementation, otherwise the default socket implementation will be used
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for this socket.
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Example that will create a socket connection through a {@code SOCKS}
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * proxy server: <br>
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * InetSocketAddress("test.domain.org", 2130)));}
70f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param proxy
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specified proxy for this socket.
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the argument {@code proxy} is {@code null} or of an
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             invalid type.
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see SocketImplFactory
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see SocketImpl
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Socket(Proxy proxy) {
80b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (proxy == null || proxy.type() == Proxy.Type.HTTP) {
81ae06196267319eef727892d9e13bdecea3482e34Elliott Hughes            throw new IllegalArgumentException("Invalid proxy: " + proxy);
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
83ae06196267319eef727892d9e13bdecea3482e34Elliott Hughes        this.proxy = proxy;
848cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(proxy);
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
871f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti    /**
881f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * Tries to connect a socket to all IP addresses of the given hostname.
891f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *
901f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @param dstName
911f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *            the target host name or IP address to connect to.
921f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @param dstPort
931f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *            the port on the target host to connect to.
941f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @param localAddress
951f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *            the address on the local host to bind to.
961f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @param localPort
971f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *            the port on the local host to bind to.
981f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @param streaming
991f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *            if {@code true} a streaming socket is returned, a datagram
1001f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *            socket otherwise.
1011f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @throws UnknownHostException
1021f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *             if the host name could not be resolved into an IP address.
1031f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * @throws IOException
1041f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     *             if an error occurs while creating the socket.
1051f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     */
1061f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti    private void tryAllAddresses(String dstName, int dstPort, InetAddress
1071f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti            localAddress, int localPort, boolean streaming) throws IOException {
1081f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        InetAddress[] dstAddresses = InetAddress.getAllByName(dstName);
1091f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        // Loop through all the destination addresses except the last, trying to
1101f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        // connect to each one and ignoring errors. There must be at least one
1111f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        // address, or getAllByName would have thrown UnknownHostException.
1121f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        InetAddress dstAddress;
1131f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        for (int i = 0; i < dstAddresses.length - 1; i++) {
1141f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti            dstAddress = dstAddresses[i];
1151f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti            try {
1161f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti                checkDestination(dstAddress, dstPort);
1178cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
1181f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti                return;
119ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes            } catch (IOException ex) {
1201f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti            }
1211f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        }
1221f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti
1231f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        // Now try to connect to the last address in the array, handing back to
1241f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        // the caller any exceptions that are thrown.
1251f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        dstAddress = dstAddresses[dstAddresses.length - 1];
1261f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        checkDestination(dstAddress, dstPort);
1271f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
1281f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti    }
1291f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming socket connected to the target host specified by
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the parameters {@code dstName} and {@code dstPort}. The socket is bound
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to any available port on the local host.
134ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     *
135ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * <p>This implementation tries each IP address for the given hostname (in
136ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
137ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * until it either connects successfully or it exhausts the set.
138f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstName
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host name or IP address to connect to.
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the host name could not be resolved into an IP address.
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1488cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(String dstName, int dstPort) throws UnknownHostException, IOException {
1491f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        this(dstName, dstPort, null, 0);
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming socket connected to the target host specified by
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the socket is bound to the given address {@code localAddress} on port
156ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * {@code localPort}. If {@code host} is {@code null} a loopback address is used to connect to.
157f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
158ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * <p>This implementation tries each IP address for the given hostname (in
159ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
160ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * until it either connects successfully or it exhausts the set.
161f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstName
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host name or IP address to connect to.
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddress
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address on the local host to bind to.
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localPort
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the local host to bind to.
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the host name could not be resolved into an IP address.
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1758cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException {
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
1771f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        tryAllAddresses(dstName, dstPort, localAddress, localPort, true);
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming or datagram socket connected to the target host
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified by the parameters {@code hostName} and {@code port}. The socket
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is bound to any available port on the local host.
184ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     *
185ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * <p>This implementation tries each IP address for the given hostname (in
186ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
187ae394a866dd86df8819b652dfe00b3d2c7ee204cElliott Hughes     * until it either connects successfully or it exhausts the set.
188f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param hostName
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host name or IP address to connect to.
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param port
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param streaming
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if {@code true} a streaming socket is returned, a datagram
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            socket otherwise.
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the host name could not be resolved into an IP address.
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @deprecated Use {@code Socket(String, int)} instead of this for streaming
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             sockets or an appropriate constructor of {@code
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             DatagramSocket} for UDP transport.
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Deprecated
2058cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(String hostName, int port, boolean streaming) throws IOException {
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
2071f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        tryAllAddresses(hostName, port, null, 0, streaming);
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming socket connected to the target host specified by
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the parameters {@code dstAddress} and {@code dstPort}. The socket is
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * bound to any available port on the local host.
214f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstAddress
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host address to connect to.
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Socket(InetAddress dstAddress, int dstPort) throws IOException {
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(dstAddress, dstPort);
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startupSocket(dstAddress, dstPort, null, 0, true);
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming socket connected to the target host specified by
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the parameters {@code dstAddress} and {@code dstPort}. On the local
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * endpoint the socket is bound to the given address {@code localAddress} on
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * port {@code localPort}.
233f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstAddress
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host address to connect to.
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddress
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address on the local host to bind to.
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localPort
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the local host to bind to.
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Socket(InetAddress dstAddress, int dstPort,
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetAddress localAddress, int localPort) throws IOException {
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(dstAddress, dstPort);
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startupSocket(dstAddress, dstPort, localAddress, localPort, true);
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming or datagram socket connected to the target host
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified by the parameters {@code addr} and {@code port}. The socket is
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * bound to any available port on the local host.
256f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param addr
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the Internet address to connect to.
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param port
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param streaming
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if {@code true} a streaming socket is returned, a datagram
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            socket otherwise.
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             streaming sockets or an appropriate constructor of {@code
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             DatagramSocket} for UDP transport.
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Deprecated
2718cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(InetAddress addr, int port, boolean streaming) throws IOException {
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(addr, port);
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startupSocket(addr, port, null, 0, streaming);
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates an unconnected socket with the given socket implementation.
279f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
2808cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * @param impl
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the socket implementation to be used.
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2858cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    protected Socket(SocketImpl impl) throws SocketException {
2868cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.impl = impl;
2878cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.proxy = null;
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks whether the connection destination satisfies the security policy
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and the validity of the port range.
293f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param destAddr
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the destination host address.
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the destination host.
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2998cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private void checkDestination(InetAddress destAddr, int dstPort) {
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dstPort < 0 || dstPort > 65535) {
301b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Port out of range: " + dstPort);
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the socket. It is not possible to reconnect or rebind to this
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * socket thereafter which means a new socket instance has to be created.
308f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing the socket.
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void close() throws IOException {
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isClosed = true;
3148cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        // RI compatibility: the RI returns the any address (but the original local port) after close.
3158cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        localAddress = Inet4Address.ANY;
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.close();
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
320a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the IP address of the target host this socket is connected to, or null if this
321a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * socket is not yet connected.
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InetAddress getInetAddress() {
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getInetAddress();
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
331a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns an input stream to read data from this socket.
332f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the byte-oriented input stream.
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the input stream or the
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket is in an invalid state.
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InputStream getInputStream() throws IOException {
3390371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isInputShutdown()) {
341b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket input is shutdown");
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getInputStream();
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
347a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting.
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getKeepAlive() throws SocketException {
3500371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
3518cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE);
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
3558cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * Returns the local IP address this socket is bound to, or {@code InetAddress.ANY} if
3568cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * the socket is unbound.
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InetAddress getLocalAddress() {
3598cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        return localAddress;
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
3638cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * Returns the local port this socket is bound to, or -1 if the socket is unbound.
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getLocalPort() {
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isBound()) {
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getLocalPort();
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
373a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns an output stream to write data into this socket.
374f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the byte-oriented output stream.
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the output stream or the
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket is in an invalid state.
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public OutputStream getOutputStream() throws IOException {
3810371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isOutputShutdown()) {
383b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket output is shutdown");
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getOutputStream();
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
389a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the port number of the target host this socket is connected to, or 0 if this socket
390a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * is not yet connected.
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getPort() {
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getPort();
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
400a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1
401a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * for no linger (i.e. {@code close} will return immediately).
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getSoLinger() throws SocketException {
4040371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4050371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
4060371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        Object value = impl.getOption(SocketOptions.SO_LINGER);
4070371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        if (value instanceof Integer) {
4080371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            return (Integer) value;
4090371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        } else {
4100371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            return -1;
4110371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        }
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
415a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized int getReceiveBufferSize() throws SocketException {
4180371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4190371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.SO_RCVBUF);
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
423a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized int getSendBufferSize() throws SocketException {
4260371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4270371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.SO_SNDBUF);
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
431a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}.
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized int getSoTimeout() throws SocketException {
4340371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4350371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT);
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
439a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting.
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getTcpNoDelay() throws SocketException {
4420371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4430371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY);
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
447a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option.
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
4490371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    public void setKeepAlive(boolean keepAlive) throws SocketException {
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (impl != null) {
4510371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            checkOpenAndCreate(true);
4520371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive));
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the internal factory for creating socket implementations. This may
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only be executed once during the lifetime of the application.
459f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param fac
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the socket implementation factory to be set.
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the factory has been already set.
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static synchronized void setSocketImplFactory(SocketImplFactory fac)
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IOException {
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (factory != null) {
468b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Factory already set");
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        factory = fac;
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
474a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setSendBufferSize(int size) throws SocketException {
4770371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size < 1) {
479b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size < 1");
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
485a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_SNDBUF receive buffer size}.
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
487b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    public synchronized void setReceiveBufferSize(int size) throws SocketException {
4880371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size < 1) {
490b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size < 1");
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
496a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds.
497a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * If {@code on} is false, {@code timeout} is irrelevant.
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setSoLinger(boolean on, int timeout) throws SocketException {
5000371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
5010371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (on && timeout < 0) {
503b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("timeout < 0");
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (on) {
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout));
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE);
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
513a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.
514a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Use 0 for no timeout.
515a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * To take effect, this option must be set before the blocking method was called.
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setSoTimeout(int timeout) throws SocketException {
5180371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeout < 0) {
520b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("timeout < 0");
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
526a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#TCP_NODELAY} option.
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setTcpNoDelay(boolean on) throws SocketException {
5290371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a stream socket, binds it to the nominated local address/port,
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * then connects it to the nominated destination address/port.
536f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstAddress
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the destination host address.
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the destination host.
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddress
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address on the local machine to bind.
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localPort
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the local machine to bind.
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             thrown if an error occurs during the bind or connect
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             operations.
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
5490371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    private void startupSocket(InetAddress dstAddress, int dstPort,
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetAddress localAddress, int localPort, boolean streaming)
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IOException {
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localPort < 0 || localPort > 65535) {
554b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Local port out of range: " + localPort);
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5578cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetAddress addr = localAddress == null ? Inet4Address.ANY : localAddress;
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            impl.create(streaming);
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCreated = true;
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
5620917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes                if (!streaming || !usingSocks()) {
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    impl.bind(addr, localPort);
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isBound = true;
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.connect(dstAddress, dstPort);
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isConnected = true;
5688cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                cacheLocalAddress();
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.close();
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5760917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes    private boolean usingSocks() {
5770917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes        return proxy != null && proxy.type() == Proxy.Type.SOCKS;
5780917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes    }
5790917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a {@code String} containing a concise, human-readable description of the
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * socket.
583f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the textual representation of this socket.
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
589f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            return "Socket[unconnected]";
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.toString();
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the input stream of this socket. Any further data sent to this
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * socket will be discarded. Reading from this socket after this method has
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * been called will return the value {@code EOF}.
598f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing the socket input stream.
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input stream is already closed.
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownInput() throws IOException {
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isInputShutdown()) {
606b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket input is shutdown");
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6080371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.shutdownInput();
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isInputShutdown = true;
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the output stream of this socket. All buffered data will be sent
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * followed by the termination sequence. Writing to the closed output stream
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * will cause an {@code IOException}.
617f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing the socket output stream.
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the output stream is already closed.
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownOutput() throws IOException {
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isOutputShutdown()) {
625b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket output is shutdown");
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6270371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.shutdownOutput();
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isOutputShutdown = true;
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks whether the socket is closed, and throws an exception. Otherwise
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * creates the underlying SocketImpl.
635f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is closed.
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
6390371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    private void checkOpenAndCreate(boolean create) throws SocketException {
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isClosed()) {
641b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket is closed");
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!create) {
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isConnected()) {
645b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new SocketException("Socket is not connected");
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // a connected socket must be created
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * return directly to fix a possible bug, if !create, should return
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * here
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isCreated) {
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isCreated) {
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.create(true);
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (SocketException e) {
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new SocketException(e.toString());
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCreated = true;
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
674a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the local address and port of this socket as a SocketAddress or
675a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * null if the socket is unbound. This is useful on multihomed
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * hosts.
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketAddress getLocalSocketAddress() {
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isBound()) {
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new InetSocketAddress(getLocalAddress(), getLocalPort());
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
686a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the remote address and port of this socket as a {@code
687a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * SocketAddress} or null if the socket is not connected.
688f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the remote socket address and port.
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketAddress getRemoteSocketAddress() {
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new InetSocketAddress(getInetAddress(), getPort());
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this socket is bound to a local address and port.
700f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the socket is bound to a local address, {@code
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         false} otherwise.
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isBound() {
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isBound;
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this socket is connected to a remote host.
710f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the socket is connected, {@code false} otherwise.
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isConnected() {
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isConnected;
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this socket is closed.
719f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the socket is closed, {@code false} otherwise.
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isClosed() {
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isClosed;
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Binds this socket to the given local host address and port specified by
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code null}, this socket will be bound to an available local address on
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * any free port.
731f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddr
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specific address and port on the local machine to bind to.
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the given SocketAddress is invalid or not supported.
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is already bound or an error occurs while
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             binding.
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void bind(SocketAddress localAddr) throws IOException {
7410371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isBound()) {
743b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new BindException("Socket is already bound");
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int port = 0;
747051128862ae7c5c031b8ddb763848ed264a63746Lorenzo Colitti        InetAddress addr = Inet4Address.ANY;
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localAddr != null) {
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!(localAddr instanceof InetSocketAddress)) {
750b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IllegalArgumentException("Local address not an InetSocketAddress: " +
751b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                        localAddr.getClass());
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((addr = inetAddr.getAddress()) == null) {
755c61ad82613eb264cbf93e91519b0c061d11b3c2dElliott Hughes                throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            port = inetAddr.getPort();
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.bind(addr, port);
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isBound = true;
7648cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                cacheLocalAddress();
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.close();
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Connects this socket to the given remote host address and port specified
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * by the SocketAddress {@code remoteAddr}.
775f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param remoteAddr
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address and port of the remote host to connect to.
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the given SocketAddress is invalid or not supported.
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is already connected or an error occurs while
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             connecting.
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void connect(SocketAddress remoteAddr) throws IOException {
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connect(remoteAddr, 0);
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Connects this socket to the given remote host address and port specified
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * by the SocketAddress {@code remoteAddr} with the specified timeout. The
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connecting method will block until the connection is established or an
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * error occurred.
793f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param remoteAddr
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address and port of the remote host to connect to.
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timeout
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timeout value in milliseconds or {@code 0} for an infinite
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            timeout.
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the given SocketAddress is invalid or not supported or the
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             timeout value is negative.
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is already connected or an error occurs while
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             connecting.
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8068cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
8070371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeout < 0) {
809b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("timeout < 0");
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isConnected()) {
812b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Already connected");
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (remoteAddr == null) {
815b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("remoteAddr == null");
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!(remoteAddr instanceof InetSocketAddress)) {
819b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Remote address not an InetSocketAddress: " +
820b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                    remoteAddr.getClass());
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        InetAddress addr;
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((addr = inetAddr.getAddress()) == null) {
825c61ad82613eb264cbf93e91519b0c061d11b3c2dElliott Hughes            throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int port = inetAddr.getPort();
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(addr, port);
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (connectLock) {
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isBound()) {
8338cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                    // socket already created at this point by earlier call or
8340371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                    // checkOpenAndCreate this caused us to lose socket
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // options on create
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // impl.create(true);
8370917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes                    if (!usingSocks()) {
838051128862ae7c5c031b8ddb763848ed264a63746Lorenzo Colitti                        impl.bind(Inet4Address.ANY, 0);
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    isBound = true;
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.connect(remoteAddr, timeout);
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isConnected = true;
8448cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                cacheLocalAddress();
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.close();
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether the incoming channel of the socket has already been
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * closed.
855f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if reading from this socket is not possible anymore,
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} otherwise.
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isInputShutdown() {
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isInputShutdown;
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
864f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Returns whether the outgoing channel of the socket has already been
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * closed.
866f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if writing to this socket is not possible anymore,
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} otherwise.
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isOutputShutdown() {
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isOutputShutdown;
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
875a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option.
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setReuseAddress(boolean reuse) throws SocketException {
8780371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
8790371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse));
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
883a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting.
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getReuseAddress() throws SocketException {
8860371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
8870371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR);
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
891a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option.
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOOBInline(boolean oobinline) throws SocketException {
8940371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
8950371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline));
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
899a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting.
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getOOBInline() throws SocketException {
9020371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
9030371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE);
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
907a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket.
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setTrafficClass(int value) throws SocketException {
9100371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value < 0 || value > 255) {
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
9182cd82d7111f68ff63145ef7c393bf1479ff06223Elliott Hughes     * Returns this socket's {@see SocketOptions#IP_TOS} setting.
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getTrafficClass() throws SocketException {
9210371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
9220371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.IP_TOS);
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sends the given single byte data which is represented by the lowest octet
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of {@code value} as "TCP urgent data".
928f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the byte of urgent data to be sent.
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while sending urgent data.
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void sendUrgentData(int value) throws IOException {
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.sendUrgentData(value);
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the appropriate flags for a socket created by {@code
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ServerSocket.accept()}.
941f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see ServerSocket#implAccept
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void accepted() {
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCreated = isBound = isConnected = true;
9468cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        cacheLocalAddress();
9478cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    }
9488cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
9498cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private void cacheLocalAddress() {
9500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes        this.localAddress = IoBridge.getSocketLocalAddress(impl.fd);
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
9540d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * Returns this socket's {@code SocketChannel}, if one exists. A channel is
9550d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * available only if this socket wraps a channel. (That is, you can go from a
9560d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.)
9570d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * In practice, this means that the socket must have been created by
9580d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * {@link java.nio.channels.ServerSocketChannel#accept} or
9590d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * {@link java.nio.channels.SocketChannel#open}.
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketChannel getChannel() {
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
966dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughes     * @hide internal use only
967dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughes     */
9683267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey    public FileDescriptor getFileDescriptor$() {
969dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughes        return impl.fd;
970dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughes    }
971dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughes
972dc33f53f38600943c84146320c748e3c46fd2e7bElliott Hughes    /**
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets performance preferences for connectionTime, latency and bandwidth.
974a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     *
975a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * <p>This method does currently nothing.
976f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param connectionTime
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value representing the importance of a short connecting
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            time.
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param latency
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value representing the importance of low latency.
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bandwidth
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value representing the importance of high bandwidth.
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9850371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Our socket implementation only provide one protocol: TCP/IP, so
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // we do nothing for this method
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
990