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 205d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException; 21f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 245d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport java.io.IOException; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 260eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughesimport java.nio.ByteOrder; 27608263018762d64a07276b7c8f58102455ccecc8Elliott Hughesimport java.util.Arrays; 280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge; 2959e4744d27231f260271dbbca406e0cc39768116Elliott Hughesimport libcore.io.Libcore; 30f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesimport libcore.io.Memory; 31ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughesimport libcore.io.Streams; 325d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 358de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes * @hide used in java.nio. 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 37f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonpublic class PlainSocketImpl extends SocketImpl { 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // For SOCKS support. A SOCKS bind() uses the last 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // host connected to in its request. 418de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes private static InetAddress lastConnectedAddress; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 438de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes private static int lastConnectedPort; 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 457738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean streaming = true; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 477738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private boolean shutdownInput; 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 497738141c52b931e103efe7ad62d32a12785bf6b1Elliott Hughes private Proxy proxy; 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 52f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 53f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd) { 54f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 55f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 56f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 57f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 58f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 59f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 60f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(Proxy proxy) { 616b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.proxy = proxy; 63f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 64f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 656b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public PlainSocketImpl() { 666b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson this(new FileDescriptor()); 676b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson } 686b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson 69f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) { 70f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.fd = fd; 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.localport = localport; 72f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.address = addr; 73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.port = port; 74f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (fd.valid()) { 75f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 76f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 77f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 78f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void accept(SocketImpl newImpl) throws IOException { 810917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksBind(); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((PlainSocketImpl) newImpl).socksAccept(); 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 86553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 87553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes try { 88553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes InetSocketAddress peerAddress = new InetSocketAddress(); 89553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes FileDescriptor clientFd = Libcore.os.accept(fd, peerAddress); 90553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 91553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes // TODO: we can't just set newImpl.fd to clientFd because a nio SocketChannel may 92553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes // be sharing the FileDescriptor. http://b//4452981. 93553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes newImpl.fd.setInt$(clientFd.getInt$()); 94553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 95553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes newImpl.address = peerAddress.getAddress(); 96553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes newImpl.port = peerAddress.getPort(); 97553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } catch (ErrnoException errnoException) { 98f4a4259d8a548ab172ca98b702feafcd0ceb1411Elliott Hughes if (errnoException.errno == EAGAIN) { 99553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes throw new SocketTimeoutException(errnoException); 100553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 101553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes throw errnoException.rethrowAsSocketException(); 102553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 10349ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes 10449ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes // Reset the client's inherited read timeout to the Java-specified default of 0. 10549ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes newImpl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(0)); 10649ff8b8582bca20a1adbda1d957220526332a8caElliott Hughes 1070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes newImpl.localport = IoBridge.getSocketLocalPort(newImpl.fd); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1100917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes private boolean usingSocks() { 1110917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes return proxy != null && proxy.type() == Proxy.Type.SOCKS; 1120917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes } 1130917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes 114f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes private void checkNotClosed() throws IOException { 115f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes if (!fd.valid()) { 116f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes throw new SocketException("Socket is closed"); 117f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 118f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes } 119f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized int available() throws IOException { 122f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we need to check if the input has been shutdown. If so 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we should return that there is no data to be read 12597144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes if (shutdownInput) { 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return IoBridge.available(fd); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes @Override protected void bind(InetAddress address, int port) throws IOException { 1320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.bind(fd, address, port); 1338cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes if (port != 0) { 1348cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes this.localport = port; 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1360b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes this.localport = IoBridge.getSocketLocalPort(fd); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 141933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller public void onBind(InetAddress localAddress, int localPort) { 142933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller localport = localPort; 143933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller } 144933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller 145933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller @Override 14658e5a8e6eeaf94d78522e0e9994c4565a3b33fdbJesse Wilson protected synchronized void close() throws IOException { 147f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 148f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller IoBridge.closeAndSignalBlockedThreads(fd); 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 152933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller public void onClose() { 153933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller guard.close(); 154933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller } 155933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller 156933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller @Override 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(String aHost, int aPort) throws IOException { 15897144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes connect(InetAddress.getByName(aHost), aPort); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void connect(InetAddress anAddr, int aPort) throws IOException { 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(anAddr, aPort, 0); 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connects this socket to the specified remote host address/port. 168f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param anAddr 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote host address to connect to 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param aPort 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the remote port to connect to 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a timeout where supported. 0 means no timeout 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs while connecting 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1788cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes private void connect(InetAddress anAddr, int aPort, int timeout) throws IOException { 179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr; 180996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes if (streaming && usingSocks()) { 181996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes socksConnect(anAddr, aPort, 0); 182996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes } else { 1830b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.connect(fd, normalAddr, aPort, timeout); 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 185933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller address = normalAddr; 186933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller port = aPort; 187933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller } 188933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller 189933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller @Override 190933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller public void onConnect(InetAddress remoteAddress, int remotePort) { 191933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller address = remoteAddress; 192933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller port = remotePort; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void create(boolean streaming) throws IOException { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.streaming = streaming; 1980b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes this.fd = IoBridge.socket(streaming); 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 201e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 202e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 20312f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 20412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 20512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 206e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom close(); 207e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 208e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 209e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 212608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override protected synchronized InputStream getInputStream() throws IOException { 213f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 214608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return new PlainSocketInputStream(this); 215608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 216608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 217608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private static class PlainSocketInputStream extends InputStream { 218608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private final PlainSocketImpl socketImpl; 219608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 220608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes public PlainSocketInputStream(PlainSocketImpl socketImpl) { 221608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes this.socketImpl = socketImpl; 222608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 223608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 224608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public int available() throws IOException { 225608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return socketImpl.available(); 226608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 227608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 228608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void close() throws IOException { 229608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes socketImpl.close(); 230608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 231608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 232608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public int read() throws IOException { 233ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes return Streams.readSingleByte(this); 234608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 235608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 236325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { 237325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes return socketImpl.read(buffer, byteOffset, byteCount); 238608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2410a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes @Override public Object getOption(int option) throws SocketException { 2420b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return IoBridge.getSocketOption(fd, option); 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 245608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override protected synchronized OutputStream getOutputStream() throws IOException { 246f9e1294b67778f9b290b9fb6eeda2d7cc7c1c3eeElliott Hughes checkNotClosed(); 247608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return new PlainSocketOutputStream(this); 248608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 249608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 250608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private static class PlainSocketOutputStream extends OutputStream { 251608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private final PlainSocketImpl socketImpl; 252608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 253608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes public PlainSocketOutputStream(PlainSocketImpl socketImpl) { 254608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes this.socketImpl = socketImpl; 255608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 256608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 257608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void close() throws IOException { 258608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes socketImpl.close(); 259608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 260608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 261608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void write(int oneByte) throws IOException { 262ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes Streams.writeSingleByte(this, oneByte); 263608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 264608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes 265608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes @Override public void write(byte[] buffer, int offset, int byteCount) throws IOException { 266608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes socketImpl.write(buffer, offset, byteCount); 267608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void listen(int backlog) throws IOException { 2720917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (usingSocks()) { 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Do nothing for a SOCKS connection. The listen occurs on the 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server during the bind. 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 277e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes try { 278e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes Libcore.os.listen(fd, backlog); 279e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes } catch (ErrnoException errnoException) { 280e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes throw errnoException.rethrowAsSocketException(); 281e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes } 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 285c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes public void setOption(int option, Object value) throws SocketException { 2860b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.setSocketOption(fd, option, value); 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the SOCKS proxy server port. 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int socksGetServerPort() { 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server port from proxy. It is unnecessary to check 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyPort" property, since proxy setting should only be 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return addr.getPort(); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the InetAddress of the SOCKS proxy server. 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InetAddress socksGetServerAddress() throws UnknownHostException { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String proxyName; 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get socks server address from proxy. It is unnecessary to check 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "socksProxyHost" property, since all proxy setting should be 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // determined by ProxySelector. 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = (InetSocketAddress) proxy.address(); 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getHostName(); 310b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (proxyName == null) { 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyName = addr.getAddress().getHostAddress(); 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 31397144c87ada735a82221d7cdf65555b8f063a05aElliott Hughes return InetAddress.getByName(proxyName); 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connect using a SOCKS server. 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 319220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes private void socksConnect(InetAddress applicationServerAddress, int applicationServerPort, int timeout) throws IOException { 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3210b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.connect(fd, socksGetServerAddress(), socksGetServerPort(), timeout); 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 323220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes throw new SocketException("SOCKS connection failed", e); 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksRequestConnection(applicationServerAddress, applicationServerPort); 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedAddress = applicationServerAddress; 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort = applicationServerPort; 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Request a SOCKS connection to the application server given. If the 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * request fails to complete successfully, an exception is thrown. 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksRequestConnection(InetAddress applicationServerAddress, 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int applicationServerPort) throws IOException { 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_CONNECT, 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project applicationServerAddress, applicationServerPort); 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 3428de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Perform an accept for a SOCKS bind. 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void socksAccept() throws IOException { 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 3528de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the input portion of the socket. 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownInput() throws IOException { 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project shutdownInput = true; 36259e4744d27231f260271dbbca406e0cc39768116Elliott Hughes try { 36359e4744d27231f260271dbbca406e0cc39768116Elliott Hughes Libcore.os.shutdown(fd, SHUT_RD); 36459e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } catch (ErrnoException errnoException) { 365454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes throw errnoException.rethrowAsSocketException(); 36659e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Shutdown the output portion of the socket. 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdownOutput() throws IOException { 37459e4744d27231f260271dbbca406e0cc39768116Elliott Hughes try { 37559e4744d27231f260271dbbca406e0cc39768116Elliott Hughes Libcore.os.shutdown(fd, SHUT_WR); 37659e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } catch (ErrnoException errnoException) { 377454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes throw errnoException.rethrowAsSocketException(); 37859e4744d27231f260271dbbca406e0cc39768116Elliott Hughes } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Bind using a SOCKS server. 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void socksBind() throws IOException { 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 3860b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.connect(fd, socksGetServerAddress(), socksGetServerPort()); 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 388220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes throw new IOException("Unable to connect to SOCKS server", e); 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 391220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes // There must be a connection to an application host for the bind to work. 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lastConnectedAddress == null) { 393b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Invalid SOCKS client"); 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use the last connected address and port in the bind request. 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socksSendRequest(Socks4Message.COMMAND_BIND, lastConnectedAddress, 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lastConnectedPort); 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = socksReadReply(); 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) { 4020eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes throw new IOException(reply.getErrorString(reply.getCommandOrResult())); 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // A peculiarity of socks 4 - if the address returned is 0, use the 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // original socks server address. 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply.getIP() == 0) { 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = socksGetServerAddress(); 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // IPv6 support not yet required as 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // currently the Socks4Message.getIP() only returns int, 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // so only works with IPv4 4byte addresses 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] replyBytes = new byte[4]; 414f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes Memory.pokeInt(replyBytes, 0, reply.getIP(), ByteOrder.BIG_ENDIAN); 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project address = InetAddress.getByAddress(replyBytes); 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project localport = reply.getPort(); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Send a SOCKS V4 request. 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 4230eb70e31581a977afa5df3292d1c96e42e548821Elliott Hughes private void socksSendRequest(int command, InetAddress address, int port) throws IOException { 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message request = new Socks4Message(); 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setCommandOrResult(command); 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setPort(port); 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project request.setIP(address.getAddress()); 428f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes request.setUserId("default"); 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getOutputStream().write(request.getBytes(), 0, request.getLength()); 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a SOCKS V4 reply. 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socks4Message socksReadReply() throws IOException { 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message reply = new Socks4Message(); 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bytesRead = 0; 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (bytesRead < Socks4Message.REPLY_LENGTH) { 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = getInputStream().read(reply.getBytes(), bytesRead, 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Socks4Message.REPLY_LENGTH - bytesRead); 4428de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes if (count == -1) { 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytesRead += count; 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (Socks4Message.REPLY_LENGTH != bytesRead) { 448b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new SocketException("Malformed reply from SOCKS server"); 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return reply; 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 4548de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughes protected void connect(SocketAddress remoteAddr, int timeout) throws IOException { 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(inetAddr.getAddress(), inetAddr.getPort(), timeout); 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean supportsUrgentData() { 46179ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes return true; 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void sendUrgentData(int value) throws IOException { 46690d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes try { 46790d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes byte[] buffer = new byte[] { (byte) value }; 46890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes Libcore.os.sendto(fd, buffer, 0, 1, MSG_OOB, null, 0); 46990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } catch (ErrnoException errnoException) { 47090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes throw errnoException.rethrowAsSocketException(); 47190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 474608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes /** 475608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes * For PlainSocketInputStream. 476608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes */ 477608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private int read(byte[] buffer, int offset, int byteCount) throws IOException { 478608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes if (byteCount == 0) { 479608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes return 0; 480608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 481608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, byteCount); 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (shutdownInput) { 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 4850b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int readCount = IoBridge.recvfrom(true, fd, buffer, offset, byteCount, 0, null, false); 486f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of zero bytes for a blocking socket means a timeout occurred 48723ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes if (readCount == 0) { 488f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new SocketTimeoutException(); 489f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 490f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // Return of -1 indicates the peer was closed 49123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes if (readCount == -1) { 492f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson shutdownInput = true; 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 49423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes return readCount; 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 497608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes /** 498608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes * For PlainSocketOutputStream. 499608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes */ 500608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes private void write(byte[] buffer, int offset, int byteCount) throws IOException { 501608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, byteCount); 502221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes if (streaming) { 503608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes while (byteCount > 0) { 5040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int bytesWritten = IoBridge.sendto(fd, buffer, offset, byteCount, 0, null, 0); 505608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes byteCount -= bytesWritten; 506608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes offset += bytesWritten; 507608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes } 508221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8Elliott Hughes } else { 5093393bc90a5bd4498add5b70df1c43e54e5a2f843Elliott Hughes // Unlike writes to a streaming socket, writes to a datagram 5103393bc90a5bd4498add5b70df1c43e54e5a2f843Elliott Hughes // socket are all-or-nothing, so we don't need a loop here. 5113393bc90a5bd4498add5b70df1c43e54e5a2f843Elliott Hughes // http://code.google.com/p/android/issues/detail?id=15304 5120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.sendto(fd, buffer, offset, byteCount, 0, address, port); 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 516