2019-06-29 00:37:23 +02:00
|
|
|
import { ClientConnectionEvent } from "vs/base/parts/ipc/common/ipc";
|
|
|
|
import { ConnectionType } from "vs/platform/remote/common/remoteAgentConnection";
|
2019-06-28 00:34:33 +02:00
|
|
|
import { Emitter } from "vs/base/common/event";
|
|
|
|
import { PersistentProtocol, ISocket } from "vs/base/parts/ipc/common/ipc.net";
|
|
|
|
import { VSBuffer } from "vs/base/common/buffer";
|
|
|
|
|
2019-06-29 00:37:23 +02:00
|
|
|
export interface Server {
|
|
|
|
readonly _onDidClientConnect: Emitter<ClientConnectionEvent>;
|
|
|
|
readonly connections: Map<ConnectionType, Map<string, Connection>>;
|
|
|
|
}
|
|
|
|
|
2019-06-28 00:34:33 +02:00
|
|
|
export abstract class Connection {
|
2019-06-29 00:37:23 +02:00
|
|
|
private readonly _onClose = new Emitter<void>();
|
2019-06-28 00:34:33 +02:00
|
|
|
public readonly onClose = this._onClose.event;
|
|
|
|
|
2019-06-29 00:37:23 +02:00
|
|
|
private timeout: NodeJS.Timeout | undefined;
|
|
|
|
private readonly wait = 1000 * 60 * 60;
|
|
|
|
|
|
|
|
public constructor(
|
|
|
|
protected readonly server: Server,
|
|
|
|
private readonly protocol: PersistentProtocol,
|
|
|
|
) {
|
|
|
|
// onClose seems to mean we want to disconnect, so dispose immediately.
|
|
|
|
this.protocol.onClose(() => this.dispose());
|
|
|
|
|
|
|
|
// If the socket closes, we want to wait before disposing so we can
|
|
|
|
// reconnect.
|
2019-06-28 00:34:33 +02:00
|
|
|
this.protocol.onSocketClose(() => {
|
2019-06-29 00:37:23 +02:00
|
|
|
this.timeout = setTimeout(() => {
|
|
|
|
this.dispose();
|
|
|
|
}, this.wait);
|
2019-06-28 00:34:33 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-29 00:37:23 +02:00
|
|
|
/**
|
|
|
|
* Completely close and clean up the connection. Should only do this once we
|
|
|
|
* don't need or want the connection. It cannot be re-used after this.
|
|
|
|
*/
|
|
|
|
public dispose(): void {
|
|
|
|
this.protocol.sendDisconnect();
|
|
|
|
this.protocol.getSocket().end();
|
|
|
|
this.protocol.dispose();
|
|
|
|
this._onClose.fire();
|
|
|
|
}
|
|
|
|
|
2019-06-28 00:34:33 +02:00
|
|
|
public reconnect(socket: ISocket, buffer: VSBuffer): void {
|
2019-06-29 00:37:23 +02:00
|
|
|
clearTimeout(this.timeout as any); // Not sure why the type doesn't work.
|
2019-06-28 00:34:33 +02:00
|
|
|
this.protocol.beginAcceptReconnection(socket, buffer);
|
|
|
|
this.protocol.endAcceptReconnection();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-29 00:37:23 +02:00
|
|
|
/**
|
|
|
|
* The management connection is used for all the IPC channels.
|
|
|
|
*/
|
2019-06-28 00:34:33 +02:00
|
|
|
export class ManagementConnection extends Connection {
|
2019-06-29 00:37:23 +02:00
|
|
|
public constructor(server: Server, protocol: PersistentProtocol) {
|
|
|
|
super(server, protocol);
|
|
|
|
// This will communicate back to the IPCServer that a new client has
|
|
|
|
// connected.
|
|
|
|
this.server._onDidClientConnect.fire({
|
|
|
|
protocol,
|
|
|
|
onDidClientDisconnect: this.onClose,
|
|
|
|
});
|
|
|
|
}
|
2019-06-28 00:34:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export class ExtensionHostConnection extends Connection {
|
|
|
|
}
|