Socket.java revision ae06196267319eef727892d9e13bdecea3482e34
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
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SocketChannel;
24f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonimport org.apache.harmony.luni.net.PlainSocketImpl;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.platform.Platform;
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.
1341f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * <p><strong>Implementation note:</strong> this implementation tries each
1351f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * IP address for the given hostname until it either connects successfully
1361f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * or it exhausts the set. It will try both IPv4 and IPv6 addresses in the
1374c5cbf2953ada194c4dc9d7b387615b1c6fe3e63Elliott Hughes     * order specified by the system property {@code "java.net.preferIPv6Addresses"}.
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
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code localPort}.
157f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If {@code host} is {@code null} a loopback address is used to connect to.
1591f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * <p><strong>Implementation note:</strong> this implementation tries each
1601f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * IP address for the given hostname until it either connects successfully
1611f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * or it exhausts the set. It will try both IPv4 and IPv6 addresses in the
1624c5cbf2953ada194c4dc9d7b387615b1c6fe3e63Elliott Hughes     * order specified by the system property {@code "java.net.preferIPv6Addresses"}.
163f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstName
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host name or IP address to connect to.
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddress
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address on the local host to bind to.
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localPort
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the local host to bind to.
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the host name could not be resolved into an IP address.
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1778cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException {
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
1791f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        tryAllAddresses(dstName, dstPort, localAddress, localPort, true);
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming or datagram socket connected to the target host
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified by the parameters {@code hostName} and {@code port}. The socket
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is bound to any available port on the local host.
1861f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * <p><strong>Implementation note:</strong> this implementation tries each
1871f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * IP address for the given hostname until it either connects successfully
1881f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti     * or it exhausts the set. It will try both IPv4 and IPv6 addresses in the
1894c5cbf2953ada194c4dc9d7b387615b1c6fe3e63Elliott Hughes     * order specified by the system property {@code "java.net.preferIPv6Addresses"}.
190f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param hostName
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host name or IP address to connect to.
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param port
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param streaming
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if {@code true} a streaming socket is returned, a datagram
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            socket otherwise.
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the host name could not be resolved into an IP address.
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @deprecated Use {@code Socket(String, int)} instead of this for streaming
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             sockets or an appropriate constructor of {@code
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             DatagramSocket} for UDP transport.
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Deprecated
2078cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(String hostName, int port, boolean streaming) throws IOException {
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
2091f2d2815dc31bf3c464eec6d1de7e428d7f1dcf6Lorenzo Colitti        tryAllAddresses(hostName, port, null, 0, streaming);
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming socket connected to the target host specified by
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the parameters {@code dstAddress} and {@code dstPort}. The socket is
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * bound to any available port on the local host.
216f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstAddress
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host address to connect to.
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Socket(InetAddress dstAddress, int dstPort) throws IOException {
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(dstAddress, dstPort);
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startupSocket(dstAddress, dstPort, null, 0, true);
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming socket connected to the target host specified by
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the parameters {@code dstAddress} and {@code dstPort}. On the local
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * endpoint the socket is bound to the given address {@code localAddress} on
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * port {@code localPort}.
235f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstAddress
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the target host address to connect to.
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddress
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address on the local host to bind to.
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localPort
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the local host to bind to.
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Socket(InetAddress dstAddress, int dstPort,
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetAddress localAddress, int localPort) throws IOException {
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(dstAddress, dstPort);
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startupSocket(dstAddress, dstPort, localAddress, localPort, true);
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new streaming or datagram socket connected to the target host
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified by the parameters {@code addr} and {@code port}. The socket is
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * bound to any available port on the local host.
258f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param addr
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the Internet address to connect to.
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param port
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the target host to connect to.
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param streaming
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if {@code true} a streaming socket is returned, a datagram
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            socket otherwise.
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             streaming sockets or an appropriate constructor of {@code
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             DatagramSocket} for UDP transport.
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Deprecated
2738cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public Socket(InetAddress addr, int port, boolean streaming) throws IOException {
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this();
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(addr, port);
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startupSocket(addr, port, null, 0, streaming);
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates an unconnected socket with the given socket implementation.
281f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
2828cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * @param impl
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the socket implementation to be used.
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the socket.
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2878cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    protected Socket(SocketImpl impl) throws SocketException {
2888cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.impl = impl;
2898cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        this.proxy = null;
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks whether the connection destination satisfies the security policy
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and the validity of the port range.
295f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param destAddr
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the destination host address.
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the destination host.
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
3018cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private void checkDestination(InetAddress destAddr, int dstPort) {
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dstPort < 0 || dstPort > 65535) {
303b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Port out of range: " + dstPort);
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the socket. It is not possible to reconnect or rebind to this
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * socket thereafter which means a new socket instance has to be created.
310f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing the socket.
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void close() throws IOException {
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isClosed = true;
3168cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        // RI compatibility: the RI returns the any address (but the original local port) after close.
3178cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        localAddress = Inet4Address.ANY;
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.close();
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
322a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the IP address of the target host this socket is connected to, or null if this
323a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * socket is not yet connected.
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InetAddress getInetAddress() {
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getInetAddress();
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
333a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns an input stream to read data from this socket.
334f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the byte-oriented input stream.
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the input stream or the
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket is in an invalid state.
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InputStream getInputStream() throws IOException {
3410371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isInputShutdown()) {
343b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket input is shutdown");
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getInputStream();
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
349a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting.
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getKeepAlive() throws SocketException {
3520371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
3538cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE);
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
3578cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * Returns the local IP address this socket is bound to, or {@code InetAddress.ANY} if
3588cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * the socket is unbound.
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InetAddress getLocalAddress() {
3618cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        return localAddress;
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
3658cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes     * Returns the local port this socket is bound to, or -1 if the socket is unbound.
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getLocalPort() {
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isBound()) {
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getLocalPort();
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
375a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns an output stream to write data into this socket.
376f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the byte-oriented output stream.
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while creating the output stream or the
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket is in an invalid state.
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public OutputStream getOutputStream() throws IOException {
3830371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isOutputShutdown()) {
385b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket output is shutdown");
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getOutputStream();
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
391a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the port number of the target host this socket is connected to, or 0 if this socket
392a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * is not yet connected.
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getPort() {
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.getPort();
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
402a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1
403a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * for no linger (i.e. {@code close} will return immediately).
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getSoLinger() throws SocketException {
4060371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4070371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
4080371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        Object value = impl.getOption(SocketOptions.SO_LINGER);
4090371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        if (value instanceof Integer) {
4100371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            return (Integer) value;
4110371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        } else {
4120371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            return -1;
4130371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        }
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
417a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized int getReceiveBufferSize() throws SocketException {
4200371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4210371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.SO_RCVBUF);
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
425a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized int getSendBufferSize() throws SocketException {
4280371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4290371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.SO_SNDBUF);
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
433a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}.
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized int getSoTimeout() throws SocketException {
4360371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4370371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT);
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
441a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting.
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getTcpNoDelay() throws SocketException {
4440371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
4450371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY);
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
449a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option.
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
4510371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    public void setKeepAlive(boolean keepAlive) throws SocketException {
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (impl != null) {
4530371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            checkOpenAndCreate(true);
4540371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive));
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the internal factory for creating socket implementations. This may
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only be executed once during the lifetime of the application.
461f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param fac
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the socket implementation factory to be set.
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the factory has been already set.
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static synchronized void setSocketImplFactory(SocketImplFactory fac)
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IOException {
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (factory != null) {
470b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Factory already set");
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        factory = fac;
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
476a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setSendBufferSize(int size) throws SocketException {
4790371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size < 1) {
481b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size < 1");
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
487a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_SNDBUF receive buffer size}.
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
489b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    public synchronized void setReceiveBufferSize(int size) throws SocketException {
4900371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size < 1) {
492b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size < 1");
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
498a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds.
499a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * If {@code on} is false, {@code timeout} is irrelevant.
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setSoLinger(boolean on, int timeout) throws SocketException {
5020371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
5030371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (on && timeout < 0) {
505b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("timeout < 0");
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (on) {
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout));
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE);
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
515a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.
516a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Use 0 for no timeout.
517a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * To take effect, this option must be set before the blocking method was called.
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setSoTimeout(int timeout) throws SocketException {
5200371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeout < 0) {
522b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("timeout < 0");
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
528a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#TCP_NODELAY} option.
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setTcpNoDelay(boolean on) throws SocketException {
5310371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a stream socket, binds it to the nominated local address/port,
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * then connects it to the nominated destination address/port.
538f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstAddress
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the destination host address.
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dstPort
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the destination host.
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddress
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address on the local machine to bind.
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localPort
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the port on the local machine to bind.
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             thrown if an error occurs during the bind or connect
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             operations.
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
5510371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    private void startupSocket(InetAddress dstAddress, int dstPort,
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetAddress localAddress, int localPort, boolean streaming)
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IOException {
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localPort < 0 || localPort > 65535) {
556b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Local port out of range: " + localPort);
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5598cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetAddress addr = localAddress == null ? Inet4Address.ANY : localAddress;
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            impl.create(streaming);
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCreated = true;
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
5640917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes                if (!streaming || !usingSocks()) {
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    impl.bind(addr, localPort);
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isBound = true;
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.connect(dstAddress, dstPort);
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isConnected = true;
5708cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                cacheLocalAddress();
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.close();
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5780917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes    private boolean usingSocks() {
5790917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes        return proxy != null && proxy.type() == Proxy.Type.SOCKS;
5800917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes    }
5810917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a {@code String} containing a concise, human-readable description of the
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * socket.
585f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the textual representation of this socket.
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
591f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            return "Socket[unconnected]";
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return impl.toString();
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the input stream of this socket. Any further data sent to this
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * socket will be discarded. Reading from this socket after this method has
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * been called will return the value {@code EOF}.
600f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing the socket input stream.
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input stream is already closed.
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownInput() throws IOException {
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isInputShutdown()) {
608b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket input is shutdown");
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6100371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.shutdownInput();
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isInputShutdown = true;
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the output stream of this socket. All buffered data will be sent
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * followed by the termination sequence. Writing to the closed output stream
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * will cause an {@code IOException}.
619f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing the socket output stream.
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the output stream is already closed.
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownOutput() throws IOException {
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isOutputShutdown()) {
627b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket output is shutdown");
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6290371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(false);
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.shutdownOutput();
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isOutputShutdown = true;
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks whether the socket is closed, and throws an exception. Otherwise
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * creates the underlying SocketImpl.
637f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is closed.
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
6410371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    private void checkOpenAndCreate(boolean create) throws SocketException {
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isClosed()) {
643b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Socket is closed");
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!create) {
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isConnected()) {
647b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new SocketException("Socket is not connected");
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // a connected socket must be created
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * return directly to fix a possible bug, if !create, should return
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * here
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isCreated) {
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isCreated) {
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.create(true);
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (SocketException e) {
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new SocketException(e.toString());
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCreated = true;
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
676a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the local address and port of this socket as a SocketAddress or
677a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * null if the socket is unbound. This is useful on multihomed
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * hosts.
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketAddress getLocalSocketAddress() {
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isBound()) {
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new InetSocketAddress(getLocalAddress(), getLocalPort());
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
688a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns the remote address and port of this socket as a {@code
689a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * SocketAddress} or null if the socket is not connected.
690f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the remote socket address and port.
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketAddress getRemoteSocketAddress() {
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new InetSocketAddress(getInetAddress(), getPort());
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this socket is bound to a local address and port.
702f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the socket is bound to a local address, {@code
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         false} otherwise.
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isBound() {
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isBound;
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this socket is connected to a remote host.
712f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the socket is connected, {@code false} otherwise.
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isConnected() {
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isConnected;
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this socket is closed.
721f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the socket is closed, {@code false} otherwise.
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isClosed() {
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isClosed;
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Binds this socket to the given local host address and port specified by
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code null}, this socket will be bound to an available local address on
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * any free port.
733f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param localAddr
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specific address and port on the local machine to bind to.
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the given SocketAddress is invalid or not supported.
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is already bound or an error occurs while
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             binding.
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void bind(SocketAddress localAddr) throws IOException {
7430371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isBound()) {
745b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new BindException("Socket is already bound");
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int port = 0;
749051128862ae7c5c031b8ddb763848ed264a63746Lorenzo Colitti        InetAddress addr = Inet4Address.ANY;
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localAddr != null) {
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!(localAddr instanceof InetSocketAddress)) {
752b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IllegalArgumentException("Local address not an InetSocketAddress: " +
753b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                        localAddr.getClass());
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((addr = inetAddr.getAddress()) == null) {
757b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new SocketException("Host is unresolved: " + inetAddr.getHostName());
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            port = inetAddr.getPort();
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.bind(addr, port);
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isBound = true;
7668cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                cacheLocalAddress();
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.close();
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Connects this socket to the given remote host address and port specified
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * by the SocketAddress {@code remoteAddr}.
777f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param remoteAddr
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address and port of the remote host to connect to.
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the given SocketAddress is invalid or not supported.
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is already connected or an error occurs while
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             connecting.
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void connect(SocketAddress remoteAddr) throws IOException {
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connect(remoteAddr, 0);
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Connects this socket to the given remote host address and port specified
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * by the SocketAddress {@code remoteAddr} with the specified timeout. The
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connecting method will block until the connection is established or an
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * error occurred.
795f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param remoteAddr
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the address and port of the remote host to connect to.
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timeout
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timeout value in milliseconds or {@code 0} for an infinite
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            timeout.
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the given SocketAddress is invalid or not supported or the
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             timeout value is negative.
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the socket is already connected or an error occurs while
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             connecting.
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8088cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
8090371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeout < 0) {
811b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("timeout < 0");
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isConnected()) {
814b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Already connected");
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (remoteAddr == null) {
817b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("remoteAddr == null");
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!(remoteAddr instanceof InetSocketAddress)) {
821b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Remote address not an InetSocketAddress: " +
822b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                    remoteAddr.getClass());
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        InetAddress addr;
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((addr = inetAddr.getAddress()) == null) {
827b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new SocketException("Host is unresolved: " + inetAddr.getHostName());
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int port = inetAddr.getPort();
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkDestination(addr, port);
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (connectLock) {
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isBound()) {
8358cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                    // socket already created at this point by earlier call or
8360371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                    // checkOpenAndCreate this caused us to lose socket
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // options on create
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // impl.create(true);
8390917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes                    if (!usingSocks()) {
840051128862ae7c5c031b8ddb763848ed264a63746Lorenzo Colitti                        impl.bind(Inet4Address.ANY, 0);
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    isBound = true;
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.connect(remoteAddr, timeout);
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isConnected = true;
8468cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes                cacheLocalAddress();
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                impl.close();
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw e;
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether the incoming channel of the socket has already been
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * closed.
857f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if reading from this socket is not possible anymore,
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} otherwise.
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isInputShutdown() {
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isInputShutdown;
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
866f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Returns whether the outgoing channel of the socket has already been
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * closed.
868f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if writing to this socket is not possible anymore,
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} otherwise.
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isOutputShutdown() {
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isOutputShutdown;
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
877a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option.
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setReuseAddress(boolean reuse) throws SocketException {
8800371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
8810371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse));
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
885a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting.
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getReuseAddress() throws SocketException {
8880371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
8890371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR);
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
893a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option.
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOOBInline(boolean oobinline) throws SocketException {
8960371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
8970371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline));
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
901a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting.
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getOOBInline() throws SocketException {
9040371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
9050371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE);
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
909a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket.
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setTrafficClass(int value) throws SocketException {
9120371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value < 0 || value > 255) {
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
9202cd82d7111f68ff63145ef7c393bf1479ff06223Elliott Hughes     * Returns this socket's {@see SocketOptions#IP_TOS} setting.
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getTrafficClass() throws SocketException {
9230371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        checkOpenAndCreate(true);
9240371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        return (Integer) impl.getOption(SocketOptions.IP_TOS);
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sends the given single byte data which is represented by the lowest octet
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of {@code value} as "TCP urgent data".
930f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the byte of urgent data to be sent.
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while sending urgent data.
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void sendUrgentData(int value) throws IOException {
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        impl.sendUrgentData(value);
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the appropriate flags for a socket created by {@code
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ServerSocket.accept()}.
943f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see ServerSocket#implAccept
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void accepted() {
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCreated = isBound = isConnected = true;
9488cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        cacheLocalAddress();
9498cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    }
9508cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
9518cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    private void cacheLocalAddress() {
9523db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes        this.localAddress = Platform.NETWORK.getSocketLocalAddress(impl.fd);
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
9560d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * Returns this socket's {@code SocketChannel}, if one exists. A channel is
9570d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * available only if this socket wraps a channel. (That is, you can go from a
9580d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.)
9590d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * In practice, this means that the socket must have been created by
9600d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * {@link java.nio.channels.ServerSocketChannel#accept} or
9610d93c38cc3c7a5001aece8a18cafc6d1fc7551f3Elliott Hughes     * {@link java.nio.channels.SocketChannel#open}.
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketChannel getChannel() {
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets performance preferences for connectionTime, latency and bandwidth.
969a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     *
970a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes     * <p>This method does currently nothing.
971f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param connectionTime
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value representing the importance of a short connecting
974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            time.
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param latency
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value representing the importance of low latency.
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bandwidth
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value representing the importance of high bandwidth.
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9800371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Our socket implementation only provide one protocol: TCP/IP, so
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // we do nothing for this method
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
985