16bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu/* 26bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Copyright (C) 2009 The Android Open Source Project 36bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * 46bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 56bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * you may not use this file except in compliance with the License. 66bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * You may obtain a copy of the License at 76bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * 86bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 96bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * 106bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Unless required by applicable law or agreed to in writing, software 116bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 126bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * See the License for the specific language governing permissions and 146bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * limitations under the License. 156bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu */ 166bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu 17f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhupackage com.android.dumprendertree.forwarder; 18f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 19f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhuimport android.util.Log; 20f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 21f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhuimport java.io.IOException; 22f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhuimport java.io.InputStream; 23f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhuimport java.io.OutputStream; 24f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhuimport java.net.Socket; 25f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 26f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu/** 27f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu * 28f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu * Worker class for {@link ForwardServer}. A Forwarder will be created once the ForwardServer 29f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu * accepts an incoming connection, and it will then forward the incoming/outgoing streams to a 30f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu * connection already proxied by adb networking (see also {@link AdbUtils}). 31f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu * 32f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu */ 33f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhupublic class Forwarder { 34f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 35f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu private ForwardServer server; 36f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu private Socket from, to; 37f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 38f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu private static final String LOGTAG = "Forwarder"; 39f6d1b3f125b06fcc4847be3cfb35e8ce21905676Guang Zhu private static final int BUFFER_SIZE = 16384; 40f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 41f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu public Forwarder (Socket from, Socket to, ForwardServer server) { 42f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu this.server = server; 43f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu this.from = from; 44f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu this.to = to; 45f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu server.register(this); 46f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 47f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 48f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu public void start() { 49f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu Thread outgoing = new Thread(new SocketPipe(from, to)); 50f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu Thread incoming = new Thread(new SocketPipe(to, from)); 51f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu outgoing.setName(LOGTAG); 52f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu incoming.setName(LOGTAG); 53f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu outgoing.start(); 54f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu incoming.start(); 55f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 56f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 57f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu public void stop() { 58f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu shutdown(from); 59f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu shutdown(to); 60f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 61f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 62f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu private void shutdown(Socket socket) { 63f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu try { 64f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu socket.shutdownInput(); 65f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } catch (IOException e) { 66f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu Log.v(LOGTAG, "Socket#shutdownInput", e); 67f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 68f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu try { 69f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu socket.shutdownOutput(); 70f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } catch (IOException e) { 71f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu Log.v(LOGTAG, "Socket#shutdownOutput", e); 72f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 73f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu try { 74f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu socket.close(); 75f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } catch (IOException e) { 76f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu Log.v(LOGTAG, "Socket#close", e); 77f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 78f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 79f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 80f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu private class SocketPipe implements Runnable { 81f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 82f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu private Socket in, out; 83f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 84f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu public SocketPipe(Socket in, Socket out) { 85f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu this.in = in; 86f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu this.out = out; 87f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 88f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 89f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu public void run() { 90f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu try { 91f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu int length; 92f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu InputStream is = in.getInputStream(); 93f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu OutputStream os = out.getOutputStream(); 94f6d1b3f125b06fcc4847be3cfb35e8ce21905676Guang Zhu byte[] buffer = new byte[BUFFER_SIZE]; 95f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu while ((length = is.read(buffer)) > 0) { 96f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu os.write(buffer, 0, length); 97f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 98f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } catch (IOException ioe) { 99f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } finally { 100f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu server.unregister(Forwarder.this); 101f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 102f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 103f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu 104f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu @Override 105f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu public String toString() { 106f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu return "SocketPipe{" + in + "=>" + out + "}"; 107f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 108f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu } 109f4bf552b5a5046e7648f405115ee48917b15b9aaGuang Zhu} 110