ConnectionHandler.java revision ef9a2175ee29b9a9c84ddd0a02d1ec80ab095222
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    private class SocketPipeThread extends Thread {
36
37        private Socket mInSocket, mOutSocket;
38
39        public SocketPipeThread(Socket inSocket, Socket outSocket) {
40            mInSocket = inSocket;
41            mOutSocket = outSocket;
42        }
43
44        @Override
45        public void run() {
46            InputStream is;
47            OutputStream os;
48            try {
49                synchronized (this) {
50                    is = mInSocket.getInputStream();
51                    os = mOutSocket.getOutputStream();
52                }
53            } catch (IOException e) {
54                Log.w(LOG_TAG, this.toString(), e);
55                return;
56            }
57
58            byte[] buffer = new byte[4096];
59            int length;
60            while (true) {
61                try {
62                    if ((length = is.read(buffer)) <= 0) {
63                        break;
64                    }
65                    os.write(buffer, 0, length);
66                } catch (IOException e) {
67                    /** This exception means one of the streams is closed */
68                    Log.v(LOG_TAG, this.toString(), e);
69                    break;
70                }
71            }
72        }
73
74        @Override
75        public String toString() {
76            return "SocketPipeThread:\n" + mInSocket + "\n=>\n" + mOutSocket;
77        }
78    }
79
80    private Socket mFromSocket, mToSocket;
81    private SocketPipeThread mFromToPipe, mToFromPipe;
82
83    public ConnectionHandler(Socket fromSocket, Socket toSocket) {
84        mFromSocket = fromSocket;
85        mToSocket = toSocket;
86        mFromToPipe = new SocketPipeThread(mFromSocket, mToSocket);
87        mToFromPipe = new SocketPipeThread(mToSocket, mFromSocket);
88    }
89
90    public void start() {
91        mFromToPipe.start();
92        mToFromPipe.start();
93    }
94
95    public void stop() {
96        shutdown(mFromSocket);
97        shutdown(mToSocket);
98    }
99
100    private void shutdown(Socket socket) {
101        synchronized (mFromToPipe) {
102            synchronized (mToFromPipe) {
103                /** This will stop the while loop in the run method */
104                try {
105                    socket.shutdownInput();
106                } catch (IOException e) {
107                    Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e);
108                }
109                try {
110                    socket.shutdownOutput();
111                } catch (IOException e) {
112                    Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e);
113                }
114                try {
115                    socket.close();
116                } catch (IOException e) {
117                    Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e);
118                }
119            }
120        }
121    }
122}