ConnectionHandler.java revision bd8c83db8f424a8cfbf94cd4915d7b99b034358c
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dumprendertree2.forwarder; 18 19import android.util.Log; 20 21import java.io.IOException; 22import java.io.InputStream; 23import java.io.OutputStream; 24import java.net.Socket; 25 26/** 27 * Worker class for {@link Forwarder}. A ConnectionHandler will be created once the Forwarder 28 * accepts an incoming connection, and it will then forward the incoming/outgoing streams to a 29 * connection already proxied by adb networking (see also {@link AdbUtils}). 30 */ 31public class ConnectionHandler { 32 33 private static final String LOG_TAG = "ConnectionHandler"; 34 35 public static interface OnFinishedCallback { 36 public void onFinished(); 37 } 38 39 private class SocketPipeThread extends Thread { 40 41 private Socket mInSocket, mOutSocket; 42 43 public SocketPipeThread(Socket inSocket, Socket outSocket) { 44 mInSocket = inSocket; 45 mOutSocket = outSocket; 46 } 47 48 @Override 49 public void run() { 50 InputStream is; 51 OutputStream os; 52 try { 53 synchronized (this) { 54 is = mInSocket.getInputStream(); 55 os = mOutSocket.getOutputStream(); 56 } 57 } catch (IOException e) { 58 Log.w(LOG_TAG, this.toString(), e); 59 finish(); 60 return; 61 } 62 63 byte[] buffer = new byte[4096]; 64 int length; 65 while (true) { 66 try { 67 if ((length = is.read(buffer)) <= 0) { 68 break; 69 } 70 os.write(buffer, 0, length); 71 } catch (IOException e) { 72 /** This exception means one of the streams is closed */ 73 Log.v(LOG_TAG, this.toString(), e); 74 break; 75 } 76 } 77 78 finish(); 79 } 80 81 private void finish() { 82 synchronized (mThreadsRunning) { 83 mThreadsRunning--; 84 if (mThreadsRunning == 0) { 85 ConnectionHandler.this.stop(); 86 mOnFinishedCallback.onFinished(); 87 } 88 } 89 } 90 91 @Override 92 public String toString() { 93 return "SocketPipeThread:\n" + mInSocket + "\n=>\n" + mOutSocket; 94 } 95 } 96 97 private Integer mThreadsRunning; 98 99 private Socket mFromSocket, mToSocket; 100 private SocketPipeThread mFromToPipe, mToFromPipe; 101 102 private OnFinishedCallback mOnFinishedCallback; 103 104 public ConnectionHandler(Socket fromSocket, Socket toSocket) { 105 mFromSocket = fromSocket; 106 mToSocket = toSocket; 107 mFromToPipe = new SocketPipeThread(mFromSocket, mToSocket); 108 mToFromPipe = new SocketPipeThread(mToSocket, mFromSocket); 109 } 110 111 public void registerOnConnectionHandlerFinishedCallback(OnFinishedCallback callback) { 112 mOnFinishedCallback = callback; 113 } 114 115 public void start() { 116 /** We have 2 threads running, one for each pipe, that we start here. */ 117 mThreadsRunning = 2; 118 mFromToPipe.start(); 119 mToFromPipe.start(); 120 } 121 122 public void stop() { 123 shutdown(mFromSocket); 124 shutdown(mToSocket); 125 } 126 127 private void shutdown(Socket socket) { 128 synchronized (mFromToPipe) { 129 synchronized (mToFromPipe) { 130 /** This will stop the while loop in the run method */ 131 try { 132 if (!socket.isInputShutdown()) { 133 socket.shutdownInput(); 134 } 135 } catch (IOException e) { 136 Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e); 137 } 138 try { 139 if (!socket.isOutputShutdown()) { 140 socket.shutdownOutput(); 141 } 142 } catch (IOException e) { 143 Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e); 144 } 145 try { 146 if (!socket.isClosed()) { 147 socket.close(); 148 } 149 } catch (IOException e) { 150 Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e); 151 } 152 } 153 } 154 } 155}