open-collaboration-server
Version:
Open Collaboration Server implementation, part of the Open Collaboration Tools project
155 lines • 4.77 kB
JavaScript
// ******************************************************************************
// Copyright 2024 TypeFox GmbH
// This program and the accompanying materials are made available under the
// terms of the MIT License, which is available in the project root.
// ******************************************************************************
import { Disposable, Emitter, Encoding, DisposableCollection } from 'open-collaboration-protocol';
export class Channel {
onDidCloseEmitter = new Emitter();
onDidDisconnectEmitter = new Emitter();
onDidReconnectEmitter = new Emitter();
onMessageEmitter = new Emitter();
get onClose() {
return this.onDidCloseEmitter.event;
}
get onDisconnect() {
return this.onDidDisconnectEmitter.event;
}
get onReconnect() {
return this.onDidReconnectEmitter.event;
}
get transport() {
return this._transport;
}
set transport(transport) {
this.toDispose.dispose();
this._transport = transport;
if (transport) {
this.toDispose.push(transport.onClose(() => {
this.onDidDisconnectEmitter.fire();
this._transport = undefined;
}));
this.toDispose.push(transport.onMessage(message => {
this.onMessageEmitter.fire(message);
}));
this.onDidReconnectEmitter.fire();
for (const message of this.buffer) {
transport.sendMessage(message);
}
this.buffer = [];
}
}
_transport;
// Buffer to store messages that couldn't be sent yet due to a disconnect
buffer = [];
toDispose = new DisposableCollection();
closeTimeout;
constructor(transport) {
this._transport = transport;
this.toDispose.push(transport.onClose(() => {
this.onDidDisconnectEmitter.fire();
this._transport = undefined;
}));
this.toDispose.push(transport.onMessage(message => {
this.onMessageEmitter.fire(message);
}));
this.onDisconnect(() => {
this.closeTimeout = setTimeout(() => {
this.close();
}, 30_000);
});
this.onReconnect(() => {
if (this.closeTimeout) {
clearTimeout(this.closeTimeout);
this.closeTimeout = undefined;
}
});
}
get onMessage() {
return this.onMessageEmitter.event;
}
sendMessage(message) {
if (this._transport) {
this._transport.sendMessage(message);
}
else {
this.buffer.push(message);
}
}
close() {
this.toDispose.dispose();
this.onDidCloseEmitter.fire();
this.onDidCloseEmitter.dispose();
this.onDidDisconnectEmitter.dispose();
this.onDidReconnectEmitter.dispose();
this.transport?.close();
}
}
export class WebSocketChannel {
onDidCloseEmitter = new Emitter();
get onClose() {
return this.onDidCloseEmitter.event;
}
_socket;
constructor(socket) {
this._socket = socket;
this._socket.onclose = () => {
this.onDidCloseEmitter.fire();
};
}
onMessage(cb) {
const decode = (message) => {
const data = Encoding.decode(new Uint8Array(message));
cb(data);
};
this._socket.on('message', decode);
return Disposable.create(() => {
this._socket.off('message', decode);
});
}
sendMessage(message) {
const buffer = Encoding.encode(message);
this._socket.send(buffer);
}
close() {
this.onDidCloseEmitter.dispose();
this._socket.close();
}
}
export class SocketIoChannel {
onDidCloseEmitter = new Emitter();
get onClose() {
return this.onDidCloseEmitter.event;
}
_socket;
constructor(socket) {
this._socket = socket;
this._socket.on('disconnect', () => {
this.onDidCloseEmitter.fire();
});
}
onMessage(cb) {
const decode = (message) => {
try {
const data = Encoding.decode(new Uint8Array(message));
cb(data);
}
catch (e) {
console.error(e);
}
};
this._socket.on('message', decode);
return Disposable.create(() => {
this._socket.off('message', decode);
});
}
sendMessage(message) {
const buffer = Encoding.encode(message);
this._socket.send(buffer);
}
close() {
this.onDidCloseEmitter.dispose();
this._socket.disconnect(true);
}
}
//# sourceMappingURL=channel.js.map