/**
  * Tells the Tor OP if it should accept network connections
  *
  * @param enable If true then the Tor OP will accept SOCKS connections, otherwise not.
  * @throws java.io.IOException - IO exceptions
  */
 public synchronized void enableNetwork(boolean enable) throws IOException {
   if (controlConnection == null) {
     throw new RuntimeException("Tor is not running!");
   }
   LOG.info("Enabling network: " + enable);
   controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
 }
 /** Change the values of the configuration options stored in kvMap. */
 public void setConf(Map<String, String> kvMap) throws IOException {
   List<String> lst = new ArrayList<String>();
   for (Iterator<Map.Entry<String, String>> it = kvMap.entrySet().iterator(); it.hasNext(); ) {
     Map.Entry<String, String> ent = it.next();
     lst.add(ent.getKey() + " " + ent.getValue() + "\n");
   }
   setConf(lst);
 }
  /**
   * Publishes a hidden service
   *
   * @param hiddenServicePort The port that the hidden service will accept connections on
   * @param localPort The local port that the hidden service will relay connections to
   * @return The hidden service's onion address in the form X.onion.
   * @throws java.io.IOException - File errors
   */
  public synchronized String publishHiddenService(int hiddenServicePort, int localPort)
      throws IOException {
    if (controlConnection == null) {
      throw new RuntimeException("Service is not running.");
    }

    List<ConfigEntry> currentHiddenServices = controlConnection.getConf("HiddenServiceOptions");

    if ((currentHiddenServices.size() == 1
            && currentHiddenServices.get(0).key.compareTo("HiddenServiceOptions") == 0
            && currentHiddenServices.get(0).value.compareTo("") == 0)
        == false) {
      throw new RuntimeException(
          "Sorry, only one hidden service to a customer and we already have one. Please send complaints to https://github.com/thaliproject/Tor_Onion_Proxy_Library/issues/5 with your scenario so we can justify fixing this.");
    }

    LOG.info("Creating hidden service");
    File hostnameFile = onionProxyContext.getHostNameFile();

    if (hostnameFile.getParentFile().exists() == false
        && hostnameFile.getParentFile().mkdirs() == false) {
      throw new RuntimeException("Could not create hostnameFile parent directory");
    }

    if (hostnameFile.exists() == false && hostnameFile.createNewFile() == false) {
      throw new RuntimeException("Could not create hostnameFile");
    }

    // Watch for the hostname file being created/updated
    WriteObserver hostNameFileObserver = onionProxyContext.generateWriteObserver(hostnameFile);
    // Use the control connection to update the Tor config
    List<String> config =
        Arrays.asList(
            "HiddenServiceDir " + hostnameFile.getParentFile().getAbsolutePath(),
            "HiddenServicePort " + hiddenServicePort + " 127.0.0.1:" + localPort);
    controlConnection.setConf(config);
    controlConnection.saveConf();
    // Wait for the hostname file to be created/updated
    if (!hostNameFileObserver.poll(HOSTNAME_TIMEOUT, MILLISECONDS)) {
      FileUtilities.listFilesToLog(hostnameFile.getParentFile());
      throw new RuntimeException("Wait for hidden service hostname file to be created expired.");
    }

    // Publish the hidden service's onion hostname in transport properties
    String hostname = new String(FileUtilities.read(hostnameFile), "UTF-8").trim();
    LOG.info("Hidden service config has completed.");

    return hostname;
  }
 /**
  * Kills the Tor OP Process. Once you have called this method nothing is going to work until you
  * either call startWithRepeat or installAndStartTorOp
  *
  * @throws java.io.IOException - File errors
  */
 public synchronized void stop() throws IOException {
   try {
     if (controlConnection == null) {
       return;
     }
     LOG.info("Stopping Tor");
     controlConnection.setConf("DisableNetwork", "1");
     controlConnection.shutdownTor("TERM");
   } finally {
     if (controlSocket != null) {
       controlSocket.close();
     }
     controlConnection = null;
     controlSocket = null;
   }
 }
 /** Change the value of the configuration option 'key' to 'val'. */
 public void setConf(String key, String value) throws IOException {
   List<String> lst = new ArrayList<String>();
   lst.add(key + " " + value);
   setConf(lst);
 }