132 lines
6.1 KiB
JavaScript
132 lines
6.1 KiB
JavaScript
"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
|