| 429 | } |
| 430 | |
| 431 | private async connect( |
| 432 | config: SSHConnectionConfig, |
| 433 | timeoutMs: number, |
| 434 | abortSignal?: AbortSignal |
| 435 | ): Promise<SSH2ConnectionEntry> { |
| 436 | const key = makeConnectionKey(config); |
| 437 | try { |
| 438 | const resolved = await resolveSSHConfig(config.host); |
| 439 | const resolvedConfig: ResolvedSSHConfig = { |
| 440 | ...resolved, |
| 441 | port: config.port ?? resolved.port, |
| 442 | identityFiles: config.identityFile |
| 443 | ? [expandLocalPath(config.identityFile)] |
| 444 | : resolved.identityFiles, |
| 445 | }; |
| 446 | const agent = getAgentConfig(); |
| 447 | const baseIdentityFiles = |
| 448 | resolvedConfig.identityFiles.length > 0 ? resolvedConfig.identityFiles : []; |
| 449 | const fallbackIdentityFiles = |
| 450 | baseIdentityFiles.length > 0 |
| 451 | ? baseIdentityFiles |
| 452 | : DEFAULT_IDENTITY_FILES.map((file) => expandLocalPath(file)); |
| 453 | const username = resolvedConfig.user ?? getDefaultUsername(); |
| 454 | const proxyTokens = { |
| 455 | host: resolvedConfig.hostName, |
| 456 | port: resolvedConfig.port, |
| 457 | user: username, |
| 458 | }; |
| 459 | |
| 460 | const attemptConnection = async ( |
| 461 | identityFiles: string[], |
| 462 | agentOverride: string | undefined |
| 463 | ): Promise<SSH2ConnectionEntry> => { |
| 464 | const resolvedConfigWithIdentities: ResolvedSSHConfig = { |
| 465 | ...resolvedConfig, |
| 466 | identityFiles, |
| 467 | }; |
| 468 | |
| 469 | const readableKeys = await resolvePrivateKeys(resolvedConfigWithIdentities.identityFiles); |
| 470 | if (abortSignal?.aborted) { |
| 471 | throw new Error(SSH2_OPERATION_ABORTED_ERROR); |
| 472 | } |
| 473 | const keysToTry: Array<Buffer | undefined> = |
| 474 | readableKeys.length > 0 ? readableKeys : [undefined]; |
| 475 | // Keep the sshPromptService wiring in place so known_hosts-backed |
| 476 | // verification can be restored without changing the public module API. |
| 477 | void sshPromptService; |
| 478 | |
| 479 | const connectWithKey = async ( |
| 480 | privateKey: Buffer | undefined, |
| 481 | reportAuthFailure: boolean |
| 482 | ): Promise<SSH2ConnectionEntry> => { |
| 483 | const proxy = resolvedConfigWithIdentities.proxyCommand |
| 484 | ? spawnProxyCommand(resolvedConfigWithIdentities.proxyCommand, proxyTokens) |
| 485 | : undefined; |
| 486 | |
| 487 | // Lazy-load ssh2 to avoid loading the native sshcrypto.node module at |
| 488 | // startup. Bun doesn't support the libuv functions the NAPI module calls, |