UNPKG

@signalapp/mock-server

Version:
85 lines (84 loc) 3.28 kB
"use strict"; // Copyright 2026 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only Object.defineProperty(exports, "__esModule", { value: true }); exports.SfuService = void 0; const call_1 = require("./call"); const calling_1 = require("../calling"); const connection_1 = require("./connection"); const srtp_1 = require("./srtp"); const ice_1 = require("./ice"); const crypto_1 = require("./crypto"); /** * Selective Forwarding Unit */ class SfuService { #calls = new Map(); #connections = new Map(); async joinCall(request) { let call = this.#calls.get(request.eraId); if (call == null) { call = new call_1.SfuCall({ creatorUserId: request.userId, roomId: request.roomId, eraId: request.eraId, maxClients: 30, newClientsRequireApproval: request.newClientsRequireApproval, persistApprovalForAllUsersWhoJoin: true, approvedUsers: request.approvedUsers, }); this.#calls.set(call.eraId, call); } if (call.hasClient(request.demuxId)) { throw new calling_1.CallingError(calling_1.CallingErrorCode.DuplicateDemuxIdDetected); } const { serverIceUsername, clientIceUsername } = (0, ice_1.getIceUsernames)({ serverIceUsernameFragment: request.serverIceUsernameFragment, clientIceUsernameFragment: request.clientIceUsernameFragment, }); const clientStatus = call.addClient({ userId: request.userId, demuxId: request.demuxId, isAdmin: request.isAdmin, }); if (clientStatus === call_1.SfuClientStatus.Rejected) { throw new calling_1.CallingError(calling_1.CallingErrorCode.TooManyClients); } const serverKeys = await crypto_1.CallingKeyPair.generate(); const serverSecret = serverKeys.privateKey; const serverPublicKey = serverKeys.publicKey; const sharedSecret = serverSecret.agree(request.clientPublicKey); const strpKeyMaterial = (0, srtp_1.getStrpKeyMaterial)({ sharedSecret, clientHkdfExtraInfo: request.clientHkdfExtraInfo, }); const connectionId = (0, connection_1.getSfuConnectionId)({ eraId: call.eraId, demuxId: request.demuxId, }); const connection = new connection_1.SfuConnection({ connectionId, demuxId: request.demuxId, serverIceUsername, clientIceUsername, serverIcePassword: request.serverIcePassword, clientIcePassword: request.clientIcePassword, strpKeyMaterial, }); this.#connections.set(connectionId, connection); return { serverPublicKey, clientStatus, }; } async peekCall(request) { const call = this.#calls.get(request.eraId); if (call == null) { throw new calling_1.CallingError(calling_1.CallingErrorCode.CallNotFound); } const includePendingUserIds = call.isAdmin(request.userId); const info = call.getInfo(includePendingUserIds); return { info }; } } exports.SfuService = SfuService;