PlainSocketImpl.java revision 79ff4e73fd689dae6667a8137ee57137962ff13a
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 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InterruptedIOException; 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.SocketOptions; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketTimeoutException; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.UnknownHostException; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessController; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedAction; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.platform.INetworkSystem; 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 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * used to store the trafficClass value which is simply returned as the 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * value that was set. We also need it to pass it to methods that specify an 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * address packets are going to be sent to 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int trafficClass; 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected INetworkSystem netImpl = Platform.getNetworkSystem(); 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int receiveTimeout = 0; 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean streaming = true; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean shutdownInput; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Proxy proxy; 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd) { 72f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 74f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 75f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(Proxy proxy) { 766b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 77f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.proxy = proxy; 78f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 806b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public PlainSocketImpl() { 816b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 826b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson } 836b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson 84f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) { 85f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson super(); 86f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 87f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.localport = localport; 88f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.address = addr; 89f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.port = port; 90f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 91f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void accept(SocketImpl newImpl) throws IOException { 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (NetUtil.usingSocks(proxy)) { 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksBind(); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksAccept(); 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (newImpl instanceof PlainSocketImpl) { 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PlainSocketImpl newPlainSocketImpl = (PlainSocketImpl) newImpl; 1038cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes netImpl.accept(fd, newImpl, newPlainSocketImpl.getFileDescriptor(), receiveTimeout); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if newImpl is not an instance of PlainSocketImpl, use 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // reflection to get/set protected fields. 1078cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (fdField == null) { 108f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes fdField = getSocketImplField("fd"); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project FileDescriptor newFd = (FileDescriptor) fdField.get(newImpl); 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.accept(fd, newImpl, newFd, receiveTimeout); 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (InterruptedIOException e) { 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SocketTimeoutException(e.getMessage()); 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalAccessException e) { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // empty 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * gets SocketImpl field by reflection. 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Field getSocketImplField(final String fieldName) { 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return AccessController.doPrivileged(new PrivilegedAction<Field>() { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Field run() { 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Field field = null; 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field = SocketImpl.class.getDeclaredField(fieldName); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field.setAccessible(true); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (NoSuchFieldException e) { 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(e); 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return field; 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1388cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initLocalPort(int localPort) { 1398cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = localPort; 1408cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1418cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 1428cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initRemoteAddressAndPort(InetAddress remoteAddress, int remotePort) { 1438cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = remoteAddress; 1448cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.port = remotePort; 1458cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1468cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized int available() throws IOException { 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we need to check if the input has been shutdown. If so 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we should return that there is no data to be read 15197144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes if (shutdownInput) { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 15449e79cdc1aadb2922178e8905a7907df0bdaf7b3Elliott Hughes return Platform.getFileSystem().ioctlAvailable(fd); 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 1588cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes protected void bind(InetAddress address, int port) throws IOException { 1598cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes netImpl.bind(fd, address, port); 1608cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = address; 1618cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (port != 0) { 1628cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = port; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1648cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = netImpl.getSocketLocalPort(fd); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void close() throws IOException { 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (fd) { 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd.valid()) { 17279ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes netImpl.close(fd); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fd = new FileDescriptor(); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 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 { 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (streaming) { 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (NetUtil.usingSocks(proxy)) { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksConnect(anAddr, aPort, 0); 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (timeout == 0) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.connect(fd, trafficClass, normalAddr, aPort); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.connectStreamWithTimeoutSocket(fd, aPort, 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project timeout, trafficClass, normalAddr); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 2158cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr); 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ConnectException e) { 2188cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes throw new ConnectException(anAddr + ":" + aPort + " - " + e.getMessage()); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.address = normalAddr; 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.port = aPort; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void create(boolean streaming) throws IOException { 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.streaming = streaming; 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (streaming) { 228f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson netImpl.createStreamSocket(fd, NetUtil.preferIPv4Stack()); 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack()); 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void finalize() throws IOException { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized InputStream getInputStream() throws IOException { 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!fd.valid()) { 242b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Socket is closed"); 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new SocketInputStream(this); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object getOption(int optID) throws SocketException { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (optID == SocketOptions.SO_TIMEOUT) { 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Integer.valueOf(receiveTimeout); 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (optID == SocketOptions.IP_TOS) { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Integer.valueOf(trafficClass); 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 255fdd13e86ec613e46b68376f90d2c89c2ac33b4b5Elliott Hughes return netImpl.getSocketOption(fd, optID); 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized OutputStream getOutputStream() throws IOException { 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!fd.valid()) { 262b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Socket is closed"); 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new SocketOutputStream(this); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void listen(int backlog) throws IOException { 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (NetUtil.usingSocks(proxy)) { 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Do nothing for a SOCKS connection. The listen occurs on the 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server during the bind. 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 27497144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes netImpl.listen(fd, backlog); 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setOption(int optID, Object val) throws SocketException { 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (optID == SocketOptions.SO_TIMEOUT) { 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project receiveTimeout = ((Integer) val).intValue(); 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.setSocketOption(fd, optID, val); 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (SocketException e) { 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we don't throw an exception for IP_TOS even if the platform 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // won't let us set the requested value 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (optID != SocketOptions.IP_TOS) { 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * save this value as it is actually used differently for IPv4 and 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * IPv6 so we cannot get the value using the getOption. The option 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is actually only set for IPv4 and a masked version of the value 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be set as only a subset of the values are allowed on the 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * socket. Therefore we need to retain it to return the value that 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * was set. We also need the value to be passed into a number of 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * natives so that it can be used properly with IPv6 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (optID == SocketOptions.IP_TOS) { 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project trafficClass = ((Integer) val).intValue(); 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 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 * Gets the SOCKS proxy server port. 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int socksGetServerPort() { 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server port from proxy. It is unnecessary to check 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyPort" property, since proxy setting should only be 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return addr.getPort(); 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the InetAddress of the SOCKS proxy server. 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InetAddress socksGetServerAddress() throws UnknownHostException { 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String proxyName; 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server address from proxy. It is unnecessary to check 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyHost" property, since all proxy setting should be 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getHostName(); 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null == proxyName) { 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getAddress().getHostAddress(); 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 33297144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes return InetAddress.getByName(proxyName); 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connect using a SOCKS server. 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksConnect(InetAddress applicationServerAddress, 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort, int timeout) throws IOException { 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (timeout == 0) { 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.connect(fd, trafficClass, socksGetServerAddress(), 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksGetServerPort()); 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.connectStreamWithTimeoutSocket(fd, 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksGetServerPort(), timeout, trafficClass, 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksGetServerAddress()); 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 351b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("SOCKS connection failed: " + e); 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksRequestConnection(applicationServerAddress, applicationServerPort); 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedAddress = applicationServerAddress; 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort = applicationServerPort; 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Request a SOCKS connection to the application server given. If the 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * request fails to complete successfully, an exception is thrown. 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksRequestConnection(InetAddress applicationServerAddress, 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort) throws IOException { 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_CONNECT, 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project applicationServerAddress, applicationServerPort); 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Perform an accept for a SOCKS bind. 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void socksAccept() throws IOException { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the input portion of the socket. 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownInput() throws IOException { 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project shutdownInput = true; 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.shutdownInput(fd); 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the output portion of the socket. 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownOutput() throws IOException { 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.shutdownOutput(fd); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Bind using a SOCKS server. 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksBind() throws IOException { 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 408b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes netImpl.connect(fd, trafficClass, socksGetServerAddress(), socksGetServerPort()); 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 410b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to connect to SOCKS server: " + e); 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // There must be a connection to an application host for the bind to 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // work. 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lastConnectedAddress == null) { 416b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Invalid SOCKS client"); 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use the last connected address and port in the bind request. 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_BIND, lastConnectedAddress, 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort); 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(reply.getErrorString(reply 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getCommandOrResult())); 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // A peculiarity of socks 4 - if the address returned is 0, use the 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // original socks server address. 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getIP() == 0) { 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = socksGetServerAddress(); 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // IPv6 support not yet required as 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // currently the Socks4Message.getIP() only returns int, 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // so only works with IPv4 4byte addresses 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] replyBytes = new byte[4]; 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project NetUtil.intToBytes(reply.getIP(), replyBytes, 0); 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = InetAddress.getByAddress(replyBytes); 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project localport = reply.getPort(); 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Send a SOCKS V4 request. 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksSendRequest(int command, InetAddress address, int port) 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message request = new Socks4Message(); 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setCommandOrResult(command); 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setPort(port); 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setIP(address.getAddress()); 453f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes request.setUserId("default"); 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getOutputStream().write(request.getBytes(), 0, request.getLength()); 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a SOCKS V4 reply. 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socks4Message socksReadReply() throws IOException { 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = new Socks4Message(); 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bytesRead = 0; 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (bytesRead < Socks4Message.REPLY_LENGTH) { 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = getInputStream().read(reply.getBytes(), bytesRead, 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message.REPLY_LENGTH - bytesRead); 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (-1 == count) { 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytesRead += count; 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (Socks4Message.REPLY_LENGTH != bytesRead) { 473b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Malformed reply from SOCKS server"); 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return reply; 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(SocketAddress remoteAddr, int timeout) 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(inetAddr.getAddress(), inetAddr.getPort(), timeout); 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean supportsUrgentData() { 48779ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes return true; 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void sendUrgentData(int value) throws IOException { 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project netImpl.sendUrgentData(fd, (byte) value); 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project FileDescriptor getFD() { 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return fd; 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int read(byte[] buffer, int offset, int count) throws IOException { 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (shutdownInput) { 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 50370882923fb227de7a54a9b1a2a4dd2c6ec8b51aeElliott Hughes int read = netImpl.read(fd, buffer, offset, count, receiveTimeout); 504f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of zero bytes for a blocking socket means a timeout occurred 505f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (read == 0) { 506f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new SocketTimeoutException(); 507f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 508f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of -1 indicates the peer was closed 509f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (read == -1) { 510f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson shutdownInput = true; 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 512f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return read; 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int write(byte[] buffer, int offset, int count) throws IOException { 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!streaming) { 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return netImpl.sendDatagram2(fd, buffer, offset, count, port, 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address); 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 520d9179c4701153caeb821cf3da639b28465317508Elliott Hughes return netImpl.write(fd, buffer, offset, count); 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 523