Skip to content

Commit

Permalink
[lssh] force exit on stale web socket
Browse files Browse the repository at this point in the history
  • Loading branch information
akosyakov committed Sep 27, 2023
1 parent 2a6498b commit 88e7188
Showing 1 changed file with 15 additions and 6 deletions.
21 changes: 15 additions & 6 deletions src/local-ssh/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,15 @@ class WebSocketSSHProxy {
localSession.onAuthenticating(async (e) => {
this.flow.workspaceId = e.username ?? '';
this.sendUserStatusFlow('connecting');
e.authenticationPromise = this.authenticateClient(e.username ?? '')
e.authenticationPromise = this.authenticateClient(e.username ?? '', () => {
// in case of stale connection ensure to trigger the reconnect asap
// try gracefully
localSession.close(SshDisconnectReason.connectionLost);
// but if not force exit
setTimeout(() => {
exitProcess(true);
}, 50);
})
.then(async session => {
this.sendUserStatusFlow('connected');
pipeSession = session;
Expand Down Expand Up @@ -237,7 +245,7 @@ class WebSocketSSHProxy {
}
}

private async authenticateClient(username: string) {
private async authenticateClient(username: string, onStale: () => void) {
const workspaceInfo = await this.retryGetWorkspaceInfo(username);
this.flow.instanceId = workspaceInfo.instanceId;
this.flow.userId = workspaceInfo.userId;
Expand All @@ -246,13 +254,13 @@ class WebSocketSSHProxy {
}

if (FORCE_TUNNEL) {
return this.getTunnelSSHConfig(workspaceInfo);
return this.getTunnelSSHConfig(workspaceInfo, onStale);
}
try {
return await this.tryDirectSSH(workspaceInfo);
} catch (e) {
this.sendErrorReport(this.flow, e, 'try direct ssh failed');
return this.getTunnelSSHConfig(workspaceInfo);
return this.getTunnelSSHConfig(workspaceInfo, onStale);
}
}

Expand All @@ -279,7 +287,7 @@ class WebSocketSSHProxy {
}
}

private async getTunnelSSHConfig(workspaceInfo: GetWorkspaceAuthInfoResponse): Promise<SshClientSession> {
private async getTunnelSSHConfig(workspaceInfo: GetWorkspaceAuthInfoResponse, onStale: () => void): Promise<SshClientSession> {
try {
const workspaceWSUrl = `wss://${workspaceInfo.workspaceId}.${workspaceInfo.workspaceHost}`;
const socket = new WebSocket(workspaceWSUrl + '/_supervisor/tunnel/ssh', undefined, {
Expand All @@ -306,7 +314,8 @@ class WebSocketSSHProxy {
// sends out pings plus a conservative assumption of the latency.
pingTimeout = setTimeout(() => {
this.telemetryService.sendUserFlowStatus('stale', this.flow);
socket.terminate();
session.close(SshDisconnectReason.byApplication);
onStale();
}, pingPeriod + 1000);
};
const stopHearbeat = () => {
Expand Down

0 comments on commit 88e7188

Please sign in to comment.