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 2156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.io.IOException; 2256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.net.ServerSocket; 2356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.net.Socket; 2456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.util.HashSet; 2556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskiimport java.util.Set; 2656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 2756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski/** 2856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * A port forwarding server. Listens on localhost on specified port and forwards the tcp 2956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski * communications to external socket via adb networking proxy. 3056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski */ 3156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowskipublic class Forwarder extends Thread { 3256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private static final String LOG_TAG = "Forwarder"; 3356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 3456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private int mPort; 3556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private String mRemoteMachineIpAddress; 3656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 3756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private ServerSocket mServerSocket; 3856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 3956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski private Set<ConnectionHandler> mConnectionHandlers = new HashSet<ConnectionHandler>(); 4056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 4156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public Forwarder(int port, String remoteMachineIpAddress) { 4256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mPort = port; 4356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mRemoteMachineIpAddress = remoteMachineIpAddress; 4456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 4556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 4656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski @Override 4756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public void start() { 4856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski Log.i(LOG_TAG, "start(): Starting fowarder on port: " + mPort); 4956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 5056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski try { 5156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mServerSocket = new ServerSocket(mPort); 5256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } catch (IOException e) { 5356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski Log.e(LOG_TAG, "mPort=" + mPort, e); 5456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski return; 5556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 5656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 5756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski super.start(); 5856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 5956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 6056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski @Override 6156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public void run() { 6256d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski while (true) { 63bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski Socket localSocket; 64bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski try { 65bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski localSocket = mServerSocket.accept(); 66bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } catch (IOException e) { 67bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski /** This most likely means that mServerSocket is already closed */ 68bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski Log.w(LOG_TAG, "mPort=" + mPort, e); 69bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski break; 70bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 7156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 72898bfbd865496855c3a6c792f9e0da011ae34854Steve Block Socket remoteSocket = null; 73898bfbd865496855c3a6c792f9e0da011ae34854Steve Block final ConnectionHandler connectionHandler; 74898bfbd865496855c3a6c792f9e0da011ae34854Steve Block try { 75898bfbd865496855c3a6c792f9e0da011ae34854Steve Block remoteSocket = AdbUtils.createSocket(); 76898bfbd865496855c3a6c792f9e0da011ae34854Steve Block connectionHandler = new ConnectionHandler( 77898bfbd865496855c3a6c792f9e0da011ae34854Steve Block mRemoteMachineIpAddress, mPort, localSocket, remoteSocket); 78898bfbd865496855c3a6c792f9e0da011ae34854Steve Block } catch (IOException exception) { 7956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski try { 80bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski localSocket.close(); 8156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } catch (IOException e) { 82bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski Log.e(LOG_TAG, "mPort=" + mPort, e); 8356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 84898bfbd865496855c3a6c792f9e0da011ae34854Steve Block if (remoteSocket != null) { 85898bfbd865496855c3a6c792f9e0da011ae34854Steve Block try { 86898bfbd865496855c3a6c792f9e0da011ae34854Steve Block remoteSocket.close(); 87898bfbd865496855c3a6c792f9e0da011ae34854Steve Block } catch (IOException e) { 88898bfbd865496855c3a6c792f9e0da011ae34854Steve Block Log.e(LOG_TAG, "mPort=" + mPort, e); 89898bfbd865496855c3a6c792f9e0da011ae34854Steve Block } 90898bfbd865496855c3a6c792f9e0da011ae34854Steve Block } 91bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski continue; 92bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 9356d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 94bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski /** 95bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski * We have to close the sockets after the ConnectionHandler finishes, so we 96bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski * don't get "Too may open files" exception. We also remove the ConnectionHandler 97bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski * from the collection to avoid memory issues. 98bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski * */ 99bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski ConnectionHandler.OnFinishedCallback callback = 100bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski new ConnectionHandler.OnFinishedCallback() { 101bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski @Override 102bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski public void onFinished() { 103bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski synchronized (this) { 1045af84db492a0c198377ba4dacc83c5a211e96ff6Maksymilian Osowski if (!mConnectionHandlers.remove(connectionHandler)) { 105bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski assert false : "removeConnectionHandler(): not in the collection"; 106bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 1075926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 108bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 109bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski }; 110bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski connectionHandler.registerOnConnectionHandlerFinishedCallback(callback); 11156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 112bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski synchronized (this) { 1135926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski mConnectionHandlers.add(connectionHandler); 11456d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 115bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski connectionHandler.start(); 11656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 11756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski 118bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski synchronized (this) { 119bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski for (ConnectionHandler connectionHandler : mConnectionHandlers) { 120bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski connectionHandler.stop(); 121bd8c83db8f424a8cfbf94cd4915d7b99b034358cMaksymilian Osowski } 1225926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 1235926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski } 1245926723f82fbdd9b523193e05f901784904b6d38Maksymilian Osowski 12556d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski public void finish() { 12656d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski try { 12756d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski mServerSocket.close(); 12856d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } catch (IOException e) { 12956d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski Log.e(LOG_TAG, "mPort=" + mPort, e); 13056d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 13156d7e400ece64591685c8a21dbb82a94a7bd8010Maksymilian Osowski } 132898bfbd865496855c3a6c792f9e0da011ae34854Steve Block} 133