/** * 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); }