156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski/* 256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * Copyright (C) 2010 The Android Open Source Project 356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * 456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * Licensed under the Apache License, Version 2.0 (the "License"); 556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * you may not use this file except in compliance with the License. 656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * You may obtain a copy of the License at 756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * 856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * http://www.apache.org/licenses/LICENSE-2.0 956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * 1056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * Unless required by applicable law or agreed to in writing, software 1156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * distributed under the License is distributed on an "AS IS" BASIS, 1256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * See the License for the specific language governing permissions and 1456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * limitations under the License. 1556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski */ 1656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 1756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskipackage com.android.dumprendertree2.forwarder; 1856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 1956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport android.util.Log; 2056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 215af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowskiimport com.android.dumprendertree2.FsUtils; 225af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski 2356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.io.IOException; 2456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.io.InputStream; 2556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.io.OutputStream; 2656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.net.Socket; 2756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 2856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski/** 2956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * Worker class for {@link Forwarder}. A ConnectionHandler will be created once the Forwarder 3056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * accepts an incoming connection, and it will then forward the incoming/outgoing streams to a 3156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * connection already proxied by adb networking (see also {@link AdbUtils}). 3256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski */ 3356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskipublic class ConnectionHandler { 3456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 3556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private static final String LOG_TAG = "ConnectionHandler"; 3656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 375926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski public static interface OnFinishedCallback { 385926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski public void onFinished(); 395926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 405926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski 4156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private class SocketPipeThread extends Thread { 4256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 435af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private InputStream mInputStream; 445af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private OutputStream mOutputStream; 4556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 465af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski public SocketPipeThread(InputStream inputStream, OutputStream outputStream) { 475af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mInputStream = inputStream; 485af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mOutputStream = outputStream; 495af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski setName("SocketPipeThread: " + getName()); 5056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 5156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 5256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski @Override 5356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public void run() { 5456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski byte[] buffer = new byte[4096]; 5556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski int length; 5656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski while (true) { 5756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski try { 585af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski if ((length = mInputStream.read(buffer)) < 0) { 59ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski break; 6056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 615af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mOutputStream.write(buffer, 0, length); 6256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } catch (IOException e) { 6356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski /** This exception means one of the streams is closed */ 6456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski Log.v(LOG_TAG, this.toString(), e); 6556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski break; 6656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 6756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 685926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski 69bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski synchronized (mThreadsRunning) { 70bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski mThreadsRunning--; 71bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski if (mThreadsRunning == 0) { 72bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski ConnectionHandler.this.stop(); 73bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski mOnFinishedCallback.onFinished(); 74bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 75bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 7656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 7756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 7856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski @Override 7956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public String toString() { 805af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski return getName(); 8156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 8256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 8356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 84bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski private Integer mThreadsRunning; 85bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski 8656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private Socket mFromSocket, mToSocket; 8756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private SocketPipeThread mFromToPipe, mToFromPipe; 885af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private InputStream mFromSocketInputStream, mToSocketInputStream; 895af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private OutputStream mFromSocketOutputStream, mToSocketOutputStream; 905af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski 915af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private int mPort; 925af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private String mRemoteMachineIpAddress; 9356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 945926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski private OnFinishedCallback mOnFinishedCallback; 955926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski 96898bfbd865496855c3a6c792f9e0da011ae34854Steve Block public ConnectionHandler(String remoteMachineIp, int port, Socket fromSocket, Socket toSocket) 97898bfbd865496855c3a6c792f9e0da011ae34854Steve Block throws IOException { 985af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mRemoteMachineIpAddress = remoteMachineIp; 995af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mPort = port; 1005af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski 10156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mFromSocket = fromSocket; 10256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mToSocket = toSocket; 1035af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski 1045af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski try { 1055af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mFromSocketInputStream = mFromSocket.getInputStream(); 1065af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mToSocketInputStream = mToSocket.getInputStream(); 1075af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mFromSocketOutputStream = mFromSocket.getOutputStream(); 1085af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mToSocketOutputStream = mToSocket.getOutputStream(); 109898bfbd865496855c3a6c792f9e0da011ae34854Steve Block AdbUtils.configureConnection(mToSocketInputStream, mToSocketOutputStream, 110898bfbd865496855c3a6c792f9e0da011ae34854Steve Block mRemoteMachineIpAddress, mPort); 1115af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski } catch (IOException e) { 1125af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski Log.e(LOG_TAG, "Unable to start ConnectionHandler", e); 1135af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski closeStreams(); 114898bfbd865496855c3a6c792f9e0da011ae34854Steve Block throw e; 1155af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski } 1165af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski 1175af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mFromToPipe = new SocketPipeThread(mFromSocketInputStream, mToSocketOutputStream); 1185af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski mToFromPipe = new SocketPipeThread(mToSocketInputStream, mFromSocketOutputStream); 11956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 12056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 1215926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski public void registerOnConnectionHandlerFinishedCallback(OnFinishedCallback callback) { 1225926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski mOnFinishedCallback = callback; 1235926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 1245926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski 1255af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski private void closeStreams() { 1265af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski FsUtils.closeInputStream(mFromSocketInputStream); 1275af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski FsUtils.closeInputStream(mToSocketInputStream); 1285af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski FsUtils.closeOutputStream(mFromSocketOutputStream); 1295af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski FsUtils.closeOutputStream(mToSocketOutputStream); 1305af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski } 1315af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski 13256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public void start() { 133bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski /** We have 2 threads running, one for each pipe, that we start here. */ 134bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski mThreadsRunning = 2; 13556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mFromToPipe.start(); 13656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mToFromPipe.start(); 13756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 13856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 13956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public void stop() { 14056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski shutdown(mFromSocket); 14156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski shutdown(mToSocket); 14256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 14356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 14456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private void shutdown(Socket socket) { 145ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski synchronized (mFromToPipe) { 146ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski synchronized (mToFromPipe) { 147ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski /** This will stop the while loop in the run method */ 148ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski try { 1495926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski if (!socket.isInputShutdown()) { 1505926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski socket.shutdownInput(); 1515926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 152ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski } catch (IOException e) { 153ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e); 154ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski } 155ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski try { 1565926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski if (!socket.isOutputShutdown()) { 1575926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski socket.shutdownOutput(); 1585926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 159ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski } catch (IOException e) { 160ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e); 161ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski } 162ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski try { 1635926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski if (!socket.isClosed()) { 1645926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski socket.close(); 1655926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 166ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski } catch (IOException e) { 167ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222Maksymilian Osowski Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e); 16856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 16956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 17056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 17156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 172898bfbd865496855c3a6c792f9e0da011ae34854Steve Block} 173