protected ConnectFuture doConnect()

in sshd-core/src/main/java/org/apache/sshd/client/SshClient.java [556:652]


    protected ConnectFuture doConnect(
            HostConfigEntry hostConfig, List<HostConfigEntry> jumps,
            AttributeRepository context, SocketAddress localAddress)
            throws IOException {
        Objects.requireNonNull(hostConfig, "No host configuration");
        String host = ValidateUtils.checkNotNullAndNotEmpty(hostConfig.getHostName(), "No target host");
        int port = hostConfig.getPort();
        ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port);
        Collection<String> hostIds = hostConfig.getIdentities();
        Collection<PathResource> idFiles = GenericUtils.stream(hostIds)
                .map(Paths::get)
                .map(PathResource::new)
                .collect(Collectors.toCollection(() -> new ArrayList<>(hostIds.size())));
        KeyIdentityProvider keys = preloadClientIdentities(idFiles);
        String username = hostConfig.getUsername();
        InetSocketAddress targetAddress = new InetSocketAddress(hostConfig.getHostName(), hostConfig.getPort());
        if (GenericUtils.isNotEmpty(jumps)) {
            ConnectFuture connectFuture = new DefaultConnectFuture(username + "@" + targetAddress, null);
            HostConfigEntry jump = jumps.remove(0);
            ConnectFuture f1 = doConnect(jump, jumps, context, null);
            AtomicReference<Cancellable> toCancel = new AtomicReference<>(f1);
            connectFuture.addListener(c -> {
                if (!c.isCanceled()) {
                    return;
                }
                Cancellable inner = toCancel.get();
                if (inner == null) {
                    return;
                }
                CancelFuture cancellation = inner.cancel();
                if (cancellation == null) {
                    return;
                }
                cancellation.addListener(cf -> {
                    if (cf.isDone()) {
                        c.getCancellation().setCanceled();
                    }
                });
            });
            f1.addListener(f2 -> {
                if (f2.isConnected()) {
                    ClientSession proxySession = f2.getClientSession();
                    try {
                        if (connectFuture.isCanceled()) {
                            proxySession.close(true);
                        }
                        AuthFuture auth = proxySession.auth();
                        toCancel.set(auth);
                        auth.addListener(f3 -> {
                            if (f3.isSuccess()) {
                                try {
                                    SshdSocketAddress address
                                            = new SshdSocketAddress(hostConfig.getHostName(), hostConfig.getPort());
                                    ExplicitPortForwardingTracker tracker = proxySession
                                            .createLocalPortForwardingTracker(SshdSocketAddress.LOCALHOST_ADDRESS, address);
                                    SshdSocketAddress bound = tracker.getBoundAddress();
                                    ConnectFuture f4 = doConnect(hostConfig.getUsername(), bound.toInetSocketAddress(),
                                            context, localAddress, keys, hostConfig);
                                    toCancel.set(f4);
                                    if (connectFuture.isCanceled()) {
                                        f4.cancel();
                                    }
                                    f4.addListener(f5 -> {
                                        if (f5.isConnected()) {
                                            ClientSession clientSession = f5.getClientSession();
                                            clientSession.setAttribute(TARGET_SERVER, address);
                                            connectFuture.setSession(clientSession);
                                            proxySession.addCloseFutureListener(f6 -> clientSession.close(true));
                                            clientSession.addCloseFutureListener(f6 -> proxySession.close(true));
                                        } else {
                                            proxySession.close(true);
                                            connectFuture.setException(f5.getException());
                                        }
                                    });
                                } catch (IOException e) {
                                    proxySession.close(true);
                                    connectFuture.setException(e);
                                }
                            } else {
                                proxySession.close(true);
                                connectFuture.setException(f3.getException());
                            }
                        });
                    } catch (IOException e) {
                        proxySession.close(true);
                        connectFuture.setException(e);
                    }
                } else {
                    connectFuture.setException(f2.getException());
                }
            });
            return connectFuture;
        } else {
            return doConnect(hostConfig.getUsername(), new InetSocketAddress(host, port),
                    context, localAddress, keys, hostConfig);
        }
    }