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