(injector: Injector, profile: SSHProfile, multiplex = true)
| 74 | } |
| 75 | |
| 76 | async setupOneSession (injector: Injector, profile: SSHProfile, multiplex = true): Promise<SSHSession> { |
| 77 | let session = await this.sshMultiplexer.getSession(profile) |
| 78 | if (!multiplex || !session || !profile.options.reuseSession) { |
| 79 | session = new SSHSession(injector, profile) |
| 80 | |
| 81 | if (profile.options.jumpHost) { |
| 82 | const jumpConnection = (await this.profilesService.getProfiles()).find(x => x.id === profile.options.jumpHost) |
| 83 | |
| 84 | if (!jumpConnection) { |
| 85 | throw new Error(`${profile.options.host}: jump host "${profile.options.jumpHost}" not found in your config`) |
| 86 | } |
| 87 | |
| 88 | const jumpSession = await this.setupOneSession( |
| 89 | this.injector, |
| 90 | this.profilesService.getConfigProxyForProfile<SSHProfile>(jumpConnection), |
| 91 | ) |
| 92 | |
| 93 | jumpSession.ref() |
| 94 | session.willDestroy$.subscribe(() => jumpSession.unref()) |
| 95 | jumpSession.willDestroy$.subscribe(() => { |
| 96 | if (session?.open) { |
| 97 | session.destroy() |
| 98 | } |
| 99 | }) |
| 100 | |
| 101 | if (!(jumpSession.ssh instanceof russh.AuthenticatedSSHClient)) { |
| 102 | throw new Error('Jump session is not authenticated yet somehow') |
| 103 | } |
| 104 | |
| 105 | try { |
| 106 | session.jumpChannel = await jumpSession.ssh.openTCPForwardChannel({ |
| 107 | addressToConnectTo: profile.options.host, |
| 108 | portToConnectTo: profile.options.port ?? 22, |
| 109 | originatorAddress: '127.0.0.1', |
| 110 | originatorPort: 0, |
| 111 | }) |
| 112 | } catch (err) { |
| 113 | jumpSession.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not set up port forward on ${jumpConnection.name}`) |
| 114 | throw err |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | this.attachSessionHandler(session.serviceMessage$, msg => { |
| 120 | msg = msg.replace(/\n/g, '\r\n ') |
| 121 | this.write(`\r${colors.black.bgWhite(' SSH ')} ${msg}\r\n`) |
| 122 | }) |
| 123 | |
| 124 | this.attachSessionHandler(session.willDestroy$, () => { |
| 125 | this.activeKIPrompt = null |
| 126 | }) |
| 127 | |
| 128 | this.attachSessionHandler(session.keyboardInteractivePrompt$, prompt => { |
| 129 | this.activeKIPrompt = prompt |
| 130 | setTimeout(() => { |
| 131 | this.frontend?.scrollToBottom() |
| 132 | }) |
| 133 | }) |
no test coverage detected