Package com.subgraph.orchid

Source Code of com.subgraph.orchid.TorClient

package com.subgraph.orchid;

import java.security.NoSuchAlgorithmException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.crypto.Cipher;
import javax.net.SocketFactory;

import com.subgraph.orchid.circuits.TorInitializationTracker;
import com.subgraph.orchid.crypto.PRNGFixes;
import com.subgraph.orchid.dashboard.Dashboard;
import com.subgraph.orchid.directory.downloader.DirectoryDownloaderImpl;
import com.subgraph.orchid.sockets.OrchidSocketFactory;

/**
* This class is the main entry-point for running a Tor proxy
* or client.
*/
public class TorClient {
  private final static Logger logger = Logger.getLogger(TorClient.class.getName());
  private final TorConfig config;
  private final Directory directory;
  private final TorInitializationTracker initializationTracker;
  private final ConnectionCache connectionCache;
  private final CircuitManager circuitManager;
  private final SocksPortListener socksListener;
  private final DirectoryDownloaderImpl directoryDownloader;
  private final Dashboard dashboard;

  private boolean isStarted = false;
  private boolean isStopped = false;
 
  private final CountDownLatch readyLatch;
 
  public TorClient() {
    this(null);
  }

  public TorClient(DirectoryStore customDirectoryStore) {
    if(Tor.isAndroidRuntime()) {
      PRNGFixes.apply();
    }
    config = Tor.createConfig();
    directory = Tor.createDirectory(config, customDirectoryStore);
    initializationTracker = Tor.createInitalizationTracker();
    initializationTracker.addListener(createReadyFlagInitializationListener());
    connectionCache = Tor.createConnectionCache(config, initializationTracker);
    directoryDownloader = Tor.createDirectoryDownloader(config, initializationTracker);
    circuitManager = Tor.createCircuitManager(config, directoryDownloader, directory, connectionCache, initializationTracker);
    socksListener = Tor.createSocksPortListener(config, circuitManager);
    readyLatch = new CountDownLatch(1);
    dashboard = new Dashboard();
    dashboard.addRenderables(circuitManager, directoryDownloader, socksListener);
  }

  public TorConfig getConfig() {
    return config;
  }

  public SocketFactory getSocketFactory() {
    return new OrchidSocketFactory(this);
  }

  /**
   * Start running the Tor client service.
   */
  public synchronized void start() {
    if(isStarted) {
      return;
    }
    if(isStopped) {
      throw new IllegalStateException("Cannot restart a TorClient instance.  Create a new instance instead.");
    }
    logger.info("Starting Orchid (version: "+ Tor.getFullVersion() +")");
    verifyUnlimitedStrengthPolicyInstalled();
    directoryDownloader.start(directory);
    circuitManager.startBuildingCircuits();
    if(dashboard.isEnabledByProperty()) {
      dashboard.startListening();
    }
    isStarted = true;
  }
 
  public synchronized void stop() {
    if(!isStarted || isStopped) {
      return;
    }
    try {
      socksListener.stop();
      if(dashboard.isListening()) {
        dashboard.stopListening();
      }
      directoryDownloader.stop();
      circuitManager.stopBuildingCircuits(true);
      directory.close();
      connectionCache.close();
    } catch (Exception e) {
      logger.log(Level.WARNING, "Unexpected exception while shutting down TorClient instance: "+ e, e);
    } finally {
      isStopped = true;
    }
  }
 
  public Directory getDirectory() {
    return directory;
  }
 
  public ConnectionCache getConnectionCache() {
    return connectionCache;
  }

  public CircuitManager getCircuitManager() {
    return circuitManager;
  }

  public void waitUntilReady() throws InterruptedException {
    readyLatch.await();
  }

  public void waitUntilReady(long timeout) throws InterruptedException, TimeoutException {
    if(!readyLatch.await(timeout, TimeUnit.MILLISECONDS)) {
      throw new TimeoutException();
    }
  }
 
  public Stream openExitStreamTo(String hostname, int port) throws InterruptedException, TimeoutException, OpenFailedException {
    ensureStarted();
    return circuitManager.openExitStreamTo(hostname, port);
  }
 
  private synchronized void ensureStarted() {
    if(!isStarted) {
      throw new IllegalStateException("Must call start() first");
    }
  }

  public void enableSocksListener(int port) {
    socksListener.addListeningPort(port);
  }

  public void enableSocksListener() {
    enableSocksListener(9150);
  }
 
  public void enableDashboard() {
    if(!dashboard.isListening()) {
      dashboard.startListening();
    }
  }
 
  public void enableDashboard(int port) {
    dashboard.setListeningPort(port);
    enableDashboard();
  }
 
  public void disableDashboard() {
    if(dashboard.isListening()) {
      dashboard.stopListening();
    }
  }

  public void addInitializationListener(TorInitializationListener listener) {
    initializationTracker.addListener(listener);
  }

  public void removeInitializationListener(TorInitializationListener listener) {
    initializationTracker.removeListener(listener);
  }
 
  private TorInitializationListener createReadyFlagInitializationListener() {
    return new TorInitializationListener() {
      public void initializationProgress(String message, int percent) {}
      public void initializationCompleted() {
        readyLatch.countDown();
      }
    };
  }

  public static void main(String[] args) {
    final TorClient client = new TorClient();
    client.addInitializationListener(createInitalizationListner());
    client.start();
    client.enableSocksListener();
  }

  private static TorInitializationListener createInitalizationListner() {
    return new TorInitializationListener() {
     
      public void initializationProgress(String message, int percent) {
        System.out.println(">>> [ "+ percent + "% ]: "+ message);
      }
     
      public void initializationCompleted() {
        System.out.println("Tor is ready to go!");
      }
    };
  }
 
  private void verifyUnlimitedStrengthPolicyInstalled() {
    try {
      if(Cipher.getMaxAllowedKeyLength("AES") < 256) {
        final String message = "Unlimited Strength Jurisdiction Policy Files are required but not installed.";
        logger.severe(message);
        throw new TorException(message);
      }
    } catch (NoSuchAlgorithmException e) {
      logger.log(Level.SEVERE, "No AES provider found");
      throw new TorException(e);
    catch (NoSuchMethodError e) {
      logger.info("Skipped check for Unlimited Strength Jurisdiction Policy Files");
    }
  }
}
TOP

Related Classes of com.subgraph.orchid.TorClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.