PlainSocketImpl.java revision f4a4259d8a548ab172ca98b702feafcd0ceb1411
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 188de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughespackage java.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.net.ConnectException; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetSocketAddress; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Proxy; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketAddress; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketImpl; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketTimeoutException; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.UnknownHostException; 340eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughesimport java.nio.ByteOrder; 35608263018762d64a07276b7c8f58102455ccecc8Elliott Hughesimport java.util.Arrays; 3659e4744d27231f260271dbbca406e0cc39768116Elliott Hughesimport libcore.io.ErrnoException; 370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge; 3859e4744d27231f260271dbbca406e0cc39768116Elliott Hughesimport libcore.io.Libcore; 39f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesimport libcore.io.Memory; 40ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughesimport libcore.io.Streams; 4159e4744d27231f260271dbbca406e0cc39768116Elliott Hughesimport static libcore.io.OsConstants.*; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 448de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes * @hide used in java.nio. 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 46f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonpublic class PlainSocketImpl extends SocketImpl { 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // For SOCKS support. A SOCKS bind() uses the last 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // host connected to in its request. 508de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes private static InetAddress lastConnectedAddress; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 528de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes private static int lastConnectedPort; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 547738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean streaming = true; 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 567738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean shutdownInput; 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 587738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private Proxy proxy; 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 61f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd) { 63f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 64f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 65f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 66f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 67f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 68f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 69f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(Proxy proxy) { 706b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.proxy = proxy; 72f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 746b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public PlainSocketImpl() { 756b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 766b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson } 776b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson 78f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) { 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 80f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.localport = localport; 81f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.address = addr; 82f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.port = port; 83f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 84f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 85f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 86f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 87f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void accept(SocketImpl newImpl) throws IOException { 900917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksBind(); 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksAccept(); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 95553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 96553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes try { 97553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes InetSocketAddress peerAddress = new InetSocketAddress(); 98553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes FileDescriptor clientFd = Libcore.os.accept(fd, peerAddress); 99553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 100553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes // TODO: we can't just set newImpl.fd to clientFd because a nio SocketChannel may 101553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes // be sharing the FileDescriptor. http://b//4452981. 102553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes newImpl.fd.setInt$(clientFd.getInt$()); 103553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 104553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes newImpl.address = peerAddress.getAddress(); 105553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes newImpl.port = peerAddress.getPort(); 106553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } catch (ErrnoException errnoException) { 107f4a4259d8a548ab172ca98b702feafcd0ceb1411Elliott Hughes if (errnoException.errno == EAGAIN) { 108553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes throw new SocketTimeoutException(errnoException); 109553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 110553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes throw errnoException.rethrowAsSocketException(); 111553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 11249ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes 11349ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes // Reset the client's inherited read timeout to the Java-specified default of 0. 11449ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes newImpl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(0)); 11549ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes 1160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes newImpl.localport = IoBridge.getSocketLocalPort(newImpl.fd); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1190917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes private boolean usingSocks() { 1200917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes return proxy != null && proxy.type() == Proxy.Type.SOCKS; 1210917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes } 1220917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes 1238cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initLocalPort(int localPort) { 1248cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = localPort; 1258cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1268cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 1278cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes public void initRemoteAddressAndPort(InetAddress remoteAddress, int remotePort) { 1288cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = remoteAddress; 1298cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.port = remotePort; 1308cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes } 1318cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes 132f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes private void checkNotClosed() throws IOException { 133f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes if (!fd.valid()) { 134f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes throw new SocketException("Socket is closed"); 135f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 136f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 137f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized int available() throws IOException { 140f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we need to check if the input has been shutdown. If so 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we should return that there is no data to be read 14397144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes if (shutdownInput) { 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1460b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return IoBridge.available(fd); 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes @Override protected void bind(InetAddress address, int port) throws IOException { 1500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.bind(fd, address, port); 1518cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.address = address; 1528cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (port != 0) { 1538cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = port; 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1550b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes this.localport = IoBridge.getSocketLocalPort(fd); 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 16058e5a8e6eeaf94d78522e0e9994c4565a3b33fdbJesse Wilson protected synchronized void close() throws IOException { 161f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 1620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.closeSocket(fd); 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(String aHost, int aPort) throws IOException { 16797144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes connect(InetAddress.getByName(aHost), aPort); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(InetAddress anAddr, int aPort) throws IOException { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(anAddr, aPort, 0); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connects this socket to the specified remote host address/port. 177f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param anAddr 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote host address to connect to 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param aPort 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote port to connect to 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a timeout where supported. 0 means no timeout 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs while connecting 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1878cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes private void connect(InetAddress anAddr, int aPort, int timeout) throws IOException { 188f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr; 189996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes if (streaming && usingSocks()) { 190996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes socksConnect(anAddr, aPort, 0); 191996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes } else { 1920b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.connect(fd, normalAddr, aPort, timeout); 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.address = normalAddr; 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.port = aPort; 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void create(boolean streaming) throws IOException { 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.streaming = streaming; 2010b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes this.fd = IoBridge.socket(streaming); 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 205e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 20612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 20712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 20812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 209e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom close(); 210e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 211e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 212e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 215608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override protected synchronized InputStream getInputStream() throws IOException { 216f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 217608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return new PlainSocketInputStream(this); 218608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 219608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 220608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private static class PlainSocketInputStream extends InputStream { 221608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private final PlainSocketImpl socketImpl; 222608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 223608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes public PlainSocketInputStream(PlainSocketImpl socketImpl) { 224608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes this.socketImpl = socketImpl; 225608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 226608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 227608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public int available() throws IOException { 228608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return socketImpl.available(); 229608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 230608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 231608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void close() throws IOException { 232608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes socketImpl.close(); 233608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 234608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 235608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public int read() throws IOException { 236ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes return Streams.readSingleByte(this); 237608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 238608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 239608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public int read(byte[] buffer, int offset, int byteCount) throws IOException { 240608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return socketImpl.read(buffer, offset, byteCount); 241608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2440a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes @Override public Object getOption(int option) throws SocketException { 2450b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return IoBridge.getSocketOption(fd, option); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override protected synchronized OutputStream getOutputStream() throws IOException { 249f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 250608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return new PlainSocketOutputStream(this); 251608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 252608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 253608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private static class PlainSocketOutputStream extends OutputStream { 254608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private final PlainSocketImpl socketImpl; 255608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 256608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes public PlainSocketOutputStream(PlainSocketImpl socketImpl) { 257608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes this.socketImpl = socketImpl; 258608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 259608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 260608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void close() throws IOException { 261608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes socketImpl.close(); 262608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 263608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 264608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void write(int oneByte) throws IOException { 265ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes Streams.writeSingleByte(this, oneByte); 266608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 267608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 268608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void write(byte[] buffer, int offset, int byteCount) throws IOException { 269608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes socketImpl.write(buffer, offset, byteCount); 270608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void listen(int backlog) throws IOException { 2750917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Do nothing for a SOCKS connection. The listen occurs on the 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server during the bind. 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 280e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes try { 281e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes Libcore.os.listen(fd, backlog); 282e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes } catch (ErrnoException errnoException) { 283e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes throw errnoException.rethrowAsSocketException(); 284e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 288c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes public void setOption(int option, Object value) throws SocketException { 2890b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.setSocketOption(fd, option, value); 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the SOCKS proxy server port. 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int socksGetServerPort() { 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server port from proxy. It is unnecessary to check 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyPort" property, since proxy setting should only be 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return addr.getPort(); 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the InetAddress of the SOCKS proxy server. 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InetAddress socksGetServerAddress() throws UnknownHostException { 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String proxyName; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server address from proxy. It is unnecessary to check 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyHost" property, since all proxy setting should be 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getHostName(); 313b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (proxyName == null) { 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getAddress().getHostAddress(); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 31697144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes return InetAddress.getByName(proxyName); 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connect using a SOCKS server. 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 322220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes private void socksConnect(InetAddress applicationServerAddress, int applicationServerPort, int timeout) throws IOException { 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3240b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.connect(fd, socksGetServerAddress(), socksGetServerPort(), timeout); 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 326220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes throw new SocketException("SOCKS connection failed", e); 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksRequestConnection(applicationServerAddress, applicationServerPort); 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedAddress = applicationServerAddress; 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort = applicationServerPort; 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Request a SOCKS connection to the application server given. If the 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * request fails to complete successfully, an exception is thrown. 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksRequestConnection(InetAddress applicationServerAddress, 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort) throws IOException { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_CONNECT, 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project applicationServerAddress, applicationServerPort); 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 3458de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Perform an accept for a SOCKS bind. 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void socksAccept() throws IOException { 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 3558de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the input portion of the socket. 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownInput() throws IOException { 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project shutdownInput = true; 36559e4744d27231f260271dbbca406e0cc39768116Elliott Hughes try { 36659e4744d27231f260271dbbca406e0cc39768116Elliott Hughes Libcore.os.shutdown(fd, SHUT_RD); 36759e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } catch (ErrnoException errnoException) { 368454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes throw errnoException.rethrowAsSocketException(); 36959e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the output portion of the socket. 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownOutput() throws IOException { 37759e4744d27231f260271dbbca406e0cc39768116Elliott Hughes try { 37859e4744d27231f260271dbbca406e0cc39768116Elliott Hughes Libcore.os.shutdown(fd, SHUT_WR); 37959e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } catch (ErrnoException errnoException) { 380454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes throw errnoException.rethrowAsSocketException(); 38159e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Bind using a SOCKS server. 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksBind() throws IOException { 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3890b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.connect(fd, socksGetServerAddress(), socksGetServerPort()); 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 391220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes throw new IOException("Unable to connect to SOCKS server", e); 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 394220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes // There must be a connection to an application host for the bind to work. 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lastConnectedAddress == null) { 396b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Invalid SOCKS client"); 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use the last connected address and port in the bind request. 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_BIND, lastConnectedAddress, 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort); 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 4050eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // A peculiarity of socks 4 - if the address returned is 0, use the 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // original socks server address. 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getIP() == 0) { 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = socksGetServerAddress(); 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // IPv6 support not yet required as 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // currently the Socks4Message.getIP() only returns int, 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // so only works with IPv4 4byte addresses 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] replyBytes = new byte[4]; 417f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes Memory.pokeInt(replyBytes, 0, reply.getIP(), ByteOrder.BIG_ENDIAN); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = InetAddress.getByAddress(replyBytes); 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project localport = reply.getPort(); 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Send a SOCKS V4 request. 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 4260eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes private void socksSendRequest(int command, InetAddress address, int port) throws IOException { 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message request = new Socks4Message(); 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setCommandOrResult(command); 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setPort(port); 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setIP(address.getAddress()); 431f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes request.setUserId("default"); 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getOutputStream().write(request.getBytes(), 0, request.getLength()); 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a SOCKS V4 reply. 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socks4Message socksReadReply() throws IOException { 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = new Socks4Message(); 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bytesRead = 0; 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (bytesRead < Socks4Message.REPLY_LENGTH) { 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = getInputStream().read(reply.getBytes(), bytesRead, 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message.REPLY_LENGTH - bytesRead); 4458de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes if (count == -1) { 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytesRead += count; 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (Socks4Message.REPLY_LENGTH != bytesRead) { 451b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Malformed reply from SOCKS server"); 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return reply; 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 4578de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes protected void connect(SocketAddress remoteAddr, int timeout) throws IOException { 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(inetAddr.getAddress(), inetAddr.getPort(), timeout); 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean supportsUrgentData() { 46479ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes return true; 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void sendUrgentData(int value) throws IOException { 46990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes try { 47090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes byte[] buffer = new byte[] { (byte) value }; 47190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes Libcore.os.sendto(fd, buffer, 0, 1, MSG_OOB, null, 0); 47290d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } catch (ErrnoException errnoException) { 47390d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes throw errnoException.rethrowAsSocketException(); 47490d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 477608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes /** 478608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes * For PlainSocketInputStream. 479608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes */ 480608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private int read(byte[] buffer, int offset, int byteCount) throws IOException { 481608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes if (byteCount == 0) { 482608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return 0; 483608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 484608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, byteCount); 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (shutdownInput) { 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 4880b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int readCount = IoBridge.recvfrom(true, fd, buffer, offset, byteCount, 0, null, false); 489f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of zero bytes for a blocking socket means a timeout occurred 49023ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes if (readCount == 0) { 491f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new SocketTimeoutException(); 492f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 493f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of -1 indicates the peer was closed 49423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes if (readCount == -1) { 495f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson shutdownInput = true; 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 49723ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes return readCount; 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 500608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes /** 501608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes * For PlainSocketOutputStream. 502608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes */ 503608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private void write(byte[] buffer, int offset, int byteCount) throws IOException { 504608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, byteCount); 505221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes if (streaming) { 506608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes while (byteCount > 0) { 5070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int bytesWritten = IoBridge.sendto(fd, buffer, offset, byteCount, 0, null, 0); 508608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes byteCount -= bytesWritten; 509608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes offset += bytesWritten; 510608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 511221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes } else { 5123393bc90a5bd4498add5b70df1c43e54e5a2f843Elliott Hughes // Unlike writes to a streaming socket, writes to a datagram 5133393bc90a5bd4498add5b70df1c43e54e5a2f843Elliott Hughes // socket are all-or-nothing, so we don't need a loop here. 5143393bc90a5bd4498add5b70df1c43e54e5a2f843Elliott Hughes // http://code.google.com/p/android/issues/detail?id=15304 5150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.sendto(fd, buffer, offset, byteCount, 0, address, port); 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 519