Home | History | Annotate | Download | only in forwarder
      1 /*
      2  * Copyright (C) 2009 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 
     17 package com.android.dumprendertree.forwarder;
     18 
     19 import android.util.Log;
     20 
     21 import java.io.IOException;
     22 import java.net.ServerSocket;
     23 import java.net.Socket;
     24 import java.util.HashSet;
     25 import java.util.Set;
     26 
     27 /**
     28  *
     29  * A port forwarding server. Listens at specified local port and forward the tcp communications to
     30  * external host/port via adb networking proxy.
     31  *
     32  */
     33 public class ForwardServer {
     34 
     35     private static final String LOGTAG = "ForwardServer";
     36 
     37     private int remotePort;
     38     private int remoteAddress;
     39     private int localPort;
     40     private ServerSocket serverSocket;
     41     private boolean started;
     42 
     43     private Set<Forwarder> forwarders;
     44 
     45     public ForwardServer(int localPort, int remoteAddress, int remotePort) {
     46         this.localPort = localPort;
     47         this.remoteAddress = remoteAddress;
     48         this.remotePort = remotePort;
     49         started = false;
     50         forwarders = new HashSet<Forwarder>();
     51     }
     52 
     53     public synchronized void start() throws IOException {
     54         if(!started) {
     55             serverSocket = new ServerSocket(localPort);
     56             Thread serverThread = new Thread(new ServerRunner(serverSocket));
     57             serverThread.setName(LOGTAG);
     58             serverThread.start();
     59             started = true;
     60         }
     61     }
     62 
     63     public synchronized void stop() {
     64         if(started) {
     65             synchronized (forwarders) {
     66                 for(Forwarder forwarder : forwarders)
     67                     forwarder.stop();
     68                 forwarders.clear();
     69             }
     70             try {
     71                 serverSocket.close();
     72             } catch (IOException ioe) {
     73                 Log.v(LOGTAG, "exception while closing", ioe);
     74             } finally {
     75                 started = false;
     76             }
     77         }
     78     }
     79 
     80     public synchronized boolean isRunning() {
     81         return started;
     82     }
     83 
     84     private class ServerRunner implements Runnable {
     85 
     86         private ServerSocket socket;
     87 
     88         public ServerRunner(ServerSocket socket) {
     89             this.socket = socket;
     90         }
     91 
     92         public void run() {
     93             try {
     94                 while (true) {
     95                     Socket localSocket = socket.accept();
     96                     Socket remoteSocket = AdbUtils.getForwardedSocket(remoteAddress, remotePort);
     97                     if(remoteSocket == null) {
     98                         try {
     99                             localSocket.close();
    100                         } catch (IOException ioe) {
    101                             Log.w(LOGTAG, "error while closing socket", ioe);
    102                         } finally {
    103                             Log.w(LOGTAG, "failed to start forwarding from " + localSocket);
    104                         }
    105                     } else {
    106                         Forwarder forwarder = new Forwarder(localSocket, remoteSocket,
    107                                 ForwardServer.this);
    108                         forwarder.start();
    109                     }
    110                 }
    111             } catch (IOException ioe) {
    112                 return;
    113             }
    114         }
    115     }
    116 
    117     public void register(Forwarder forwarder) {
    118         synchronized (forwarders) {
    119             if(!forwarders.contains(forwarder)) {
    120                 forwarders.add(forwarder);
    121             }
    122         }
    123     }
    124 
    125     public void unregister(Forwarder recyclable) {
    126         synchronized (forwarders) {
    127             if(forwarders.contains(recyclable)) {
    128                 recyclable.stop();
    129                 forwarders.remove(recyclable);
    130             }
    131         }
    132     }
    133 }