PlainSocketImpl.java revision b46dab348e2007bc08abaf7ecae34d89a2474e50
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 org.apache.harmony.luni.net; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Field; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.ConnectException; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetSocketAddress; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Proxy; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketAddress; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketImpl; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketTimeoutException; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.UnknownHostException; 350eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughesimport java.nio.ByteOrder; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessController; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedAction; 380eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughesimport org.apache.harmony.luni.platform.OSMemory; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.platform.Platform; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A concrete connected-socket implementation. 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 44f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonpublic class PlainSocketImpl extends SocketImpl { 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // For SOCKS support. A SOCKS bind() uses the last 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // host connected to in its request. 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static private InetAddress lastConnectedAddress; 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static private int lastConnectedPort; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static Field fdField; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 547738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean streaming = true; 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 567738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean shutdownInput; 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 587738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private Proxy proxy; 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 61f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd) { 63f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 64f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 65f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 66f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 67f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 68f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 69f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(Proxy proxy) { 706b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.proxy = proxy; 72f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 746b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public PlainSocketImpl() { 756b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 766b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson } 776b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson 78f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) { 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson super(); 80f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 81f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.localport = localport; 82f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.address = addr; 83f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.port = port; 84f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 85f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 86f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 87f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 88f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void accept(SocketImpl newImpl) throws IOException { 910917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksBind(); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksAccept(); 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (newImpl instanceof PlainSocketImpl) { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PlainSocketImpl newPlainSocketImpl = (PlainSocketImpl) newImpl; 1003db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.accept(fd, newImpl, newPlainSocketImpl.getFileDescriptor()); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if newImpl is not an instance of PlainSocketImpl, use 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // reflection to get/set protected fields. 1048cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (fdField == null) { 105f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes fdField = getSocketImplField("fd"); 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project FileDescriptor newFd = (FileDescriptor) fdField.get(newImpl); 1083db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.accept(fd, newImpl, newFd); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalAccessException e) { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // empty 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1150917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes private boolean usingSocks() { 1160917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes return proxy != null && proxy.type() == Proxy.Type.SOCKS; 1170917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes } 1180917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * gets SocketImpl field by reflection. 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Field getSocketImplField(final String fieldName) { 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return AccessController.doPrivileged(new PrivilegedAction<Field>() { 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Field run() { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Field field = null; 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field = SocketImpl.class.getDeclaredField(fieldName); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field.setAccessible(true); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (NoSuchFieldException e) { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(e); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return field; 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1378cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initLocalPort(int localPort) { 1388cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = localPort; 1398cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1408cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 1418cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initRemoteAddressAndPort(InetAddress remoteAddress, int remotePort) { 1428cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = remoteAddress; 1438cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.port = remotePort; 1448cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1458cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 146f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes private void checkNotClosed() throws IOException { 147f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes if (!fd.valid()) { 148f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes throw new SocketException("Socket is closed"); 149f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 150f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 151f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized int available() throws IOException { 154f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we need to check if the input has been shutdown. If so 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we should return that there is no data to be read 15797144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes if (shutdownInput) { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1603db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.FILE_SYSTEM.ioctlAvailable(fd); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 1648cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes protected void bind(InetAddress address, int port) throws IOException { 1653db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.bind(fd, address, port); 1668cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = address; 1678cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (port != 0) { 1688cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = port; 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1703db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes this.localport = Platform.NETWORK.getSocketLocalPort(fd); 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 17558e5a8e6eeaf94d78522e0e9994c4565a3b33fdbJesse Wilson protected synchronized void close() throws IOException { 176f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 177c6e0981e5a2d23a0758ed71a8086c4278a7832efJesse Wilson Platform.NETWORK.close(fd); 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(String aHost, int aPort) throws IOException { 18297144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes connect(InetAddress.getByName(aHost), aPort); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(InetAddress anAddr, int aPort) throws IOException { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(anAddr, aPort, 0); 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connects this socket to the specified remote host address/port. 192f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param anAddr 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote host address to connect to 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param aPort 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote port to connect to 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a timeout where supported. 0 means no timeout 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs while connecting 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2028cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes private void connect(InetAddress anAddr, int aPort, int timeout) throws IOException { 203f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr; 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 2050917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (streaming && usingSocks()) { 206036ffc75d2b7ece42bcd97f290c026e215868ba9Elliott Hughes socksConnect(anAddr, aPort, 0); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 2083db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.connect(fd, normalAddr, aPort, timeout); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ConnectException e) { 2118cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes throw new ConnectException(anAddr + ":" + aPort + " - " + e.getMessage()); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.address = normalAddr; 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.port = aPort; 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void create(boolean streaming) throws IOException { 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.streaming = streaming; 2203db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.socket(fd, streaming); 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 223e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 224e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 22512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 22612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 22712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 228e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom close(); 229e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 230e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 231e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized InputStream getInputStream() throws IOException { 236f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new SocketInputStream(this); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object getOption(int optID) throws SocketException { 2423db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.NETWORK.getSocketOption(fd, optID); 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized OutputStream getOutputStream() throws IOException { 247f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new SocketOutputStream(this); 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void listen(int backlog) throws IOException { 2530917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Do nothing for a SOCKS connection. The listen occurs on the 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server during the bind. 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2583db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.listen(fd, backlog); 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setOption(int optID, Object val) throws SocketException { 2633db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.setSocketOption(fd, optID, val); 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the SOCKS proxy server port. 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int socksGetServerPort() { 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server port from proxy. It is unnecessary to check 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyPort" property, since proxy setting should only be 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return addr.getPort(); 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the InetAddress of the SOCKS proxy server. 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InetAddress socksGetServerAddress() throws UnknownHostException { 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String proxyName; 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server address from proxy. It is unnecessary to check 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyHost" property, since all proxy setting should be 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getHostName(); 288b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (proxyName == null) { 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getAddress().getHostAddress(); 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 29197144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes return InetAddress.getByName(proxyName); 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connect using a SOCKS server. 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksConnect(InetAddress applicationServerAddress, 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort, int timeout) throws IOException { 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3003db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.connect(fd, socksGetServerAddress(), socksGetServerPort(), timeout); 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 302b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("SOCKS connection failed: " + e); 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksRequestConnection(applicationServerAddress, applicationServerPort); 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedAddress = applicationServerAddress; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort = applicationServerPort; 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Request a SOCKS connection to the application server given. If the 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * request fails to complete successfully, an exception is thrown. 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksRequestConnection(InetAddress applicationServerAddress, 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort) throws IOException { 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_CONNECT, 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project applicationServerAddress, applicationServerPort); 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Perform an accept for a SOCKS bind. 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void socksAccept() throws IOException { 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the input portion of the socket. 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownInput() throws IOException { 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project shutdownInput = true; 3433db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.shutdownInput(fd); 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the output portion of the socket. 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownOutput() throws IOException { 3513db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.shutdownOutput(fd); 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Bind using a SOCKS server. 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksBind() throws IOException { 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3593db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.connect(fd, socksGetServerAddress(), socksGetServerPort(), 0); 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 361b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to connect to SOCKS server: " + e); 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // There must be a connection to an application host for the bind to 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // work. 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lastConnectedAddress == null) { 367b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Invalid SOCKS client"); 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use the last connected address and port in the bind request. 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_BIND, lastConnectedAddress, 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort); 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 3760eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // A peculiarity of socks 4 - if the address returned is 0, use the 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // original socks server address. 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getIP() == 0) { 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = socksGetServerAddress(); 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // IPv6 support not yet required as 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // currently the Socks4Message.getIP() only returns int, 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // so only works with IPv4 4byte addresses 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] replyBytes = new byte[4]; 3880eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes OSMemory.pokeInt(replyBytes, 0, reply.getIP(), ByteOrder.BIG_ENDIAN); 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = InetAddress.getByAddress(replyBytes); 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project localport = reply.getPort(); 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Send a SOCKS V4 request. 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3970eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes private void socksSendRequest(int command, InetAddress address, int port) throws IOException { 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message request = new Socks4Message(); 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setCommandOrResult(command); 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setPort(port); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setIP(address.getAddress()); 402f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes request.setUserId("default"); 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getOutputStream().write(request.getBytes(), 0, request.getLength()); 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a SOCKS V4 reply. 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socks4Message socksReadReply() throws IOException { 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = new Socks4Message(); 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bytesRead = 0; 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (bytesRead < Socks4Message.REPLY_LENGTH) { 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = getInputStream().read(reply.getBytes(), bytesRead, 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message.REPLY_LENGTH - bytesRead); 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (-1 == count) { 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytesRead += count; 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (Socks4Message.REPLY_LENGTH != bytesRead) { 422b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Malformed reply from SOCKS server"); 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return reply; 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(SocketAddress remoteAddr, int timeout) 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(inetAddr.getAddress(), inetAddr.getPort(), timeout); 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean supportsUrgentData() { 43679ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes return true; 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void sendUrgentData(int value) throws IOException { 4413db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.sendUrgentData(fd, (byte) value); 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int read(byte[] buffer, int offset, int count) throws IOException { 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (shutdownInput) { 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 4483db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes int read = Platform.NETWORK.read(fd, buffer, offset, count); 449f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of zero bytes for a blocking socket means a timeout occurred 450f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (read == 0) { 451f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new SocketTimeoutException(); 452f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 453f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of -1 indicates the peer was closed 454f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (read == -1) { 455f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson shutdownInput = true; 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 457f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return read; 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int write(byte[] buffer, int offset, int count) throws IOException { 461221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes if (streaming) { 4623db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.NETWORK.write(fd, buffer, offset, count); 463221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes } else { 4643db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.NETWORK.send(fd, buffer, offset, count, port, address); 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 468