open-collaboration-server
Version:
Open Collaboration Server implementation, part of the Open Collaboration Tools project
96 lines • 4.22 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.
// ******************************************************************************
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { inject, injectable } from 'inversify';
import { Deferred, BroadcastMessage, Message } from 'open-collaboration-protocol';
import { nanoid } from 'nanoid';
import { Logger } from './utils/logging.js';
let MessageRelay = class MessageRelay {
logger;
requestMap = new Map();
pushResponse(receiver, message) {
const relayedRequest = this.requestMap.get(message.id.toString());
if (relayedRequest) {
relayedRequest.response.resolve(message);
relayedRequest.dispose();
}
}
sendRequest(target, message, timeoutMs) {
const deferred = new Deferred();
const messageId = message.id;
const key = nanoid(24);
const dispose = () => {
this.requestMap.delete(key);
clearTimeout(timeout);
deferred.reject(new Error('Request timed out'));
};
const timeout = setTimeout(dispose, timeoutMs ?? 30_000);
this.requestMap.set(key, {
id: messageId,
response: deferred,
dispose
});
const targetMessage = {
...message,
id: key
};
target.channel.sendMessage(targetMessage);
return deferred.promise;
}
sendNotification(target, message) {
target.channel.sendMessage(message);
}
sendBroadcast(origin, message) {
try {
const room = origin.room;
message.origin = origin.id;
for (const peer of room.peers) {
if (peer !== origin) {
// Find the key for the target peer
const peerKey = message.metadata.encryption.keys.find(e => e.target === peer.id);
if (peerKey && BroadcastMessage.isEncrypted(message)) {
// Adjust the message to only contain the key for the target peer
// All other keys are not of use for the target peer
const messageWithSingleKey = {
...message,
metadata: {
...message.metadata,
encryption: {
keys: [peerKey]
}
}
};
peer.channel.sendMessage(messageWithSingleKey);
}
else if (!Message.isEncrypted(message)) {
peer.channel.sendMessage(message);
}
else {
// If the sender did not include a key for one of the peers, they cannot decrypt the message
// This is unexpected behavior as every broadcast should be sent to every peer in the room
this.logger.warn(`No key found for peer ${peer.id} in room ${room.id}`);
}
}
}
}
catch (error) {
this.logger.error('Error occurred during broadcast', error);
}
}
};
__decorate([
inject(Logger)
], MessageRelay.prototype, "logger", void 0);
MessageRelay = __decorate([
injectable()
], MessageRelay);
export { MessageRelay };
//# sourceMappingURL=message-relay.js.map