/**
   * Determines if the boot strap process has completed.
   *
   * @return True if complete
   */
  public synchronized boolean isBootstrapped() {
    if (controlConnection == null) {
      return false;
    }

    String phase = null;
    try {
      phase = controlConnection.getInfo("status/bootstrap-phase");
    } catch (IOException e) {
      LOG.warn("Control connection is not responding properly to getInfo", e);
    }

    if (phase != null && phase.contains("PROGRESS=100")) {
      LOG.info("Tor has already bootstrapped");
      return true;
    }

    return false;
  }
  /**
   * Returns the socks port on the IPv4 localhost address that the Tor OP is listening on
   *
   * @return Discovered socks port
   * @throws java.io.IOException - File errors
   */
  public synchronized int getIPv4LocalHostSocksPort() throws IOException {
    if (isRunning() == false) {
      throw new RuntimeException("Tor is not running!");
    }

    // This returns a set of space delimited quoted strings which could be Ipv4, Ipv6 or unix
    // sockets
    String[] socksIpPorts = controlConnection.getInfo("net/listeners/socks").split(" ");

    for (String address : socksIpPorts) {
      if (address.contains("\"127.0.0.1:")) {
        // Remember, the last character will be a " so we have to remove that
        return Integer.parseInt(
            address.substring(address.lastIndexOf(":") + 1, address.length() - 1));
      }
    }

    throw new RuntimeException("We don't have an Ipv4 localhost binding for socks!");
  }