PlainSocketImpl.java revision f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8a
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; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessController; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedAction; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.platform.Platform; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A concrete connected-socket implementation. 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 42f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonpublic class PlainSocketImpl extends SocketImpl { 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // For SOCKS support. A SOCKS bind() uses the last 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // host connected to in its request. 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static private InetAddress lastConnectedAddress; 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static private int lastConnectedPort; 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static Field fdField; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 527738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean streaming = true; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 547738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean shutdownInput; 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 567738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private Proxy proxy; 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 58f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom private final CloseGuard guard = CloseGuard.getUnopened(); 59f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 60f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd) { 61f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 62f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 63f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 64f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 65f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 66f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 67f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(Proxy proxy) { 686b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 69f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.proxy = proxy; 70f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 726b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public PlainSocketImpl() { 736b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 746b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson } 756b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson 76f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) { 77f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson super(); 78f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.localport = localport; 80f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.address = addr; 81f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.port = port; 82f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 83f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 84f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 85f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 86f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void accept(SocketImpl newImpl) throws IOException { 890917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksBind(); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksAccept(); 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (newImpl instanceof PlainSocketImpl) { 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PlainSocketImpl newPlainSocketImpl = (PlainSocketImpl) newImpl; 983db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.accept(fd, newImpl, newPlainSocketImpl.getFileDescriptor()); 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if newImpl is not an instance of PlainSocketImpl, use 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // reflection to get/set protected fields. 1028cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (fdField == null) { 103f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes fdField = getSocketImplField("fd"); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project FileDescriptor newFd = (FileDescriptor) fdField.get(newImpl); 1063db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.accept(fd, newImpl, newFd); 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalAccessException e) { 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // empty 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1130917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes private boolean usingSocks() { 1140917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes return proxy != null && proxy.type() == Proxy.Type.SOCKS; 1150917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes } 1160917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * gets SocketImpl field by reflection. 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Field getSocketImplField(final String fieldName) { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return AccessController.doPrivileged(new PrivilegedAction<Field>() { 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Field run() { 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Field field = null; 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field = SocketImpl.class.getDeclaredField(fieldName); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field.setAccessible(true); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (NoSuchFieldException e) { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(e); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return field; 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1358cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initLocalPort(int localPort) { 1368cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = localPort; 1378cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1388cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 1398cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initRemoteAddressAndPort(InetAddress remoteAddress, int remotePort) { 1408cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = remoteAddress; 1418cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.port = remotePort; 1428cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1438cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 144f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes private void checkNotClosed() throws IOException { 145f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes if (!fd.valid()) { 146f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes throw new SocketException("Socket is closed"); 147f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 148f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 149f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized int available() throws IOException { 152f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we need to check if the input has been shutdown. If so 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we should return that there is no data to be read 15597144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes if (shutdownInput) { 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1583db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.FILE_SYSTEM.ioctlAvailable(fd); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 1628cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes protected void bind(InetAddress address, int port) throws IOException { 1633db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.bind(fd, address, port); 1648cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = address; 1658cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (port != 0) { 1668cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = port; 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1683db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes this.localport = Platform.NETWORK.getSocketLocalPort(fd); 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 17358e5a8e6eeaf94d78522e0e9994c4565a3b33fdbJesse Wilson protected synchronized void close() throws IOException { 174f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 175c6e0981e5a2d23a0758ed71a8086c4278a7832efJesse Wilson Platform.NETWORK.close(fd); 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(String aHost, int aPort) throws IOException { 18097144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes connect(InetAddress.getByName(aHost), aPort); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(InetAddress anAddr, int aPort) throws IOException { 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(anAddr, aPort, 0); 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connects this socket to the specified remote host address/port. 190f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param anAddr 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote host address to connect to 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param aPort 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote port to connect to 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a timeout where supported. 0 means no timeout 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs while connecting 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2008cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes private void connect(InetAddress anAddr, int aPort, int timeout) throws IOException { 201f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr; 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 2030917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (streaming && usingSocks()) { 204036ffc75d2b7ece42bcd97f290c026e215868ba9Elliott Hughes socksConnect(anAddr, aPort, 0); 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 2063db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.connect(fd, normalAddr, aPort, timeout); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ConnectException e) { 2098cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes throw new ConnectException(anAddr + ":" + aPort + " - " + e.getMessage()); 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.address = normalAddr; 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.port = aPort; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void create(boolean streaming) throws IOException { 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.streaming = streaming; 2183db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.socket(fd, streaming); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 221e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 222e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 223f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.warnIfOpen(); 224e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom close(); 225e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 226e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 227e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized InputStream getInputStream() throws IOException { 232f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new SocketInputStream(this); 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object getOption(int optID) throws SocketException { 2383db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.NETWORK.getSocketOption(fd, optID); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized OutputStream getOutputStream() throws IOException { 243f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new SocketOutputStream(this); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void listen(int backlog) throws IOException { 2490917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Do nothing for a SOCKS connection. The listen occurs on the 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server during the bind. 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2543db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.listen(fd, backlog); 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setOption(int optID, Object val) throws SocketException { 2593db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.setSocketOption(fd, optID, val); 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the SOCKS proxy server port. 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int socksGetServerPort() { 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server port from proxy. It is unnecessary to check 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyPort" property, since proxy setting should only be 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return addr.getPort(); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the InetAddress of the SOCKS proxy server. 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InetAddress socksGetServerAddress() throws UnknownHostException { 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String proxyName; 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server address from proxy. It is unnecessary to check 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyHost" property, since all proxy setting should be 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getHostName(); 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null == proxyName) { 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getAddress().getHostAddress(); 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 28797144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes return InetAddress.getByName(proxyName); 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connect using a SOCKS server. 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksConnect(InetAddress applicationServerAddress, 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort, int timeout) throws IOException { 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 2963db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.connect(fd, socksGetServerAddress(), socksGetServerPort(), timeout); 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 298b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("SOCKS connection failed: " + e); 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksRequestConnection(applicationServerAddress, applicationServerPort); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedAddress = applicationServerAddress; 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort = applicationServerPort; 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Request a SOCKS connection to the application server given. If the 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * request fails to complete successfully, an exception is thrown. 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksRequestConnection(InetAddress applicationServerAddress, 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort) throws IOException { 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_CONNECT, 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project applicationServerAddress, applicationServerPort); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Perform an accept for a SOCKS bind. 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void socksAccept() throws IOException { 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the input portion of the socket. 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownInput() throws IOException { 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project shutdownInput = true; 3393db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.shutdownInput(fd); 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the output portion of the socket. 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownOutput() throws IOException { 3473db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.shutdownOutput(fd); 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Bind using a SOCKS server. 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksBind() throws IOException { 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3553db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.connect(fd, socksGetServerAddress(), socksGetServerPort(), 0); 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 357b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to connect to SOCKS server: " + e); 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // There must be a connection to an application host for the bind to 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // work. 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lastConnectedAddress == null) { 363b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Invalid SOCKS client"); 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use the last connected address and port in the bind request. 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_BIND, lastConnectedAddress, 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort); 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // A peculiarity of socks 4 - if the address returned is 0, use the 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // original socks server address. 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getIP() == 0) { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = socksGetServerAddress(); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // IPv6 support not yet required as 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // currently the Socks4Message.getIP() only returns int, 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // so only works with IPv4 4byte addresses 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] replyBytes = new byte[4]; 3850917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes intToBytes(reply.getIP(), replyBytes, 0); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = InetAddress.getByAddress(replyBytes); 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project localport = reply.getPort(); 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 391171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes private static void intToBytes(int value, byte[] bytes, int start) { 3920917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes /* 3930917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes * Shift the int so the current byte is right-most Use a byte mask of 3940917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes * 255 to single out the last byte. 3950917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes */ 3960917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes bytes[start] = (byte) ((value >> 24) & 255); 3970917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes bytes[start + 1] = (byte) ((value >> 16) & 255); 3980917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes bytes[start + 2] = (byte) ((value >> 8) & 255); 3990917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes bytes[start + 3] = (byte) (value & 255); 4000917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes } 4010917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Send a SOCKS V4 request. 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksSendRequest(int command, InetAddress address, int port) 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message request = new Socks4Message(); 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setCommandOrResult(command); 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setPort(port); 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setIP(address.getAddress()); 411f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes request.setUserId("default"); 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getOutputStream().write(request.getBytes(), 0, request.getLength()); 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a SOCKS V4 reply. 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socks4Message socksReadReply() throws IOException { 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = new Socks4Message(); 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bytesRead = 0; 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (bytesRead < Socks4Message.REPLY_LENGTH) { 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = getInputStream().read(reply.getBytes(), bytesRead, 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message.REPLY_LENGTH - bytesRead); 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (-1 == count) { 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytesRead += count; 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (Socks4Message.REPLY_LENGTH != bytesRead) { 431b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Malformed reply from SOCKS server"); 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return reply; 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(SocketAddress remoteAddr, int timeout) 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(inetAddr.getAddress(), inetAddr.getPort(), timeout); 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean supportsUrgentData() { 44579ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes return true; 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void sendUrgentData(int value) throws IOException { 4503db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes Platform.NETWORK.sendUrgentData(fd, (byte) value); 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int read(byte[] buffer, int offset, int count) throws IOException { 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (shutdownInput) { 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 4573db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes int read = Platform.NETWORK.read(fd, buffer, offset, count); 458f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of zero bytes for a blocking socket means a timeout occurred 459f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (read == 0) { 460f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new SocketTimeoutException(); 461f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 462f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of -1 indicates the peer was closed 463f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (read == -1) { 464f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson shutdownInput = true; 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 466f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return read; 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int write(byte[] buffer, int offset, int count) throws IOException { 470221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes if (streaming) { 4713db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.NETWORK.write(fd, buffer, offset, count); 472221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes } else { 4733db0d1b07a79c3c871b0aa0929674adae3081b4fElliott Hughes return Platform.NETWORK.send(fd, buffer, offset, count, port, address); 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 477