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