Package com.subgraph.orchid.circuits.path

Source Code of com.subgraph.orchid.circuits.path.CircuitPathChooser

package com.subgraph.orchid.circuits.path;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.subgraph.orchid.Directory;
import com.subgraph.orchid.Router;
import com.subgraph.orchid.TorConfig;
import com.subgraph.orchid.circuits.guards.EntryGuards;
import com.subgraph.orchid.circuits.path.CircuitNodeChooser.WeightRule;
import com.subgraph.orchid.data.IPv4Address;
import com.subgraph.orchid.data.exitpolicy.ExitTarget;

public class CircuitPathChooser {
 
  public static CircuitPathChooser create(TorConfig config, Directory directory) {
    return new CircuitPathChooser(config, directory, new CircuitNodeChooser(config, directory));
  }

  private final Directory directory;
  private final CircuitNodeChooser nodeChooser;
 
  private EntryGuards entryGuards;
  private boolean useEntryGuards;
 
  CircuitPathChooser(TorConfig config, Directory directory, CircuitNodeChooser nodeChooser) {
    this.directory = directory;
    this.nodeChooser = nodeChooser;
    this.entryGuards = null;
    this.useEntryGuards = false;
  }

  public void enableEntryGuards(EntryGuards entryGuards) {
    this.entryGuards = entryGuards;
    this.useEntryGuards = true;
  }

  public List<Router> chooseDirectoryPath() throws InterruptedException {
    if(useEntryGuards && entryGuards.isUsingBridges()) {
      final Set<Router> empty = Collections.emptySet();
      final Router bridge = entryGuards.chooseRandomGuard(empty);
      if(bridge == null) {
        throw new IllegalStateException("Failed to choose bridge for directory request");
      }
      return Arrays.asList(bridge);
    }
    final Router dir = nodeChooser.chooseDirectory();
    return Arrays.asList(dir);
  }
 
  public List<Router> chooseInternalPath() throws InterruptedException, PathSelectionFailedException {
    final Set<Router> excluded = Collections.emptySet();
    final Router finalRouter = chooseMiddleNode(excluded);
    return choosePathWithFinal(finalRouter);
  }

  public List<Router> choosePathWithExit(Router exitRouter) throws InterruptedException, PathSelectionFailedException {
    return choosePathWithFinal(exitRouter);
  }

  public List<Router> choosePathWithFinal(Router finalRouter) throws InterruptedException, PathSelectionFailedException {
    final Set<Router> excluded = new HashSet<Router>();
    excludeChosenRouterAndRelated(finalRouter, excluded);

    final Router middleRouter = chooseMiddleNode(excluded);
    if(middleRouter == null) {
      throw new PathSelectionFailedException("Failed to select suitable middle node");
    }
    excludeChosenRouterAndRelated(middleRouter, excluded);

    final Router entryRouter = chooseEntryNode(excluded);
    if(entryRouter == null) {
      throw new PathSelectionFailedException("Failed to select suitable entry node");
    }
    return Arrays.asList(entryRouter, middleRouter, finalRouter);
  }

  public Router chooseEntryNode(final Set<Router> excludedRouters) throws InterruptedException {
    if(useEntryGuards) {
      return entryGuards.chooseRandomGuard(excludedRouters);
    }

    return nodeChooser.chooseRandomNode(WeightRule.WEIGHT_FOR_GUARD, new RouterFilter() {
      public boolean filter(Router router) {
        return router.isPossibleGuard() && !excludedRouters.contains(router);
      }
    });
  }

  Router chooseMiddleNode(final Set<Router> excludedRouters) {
    return nodeChooser.chooseRandomNode(WeightRule.WEIGHT_FOR_MID, new RouterFilter() {
      public boolean filter(Router router) {
        return router.isFast() && !excludedRouters.contains(router);
      }
    });
  }

  public Router chooseExitNodeForTargets(List<ExitTarget> targets) {
    final List<Router> routers = filterForExitTargets(
        getUsableExitRouters(), targets);
    return nodeChooser.chooseExitNode(routers);
  }
 
  private List<Router> getUsableExitRouters() {
    final List<Router> result = new ArrayList<Router>();
    for(Router r: nodeChooser.getUsableRouters(true)) {
      if(r.isExit() && !r.isBadExit()) {
        result.add(r);
      }
    }
    return result;
  }

  private void excludeChosenRouterAndRelated(Router router, Set<Router> excludedRouters) {
    excludedRouters.add(router);
    for(Router r: directory.getAllRouters()) {
      if(areInSameSlash16(router, r)) {
        excludedRouters.add(r);
      }
    }
   
    for(String s: router.getFamilyMembers()) {
      Router r = directory.getRouterByName(s);
      if(r != null) {
        // Is mutual?
        if(isFamilyMember(r.getFamilyMembers(), router)) {
          excludedRouters.add(r);
        }
      }
    }
  }
 
  private boolean isFamilyMember(Collection<String> familyMemberNames, Router r) {
    for(String s: familyMemberNames) {
      Router member = directory.getRouterByName(s);
      if(member != null && member.equals(r)) {
        return true;
      }
    }
    return false;
  }

  // Are routers r1 and r2 in the same /16 network
  private boolean areInSameSlash16(Router r1, Router r2) {
    final IPv4Address a1 = r1.getAddress();
    final IPv4Address a2 = r2.getAddress();
    final int mask = 0xFFFF0000;
    return (a1.getAddressData() & mask) == (a2.getAddressData() & mask);
  }
 
  private List<Router> filterForExitTargets(List<Router> routers, List<ExitTarget> exitTargets) {
    int bestSupport = 0;
    if(exitTargets.isEmpty()) {
      return routers;
    }
   
    final int[] nSupport = new int[routers.size()];
   
    for(int i = 0; i < routers.size(); i++) {
      final Router r = routers.get(i);
      nSupport[i] = countTargetSupport(r, exitTargets);
      if(nSupport[i] > bestSupport) {
        bestSupport = nSupport[i];
      }
    }
   
    if(bestSupport == 0) {
      return routers;
    }

    final List<Router> results = new ArrayList<Router>();
    for(int i = 0; i < routers.size(); i++) {
      if(nSupport[i] == bestSupport) {
        results.add(routers.get(i));
      }
    }
    return results;
  }

  private int countTargetSupport(Router router, List<ExitTarget> targets) {
    int count = 0;
    for(ExitTarget t: targets) {
      if(routerSupportsTarget(router, t)) {
        count += 1;
      }
    }
    return count;
  }

  private boolean routerSupportsTarget(Router router, ExitTarget target) {
    if(target.isAddressTarget()) {
      return router.exitPolicyAccepts(target.getAddress(), target.getPort());
    } else {
      return router.exitPolicyAccepts(target.getPort());
    }
  }
}
TOP

Related Classes of com.subgraph.orchid.circuits.path.CircuitPathChooser

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.