| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.dumprendertree.forwarder; |
| |
| import android.util.Log; |
| |
| import java.io.IOException; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * |
| * A port forwarding server. Listens at specified local port and forward the tcp communications to |
| * external host/port via adb networking proxy. |
| * |
| */ |
| public class ForwardServer { |
| |
| private static final String LOGTAG = "ForwardServer"; |
| |
| private int remotePort; |
| private int remoteAddress; |
| private int localPort; |
| private ServerSocket serverSocket; |
| private boolean started; |
| |
| private Set<Forwarder> forwarders; |
| |
| public ForwardServer(int localPort, int remoteAddress, int remotePort) { |
| this.localPort = localPort; |
| this.remoteAddress = remoteAddress; |
| this.remotePort = remotePort; |
| started = false; |
| forwarders = new HashSet<Forwarder>(); |
| } |
| |
| public synchronized void start() throws IOException { |
| if(!started) { |
| serverSocket = new ServerSocket(localPort); |
| Thread serverThread = new Thread(new ServerRunner(serverSocket)); |
| serverThread.setName(LOGTAG); |
| serverThread.start(); |
| started = true; |
| } |
| } |
| |
| public synchronized void stop() { |
| if(started) { |
| synchronized (forwarders) { |
| for(Forwarder forwarder : forwarders) |
| forwarder.stop(); |
| forwarders.clear(); |
| } |
| try { |
| serverSocket.close(); |
| } catch (IOException ioe) { |
| Log.v(LOGTAG, "exception while closing", ioe); |
| } finally { |
| started = false; |
| } |
| } |
| } |
| |
| public synchronized boolean isRunning() { |
| return started; |
| } |
| |
| private class ServerRunner implements Runnable { |
| |
| private ServerSocket socket; |
| |
| public ServerRunner(ServerSocket socket) { |
| this.socket = socket; |
| } |
| |
| public void run() { |
| try { |
| while (true) { |
| Socket localSocket = socket.accept(); |
| Socket remoteSocket = AdbUtils.getForwardedSocket(remoteAddress, remotePort); |
| if(remoteSocket == null) { |
| try { |
| localSocket.close(); |
| } catch (IOException ioe) { |
| Log.w(LOGTAG, "error while closing socket", ioe); |
| } finally { |
| Log.w(LOGTAG, "failed to start forwarding from " + localSocket); |
| } |
| } else { |
| Forwarder forwarder = new Forwarder(localSocket, remoteSocket, |
| ForwardServer.this); |
| forwarder.start(); |
| } |
| } |
| } catch (IOException ioe) { |
| return; |
| } |
| } |
| } |
| |
| public void register(Forwarder forwarder) { |
| synchronized (forwarders) { |
| if(!forwarders.contains(forwarder)) { |
| forwarders.add(forwarder); |
| } |
| } |
| } |
| |
| public void unregister(Forwarder recyclable) { |
| synchronized (forwarders) { |
| if(forwarders.contains(recyclable)) { |
| recyclable.stop(); |
| forwarders.remove(recyclable); |
| } |
| } |
| } |
| } |