@microsoft/dev-tunnels-connections
Version:
Tunnels library for Visual Studio tools
169 lines • 6.95 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TunnelConnectionBase = void 0;
const dev_tunnels_ssh_1 = require("@microsoft/dev-tunnels-ssh");
const vscode_jsonrpc_1 = require("vscode-jsonrpc");
const connectionStatus_1 = require("./connectionStatus");
const connectionStatusChangedEventArgs_1 = require("./connectionStatusChangedEventArgs");
const refreshingTunnelAccessTokenEventArgs_1 = require("./refreshingTunnelAccessTokenEventArgs");
const utils_1 = require("./utils");
const sshKeepAliveEventArgs_1 = require("./sshKeepAliveEventArgs");
/**
* Tunnel connection base class.
*/
class TunnelConnectionBase {
constructor(
/**
* Gets tunnel access scope for this tunnel session.
*/
tunnelAccessScope) {
this.tunnelAccessScope = tunnelAccessScope;
this.disposeCts = new vscode_jsonrpc_1.CancellationTokenSource();
this.status = connectionStatus_1.ConnectionStatus.None;
this.refreshingTunnelAccessTokenEmitter = new utils_1.TrackingEmitter();
this.connectionStatusChangedEmitter = new vscode_jsonrpc_1.Emitter();
this.retryingTunnelConnectionEmitter = new vscode_jsonrpc_1.Emitter();
this.forwardedPortConnectingEmitter = new vscode_jsonrpc_1.Emitter();
this.keepAliveFailedEmitter = new vscode_jsonrpc_1.Emitter();
this.keepAliveSucceededEmitter = new vscode_jsonrpc_1.Emitter();
/**
* Event for refreshing the tunnel access token.
* The tunnel client will fire this event when it is not able to use the access token it got from the tunnel.
*/
this.refreshingTunnelAccessToken = this.refreshingTunnelAccessTokenEmitter.event;
/**
* Connection status changed event.
*/
this.connectionStatusChanged = this.connectionStatusChangedEmitter.event;
/**
* Event raised when a tunnel connection attempt failed and is about to be retried.
* An event handler can cancel the retry by setting {@link RetryingTunnelConnectionEventArgs.retry} to false.
*/
this.retryingTunnelConnection = this.retryingTunnelConnectionEmitter.event;
/**
* An event which fires when a connection is made to the forwarded port.
*/
this.forwardedPortConnecting = this.forwardedPortConnectingEmitter.event;
/**
* Event raised when a keep-alive message response is not received.
*/
this.keepAliveFailed = this.keepAliveFailedEmitter.event;
/**
* Event raised when a keep-alive message response is received.
*/
this.keepAliveSucceeded = this.keepAliveSucceededEmitter.event;
}
/**
* Gets a value indicathing that this tunnel connection session is disposed.
*/
get isDisposed() {
return this.disposeCts.token.isCancellationRequested;
}
get isRefreshingTunnelAccessTokenEventHandled() {
return this.refreshingTunnelAccessTokenEmitter.isSubscribed;
}
/**
* Gets dispose cancellation token.
*/
get disposeToken() {
return this.disposeCts.token;
}
/**
* Gets the connection status.
*/
get connectionStatus() {
return this.status;
}
/**
* Sets the connection status.
* Throws CancellationError if the session is disposed and the status being set is not ConnectionStatus.Disconnected.
*/
set connectionStatus(value) {
if (this.isDisposed && value !== connectionStatus_1.ConnectionStatus.Disconnected) {
this.throwIfDisposed(`ConnectionStatus: ${value}`);
}
if (value === connectionStatus_1.ConnectionStatus.RefreshingTunnelAccessToken && this.status !== connectionStatus_1.ConnectionStatus.Connecting) {
throw new Error('Refreshing tunnel access token is allowed only when connecting.');
}
if (value !== this.status) {
const previousStatus = this.connectionStatus;
this.status = value;
this.onConnectionStatusChanged(previousStatus, value);
}
}
/**
* Gets the error that caused disconnection.
* Undefined if not yet connected or disconnection was caused by disposing of this object.
*/
get disconnectError() {
return this.error;
}
/**
* Sets the error that caused disconnection.
*/
set disconnectError(e) {
this.error = e;
}
onForwardedPortConnecting(e) {
this.forwardedPortConnectingEmitter.fire(e);
}
/**
* Raises the keep-alive failed event.
*/
onKeepAliveFailed(count) {
this.keepAliveFailedEmitter.fire(new sshKeepAliveEventArgs_1.SshKeepAliveEventArgs(count));
}
/**
* Raises the keep-alive succeeded event.
*/
onKeepAliveSucceeded(count) {
this.keepAliveSucceededEmitter.fire(new sshKeepAliveEventArgs_1.SshKeepAliveEventArgs(count));
}
/**
* Closes and disposes the tunnel session.
*/
dispose() {
this.disposeCts.cancel();
this.connectionStatus = connectionStatus_1.ConnectionStatus.Disconnected;
return Promise.resolve();
}
/**
* Notifies about a connection retry, giving the relay client a chance to delay or cancel it.
*/
onRetrying(event) {
this.retryingTunnelConnectionEmitter.fire(event);
}
/**
* Gets the fresh tunnel access token or undefined if it cannot.
*/
async getFreshTunnelAccessToken(cancellation) {
const event = new refreshingTunnelAccessTokenEventArgs_1.RefreshingTunnelAccessTokenEventArgs(this.tunnelAccessScope, cancellation);
this.refreshingTunnelAccessTokenEmitter.fire(event);
return event.tunnelAccessToken ? await event.tunnelAccessToken : undefined;
}
/**
* Event fired when the connection status has changed.
*/
onConnectionStatusChanged(previousStatus, status) {
// Disconnect error is provided only during disconnection, not disposal.
const disconnectError = this.connectionStatus === connectionStatus_1.ConnectionStatus.Disconnected && !this.isDisposed ? this.disconnectError : undefined;
const event = new connectionStatusChangedEventArgs_1.ConnectionStatusChangedEventArgs(previousStatus, status, disconnectError);
this.connectionStatusChangedEmitter.fire(event);
}
/**
* Throws CancellationError if the tunnel connection is disposed.
*/
throwIfDisposed(message, stack) {
if (this.isDisposed) {
const error = new dev_tunnels_ssh_1.ObjectDisposedError(`The tunnel connection is disposed. ${message}`);
if (stack) {
error.stack = stack;
}
throw error;
}
}
}
exports.TunnelConnectionBase = TunnelConnectionBase;
//# sourceMappingURL=tunnelConnectionBase.js.map