"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RustEngine = exports.SYNC_LOCK_NAME = void 0; const matrix_sdk_crypto_nodejs_1 = require("@matrix-org/matrix-sdk-crypto-nodejs"); const AsyncLock = require("async-lock"); const Crypto_1 = require("../models/Crypto"); const EncryptionEvent_1 = require("../models/events/EncryptionEvent"); /** * @internal */ exports.SYNC_LOCK_NAME = "sync"; /** * @internal */ class RustEngine { constructor(machine, client) { this.machine = machine; this.client = client; this.lock = new AsyncLock(); } async run() { await this.runOnly(); // run everything, but with syntactic sugar } async runOnly(...types) { // Note: we should not be running this until it runs out, so cache the value into a variable const requests = await this.machine.outgoingRequests(); for (const request of requests) { if (types.length && !types.includes(request.type)) continue; switch (request.type) { case 0 /* RequestType.KeysUpload */: await this.processKeysUploadRequest(request); break; case 1 /* RequestType.KeysQuery */: await this.processKeysQueryRequest(request); break; case 2 /* RequestType.KeysClaim */: await this.processKeysClaimRequest(request); break; case 3 /* RequestType.ToDevice */: await this.processToDeviceRequest(request); break; case 5 /* RequestType.RoomMessage */: throw new Error("Bindings error: Sending room messages is not supported"); case 4 /* RequestType.SignatureUpload */: throw new Error("Bindings error: Backup feature not possible"); case 6 /* RequestType.KeysBackup */: throw new Error("Bindings error: Backup feature not possible"); default: throw new Error("Bindings error: Unrecognized request type: " + request.type); } } } async addTrackedUsers(userIds) { await this.lock.acquire(exports.SYNC_LOCK_NAME, async () => { const uids = userIds.map(u => new matrix_sdk_crypto_nodejs_1.UserId(u)); await this.machine.updateTrackedUsers(uids); const keysClaim = await this.machine.getMissingSessions(uids); if (keysClaim) { await this.processKeysClaimRequest(keysClaim); } }); } async prepareEncrypt(roomId, roomInfo) { // TODO: Handle pre-shared invite keys too const members = (await this.client.getJoinedRoomMembers(roomId)).map(u => new matrix_sdk_crypto_nodejs_1.UserId(u)); let historyVis = 1 /* HistoryVisibility.Joined */; switch (roomInfo.historyVisibility) { case "world_readable": historyVis = 3 /* HistoryVisibility.WorldReadable */; break; case "invited": historyVis = 0 /* HistoryVisibility.Invited */; break; case "shared": historyVis = 2 /* HistoryVisibility.Shared */; break; case "joined": default: // Default and other cases handled by assignment before switch } const encEv = new EncryptionEvent_1.EncryptionEvent({ type: "m.room.encryption", content: roomInfo, }); const settings = new matrix_sdk_crypto_nodejs_1.EncryptionSettings(); settings.algorithm = roomInfo.algorithm === Crypto_1.EncryptionAlgorithm.MegolmV1AesSha2 ? 1 /* RustEncryptionAlgorithm.MegolmV1AesSha2 */ : undefined; settings.historyVisibility = historyVis; settings.rotationPeriod = BigInt(encEv.rotationPeriodMs); settings.rotationPeriodMessages = BigInt(encEv.rotationPeriodMessages); await this.lock.acquire(exports.SYNC_LOCK_NAME, async () => { await this.machine.updateTrackedUsers(members); // just in case we missed some await this.runOnly(1 /* RequestType.KeysQuery */); const keysClaim = await this.machine.getMissingSessions(members); if (keysClaim) { await this.processKeysClaimRequest(keysClaim); } }); await this.lock.acquire(roomId, async () => { const requests = JSON.parse(await this.machine.shareRoomKey(new matrix_sdk_crypto_nodejs_1.RoomId(roomId), members, settings)); for (const req of requests) { await this.actuallyProcessToDeviceRequest(req.txn_id, req.event_type, req.messages); } }); } async processKeysClaimRequest(request) { const resp = await this.client.doRequest("POST", "/_matrix/client/v3/keys/claim", null, JSON.parse(request.body)); await this.machine.markRequestAsSent(request.id, request.type, JSON.stringify(resp)); } async processKeysUploadRequest(request) { const body = JSON.parse(request.body); // delete body["one_time_keys"]; // use this to test MSC3983 const resp = await this.client.doRequest("POST", "/_matrix/client/v3/keys/upload", null, body); await this.machine.markRequestAsSent(request.id, request.type, JSON.stringify(resp)); } async processKeysQueryRequest(request) { const resp = await this.client.doRequest("POST", "/_matrix/client/v3/keys/query", null, JSON.parse(request.body)); await this.machine.markRequestAsSent(request.id, request.type, JSON.stringify(resp)); } async processToDeviceRequest(request) { const req = JSON.parse(request.body); await this.actuallyProcessToDeviceRequest(req.txn_id, req.event_type, req.messages); } async actuallyProcessToDeviceRequest(id, type, messages) { const resp = await this.client.sendToDevices(type, messages); await this.machine.markRequestAsSent(id, 3 /* RequestType.ToDevice */, JSON.stringify(resp)); } } exports.RustEngine = RustEngine; //# sourceMappingURL=RustEngine.js.map