/**
   * Create a new connected socket. Blocks until the socket is created, unless the connectDelay
   * option (i2p.streaming.connectDelay) is set and greater than zero. If so this will return
   * immediately, and the client may quickly write initial data to the socket and this data will be
   * bundled in the SYN packet.
   *
   * @param peer Destination to connect to
   * @param options I2P socket options to be used for connecting, may be null
   * @return I2PSocket if successful
   * @throws NoRouteToHostException if the peer is not found or not reachable
   * @throws I2PException if there is some other I2P-related problem
   */
  public I2PSocket connect(Destination peer, I2PSocketOptions options)
      throws I2PException, NoRouteToHostException {
    if (options == null) options = _defaultOptions;
    ConnectionOptions opts = null;
    if (options instanceof ConnectionOptions)
      opts = new ConnectionOptions((ConnectionOptions) options);
    else opts = new ConnectionOptions(options);

    if (_log.shouldLog(Log.INFO))
      _log.info(
          "Connecting to "
              + peer.calculateHash().toBase64().substring(0, 6)
              + " with options: "
              + opts);
    // pick the subsession here
    I2PSession session = _session;
    if (!_subsessions.isEmpty()) {
      updateUserDsaList();
      Hash h = peer.calculateHash();
      if (_dsaOnly.contains(h) || (!_userDsaOnly.isEmpty() && _userDsaOnly.contains(h))) {
        // FIXME just taking the first one for now
        for (I2PSession sess : _subsessions) {
          if (sess.getMyDestination().getSigType() == SigType.DSA_SHA1) {
            session = sess;
            break;
          }
        }
      }
    }
    verifySession(session);
    // the following blocks unless connect delay > 0
    Connection con = _connectionManager.connect(peer, opts, session);
    if (con == null)
      throw new TooManyStreamsException("Too many streams, max " + _defaultOptions.getMaxConns());
    I2PSocketFull socket = new I2PSocketFull(con, _context);
    con.setSocket(socket);
    if (con.getConnectionError() != null) {
      con.disconnect(false);
      throw new NoRouteToHostException(con.getConnectionError());
    }
    return socket;
  }