matrix-js-sdk 41.5.0 → 41.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/lib/ReEmitter.js +1 -1
- package/lib/ReEmitter.js.map +1 -1
- package/lib/ToDeviceMessageQueue.js +2 -2
- package/lib/ToDeviceMessageQueue.js.map +1 -1
- package/lib/autodiscovery.js +0 -1
- package/lib/autodiscovery.js.map +1 -1
- package/lib/client.js +112 -165
- package/lib/client.js.map +1 -1
- package/lib/common-crypto/CryptoBackend.js +0 -2
- package/lib/common-crypto/CryptoBackend.js.map +1 -1
- package/lib/content-helpers.js +3 -5
- package/lib/content-helpers.js.map +1 -1
- package/lib/content-repo.js +7 -1
- package/lib/content-repo.js.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store-backend.js +9 -11
- package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store.js +0 -2
- package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
- package/lib/crypto/store/localStorage-crypto-store.js +11 -9
- package/lib/crypto/store/localStorage-crypto-store.js.map +1 -1
- package/lib/crypto/store/memory-crypto-store.js +11 -9
- package/lib/crypto/store/memory-crypto-store.js.map +1 -1
- package/lib/crypto-api/index.js +58 -58
- package/lib/crypto-api/index.js.map +1 -1
- package/lib/embedded.js +29 -45
- package/lib/embedded.js.map +1 -1
- package/lib/extensible_events_v1/MessageEvent.js +15 -15
- package/lib/extensible_events_v1/MessageEvent.js.map +1 -1
- package/lib/extensible_events_v1/PollEndEvent.js +8 -8
- package/lib/extensible_events_v1/PollEndEvent.js.map +1 -1
- package/lib/extensible_events_v1/PollResponseEvent.js +0 -1
- package/lib/extensible_events_v1/PollResponseEvent.js.map +1 -1
- package/lib/extensible_events_v1/PollStartEvent.js +28 -28
- package/lib/extensible_events_v1/PollStartEvent.js.map +1 -1
- package/lib/feature.js +5 -1
- package/lib/feature.js.map +1 -1
- package/lib/filter-component.js +4 -1
- package/lib/filter-component.js.map +1 -1
- package/lib/filter.js +1 -3
- package/lib/filter.js.map +1 -1
- package/lib/http-api/errors.js +20 -16
- package/lib/http-api/errors.js.map +1 -1
- package/lib/http-api/fetch.js +4 -6
- package/lib/http-api/fetch.js.map +1 -1
- package/lib/http-api/refresh.js +10 -12
- package/lib/http-api/refresh.js.map +1 -1
- package/lib/interactive-auth.js +1 -11
- package/lib/interactive-auth.js.map +1 -1
- package/lib/logger.js +0 -2
- package/lib/logger.js.map +1 -1
- package/lib/matrixrtc/CallMembership.js +43 -57
- package/lib/matrixrtc/CallMembership.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js +19 -24
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSessionManager.js +2 -3
- package/lib/matrixrtc/MatrixRTCSessionManager.js.map +1 -1
- package/lib/matrixrtc/MembershipManager.js +23 -30
- package/lib/matrixrtc/MembershipManager.js.map +1 -1
- package/lib/matrixrtc/MembershipManagerActionScheduler.js +1 -2
- package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
- package/lib/matrixrtc/RTCEncryptionManager.js +8 -11
- package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
- package/lib/matrixrtc/ToDeviceKeyTransport.js +4 -4
- package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
- package/lib/matrixrtc/utils.js +7 -1
- package/lib/matrixrtc/utils.js.map +1 -1
- package/lib/models/MSC3089TreeSpace.js +5 -7
- package/lib/models/MSC3089TreeSpace.js.map +1 -1
- package/lib/models/beacon.js +5 -11
- package/lib/models/beacon.js.map +1 -1
- package/lib/models/device.js +0 -7
- package/lib/models/device.js.map +1 -1
- package/lib/models/event-context.js +1 -2
- package/lib/models/event-context.js.map +1 -1
- package/lib/models/event-timeline-set.js +16 -26
- package/lib/models/event-timeline-set.js.map +1 -1
- package/lib/models/event-timeline.js +8 -15
- package/lib/models/event-timeline.js.map +1 -1
- package/lib/models/event.js +20 -37
- package/lib/models/event.js.map +1 -1
- package/lib/models/invites-ignorer.js +8 -12
- package/lib/models/invites-ignorer.js.map +1 -1
- package/lib/models/poll.js +7 -13
- package/lib/models/poll.js.map +1 -1
- package/lib/models/read-receipt.js +8 -4
- package/lib/models/read-receipt.js.map +1 -1
- package/lib/models/related-relations.js +0 -2
- package/lib/models/related-relations.js.map +1 -1
- package/lib/models/relations-container.js +4 -6
- package/lib/models/relations-container.js.map +1 -1
- package/lib/models/relations.js +7 -10
- package/lib/models/relations.js.map +1 -1
- package/lib/models/room-member.js +2 -24
- package/lib/models/room-member.js.map +1 -1
- package/lib/models/room-receipts.js +25 -22
- package/lib/models/room-receipts.js.map +1 -1
- package/lib/models/room-state.js +2 -2
- package/lib/models/room-state.js.map +1 -1
- package/lib/models/room-sticky-events.js +20 -5
- package/lib/models/room-sticky-events.js.map +1 -1
- package/lib/models/room.js +82 -105
- package/lib/models/room.js.map +1 -1
- package/lib/models/thread.js +12 -57
- package/lib/models/thread.js.map +1 -1
- package/lib/models/user.js +1 -20
- package/lib/models/user.js.map +1 -1
- package/lib/oidc/authorize.js +23 -32
- package/lib/oidc/authorize.js.map +1 -1
- package/lib/oidc/tokenRefresher.js +8 -11
- package/lib/oidc/tokenRefresher.js.map +1 -1
- package/lib/pushprocessor.js +8 -5
- package/lib/pushprocessor.js.map +1 -1
- package/lib/receipt-accumulator.js +12 -3
- package/lib/receipt-accumulator.js.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.js +10 -23
- package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
- package/lib/rendezvous/channels/MSC4108SecureChannel.js +5 -10
- package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +1 -1
- package/lib/rendezvous/transports/MSC4108RendezvousSession.js +5 -15
- package/lib/rendezvous/transports/MSC4108RendezvousSession.js.map +1 -1
- package/lib/room-hierarchy.js +7 -12
- package/lib/room-hierarchy.js.map +1 -1
- package/lib/rust-crypto/DehydratedDeviceManager.js +2 -3
- package/lib/rust-crypto/DehydratedDeviceManager.js.map +1 -1
- package/lib/rust-crypto/KeyClaimManager.js +1 -2
- package/lib/rust-crypto/KeyClaimManager.js.map +1 -1
- package/lib/rust-crypto/OutgoingRequestProcessor.js +11 -4
- package/lib/rust-crypto/OutgoingRequestProcessor.js.map +1 -1
- package/lib/rust-crypto/OutgoingRequestsManager.js +12 -12
- package/lib/rust-crypto/OutgoingRequestsManager.js.map +1 -1
- package/lib/rust-crypto/PerSessionKeyBackupDownloader.js +3 -5
- package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
- package/lib/rust-crypto/RoomEncryptor.js +6 -6
- package/lib/rust-crypto/RoomEncryptor.js.map +1 -1
- package/lib/rust-crypto/backup.js +22 -16
- package/lib/rust-crypto/backup.js.map +1 -1
- package/lib/rust-crypto/device-converter.js +13 -4
- package/lib/rust-crypto/device-converter.js.map +1 -1
- package/lib/rust-crypto/index.js +1 -3
- package/lib/rust-crypto/index.js.map +1 -1
- package/lib/rust-crypto/libolm_migration.js +13 -15
- package/lib/rust-crypto/libolm_migration.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.js +52 -59
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/lib/rust-crypto/verification.js +10 -10
- package/lib/rust-crypto/verification.js.map +1 -1
- package/lib/scheduler.js +2 -2
- package/lib/scheduler.js.map +1 -1
- package/lib/secret-storage.js +16 -10
- package/lib/secret-storage.js.map +1 -1
- package/lib/serverCapabilities.js +2 -5
- package/lib/serverCapabilities.js.map +1 -1
- package/lib/sliding-sync-sdk.js +4 -9
- package/lib/sliding-sync-sdk.js.map +1 -1
- package/lib/sliding-sync.js +4 -9
- package/lib/sliding-sync.js.map +1 -1
- package/lib/store/indexeddb-local-backend.js +13 -8
- package/lib/store/indexeddb-local-backend.js.map +1 -1
- package/lib/store/indexeddb-remote-backend.js +6 -7
- package/lib/store/indexeddb-remote-backend.js.map +1 -1
- package/lib/store/indexeddb-store-worker.js +1 -2
- package/lib/store/indexeddb-store-worker.js.map +1 -1
- package/lib/store/indexeddb.js +4 -2
- package/lib/store/indexeddb.js.map +1 -1
- package/lib/store/memory.js +0 -4
- package/lib/store/memory.js.map +1 -1
- package/lib/sync-accumulator.js +2 -4
- package/lib/sync-accumulator.js.map +1 -1
- package/lib/sync.js +36 -43
- package/lib/sync.js.map +1 -1
- package/lib/timeline-window.js +2 -6
- package/lib/timeline-window.js.map +1 -1
- package/lib/utils/decryptAESSecretStorageItem.js +5 -1
- package/lib/utils/decryptAESSecretStorageItem.js.map +1 -1
- package/lib/utils/encryptAESSecretStorageItem.js +5 -1
- package/lib/utils/encryptAESSecretStorageItem.js.map +1 -1
- package/lib/utils.js +35 -20
- package/lib/utils.js.map +1 -1
- package/lib/webrtc/call.js +13 -45
- package/lib/webrtc/call.js.map +1 -1
- package/lib/webrtc/callEventHandler.js +0 -5
- package/lib/webrtc/callEventHandler.js.map +1 -1
- package/lib/webrtc/callFeed.js +0 -15
- package/lib/webrtc/callFeed.js.map +1 -1
- package/lib/webrtc/groupCall.js +82 -89
- package/lib/webrtc/groupCall.js.map +1 -1
- package/lib/webrtc/groupCallEventHandler.js +6 -7
- package/lib/webrtc/groupCallEventHandler.js.map +1 -1
- package/lib/webrtc/mediaHandler.js +8 -15
- package/lib/webrtc/mediaHandler.js.map +1 -1
- package/lib/webrtc/stats/callStatsReportGatherer.js +2 -5
- package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
- package/lib/webrtc/stats/connectionStatsReportBuilder.js +5 -1
- package/lib/webrtc/stats/connectionStatsReportBuilder.js.map +1 -1
- package/lib/webrtc/stats/groupCallStats.js +3 -4
- package/lib/webrtc/stats/groupCallStats.js.map +1 -1
- package/lib/webrtc/stats/media/mediaTrackStats.js +3 -3
- package/lib/webrtc/stats/media/mediaTrackStats.js.map +1 -1
- package/lib/webrtc/stats/media/mediaTrackStatsHandler.js +1 -1
- package/lib/webrtc/stats/media/mediaTrackStatsHandler.js.map +1 -1
- package/package.json +3 -3
- package/src/rendezvous/MSC4108SignInWithQR.ts +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DehydratedDeviceManager.js","names":["RustSdkCryptoJs","encodeUri","Method","decodeBase64","CryptoEvent","TypedEventEmitter","UnstablePrefix","SECRET_STORAGE_NAME","DEHYDRATION_INTERVAL","DehydratedDeviceManager","constructor","logger","olmMachine","http","outgoingRequestProcessor","secretStorage","_defineProperty","cacheKey","key","_this","_asyncToGenerator","dehydratedDevices","saveDehydratedDeviceKey","emit","DehydrationKeyCached","isSupported","_this2","authedRequest","Get","undefined","prefix","error","err","errcode","start","_arguments","arguments","_this3","opts","length","createNewKey","onlyIfKeyCached","getDehydratedDeviceKey","stop","rehydrate","rehydrateDeviceIfAvailable","e","info","RehydrationError","message","resetKey","scheduleDeviceDehydration","isKeyStored","_this4","Boolean","isStored","_this5","DehydratedDeviceKey","createRandomKey","store","toBase64","getKey","create","_this6","cachedKey","keyB64","get","bytes","createKeyFromArray","fill","_this7","dehydratedDeviceResp","RehydrationStarted","rehydratedDevice","DeviceId","device_id","JSON","stringify","device_data","nextBatch","toDeviceCount","roomKeyCount","path","$device_id","eventResp","Post","next_batch","events","roomKeyInfos","receiveEvents","RehydrationProgress","concat","RehydrationCompleted","createAndUploadDehydratedDevice","_this8","dehydratedDevice","DehydratedDeviceCreated","request","keysForUpload","makeOutgoingRequest","DehydratedDeviceUploaded","_this9","intervalId","setInterval","catch","DehydratedDeviceRotationError","clearInterval","delete","_this0","Delete"],"sources":["../../src/rust-crypto/DehydratedDeviceManager.ts"],"sourcesContent":["/*\nCopyright 2024 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport * as RustSdkCryptoJs from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type OutgoingRequestProcessor } from \"./OutgoingRequestProcessor.ts\";\nimport { encodeUri } from \"../utils.ts\";\nimport { type IHttpOpts, type MatrixError, type MatrixHttpApi, Method } from \"../http-api/index.ts\";\nimport { type IToDeviceEvent } from \"../sync-accumulator.ts\";\nimport { type ServerSideSecretStorage } from \"../secret-storage.ts\";\nimport { decodeBase64 } from \"../base64.ts\";\nimport { type Logger } from \"../logger.ts\";\nimport { CryptoEvent, type CryptoEventHandlerMap, type StartDehydrationOpts } from \"../crypto-api/index.ts\";\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\n\n/**\n * The response body of `GET /_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device`.\n */\ninterface DehydratedDeviceResp {\n device_id: string;\n device_data: {\n algorithm: string;\n };\n}\n/**\n * The response body of `POST /_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/events`.\n */\ninterface DehydratedDeviceEventsResp {\n events: IToDeviceEvent[];\n next_batch: string;\n}\n\n/**\n * The unstable URL prefix for dehydrated device endpoints\n */\nexport const UnstablePrefix = \"/_matrix/client/unstable/org.matrix.msc3814.v1\";\n/**\n * The name used for the dehydration key in Secret Storage\n */\nconst SECRET_STORAGE_NAME = \"org.matrix.msc3814\";\n\n/**\n * The interval between creating dehydrated devices. (one week)\n */\nconst DEHYDRATION_INTERVAL = 7 * 24 * 60 * 60 * 1000;\n\n/**\n * Manages dehydrated devices\n *\n * We have one of these per `RustCrypto`. It's responsible for\n *\n * * determining server support for dehydrated devices\n * * creating new dehydrated devices when requested, including periodically\n * replacing the dehydrated device with a new one\n * * rehydrating a device when requested, and when present\n *\n * @internal\n */\nexport class DehydratedDeviceManager extends TypedEventEmitter<DehydratedDevicesEvents, DehydratedDevicesEventMap> {\n /** the ID of the interval for periodically replacing the dehydrated device */\n private intervalId?: ReturnType<typeof setInterval>;\n\n public constructor(\n private readonly logger: Logger,\n private readonly olmMachine: RustSdkCryptoJs.OlmMachine,\n private readonly http: MatrixHttpApi<IHttpOpts & { onlyData: true }>,\n private readonly outgoingRequestProcessor: OutgoingRequestProcessor,\n private readonly secretStorage: ServerSideSecretStorage,\n ) {\n super();\n }\n\n private async cacheKey(key: RustSdkCryptoJs.DehydratedDeviceKey): Promise<void> {\n await this.olmMachine.dehydratedDevices().saveDehydratedDeviceKey(key);\n this.emit(CryptoEvent.DehydrationKeyCached);\n }\n\n /**\n * Return whether the server supports dehydrated devices.\n */\n public async isSupported(): Promise<boolean> {\n // call the endpoint to get a dehydrated device. If it returns an\n // M_UNRECOGNIZED error, then dehydration is unsupported. If it returns\n // a successful response, or an M_NOT_FOUND, then dehydration is supported.\n // Any other exceptions are passed through.\n try {\n await this.http.authedRequest<DehydratedDeviceResp>(\n Method.Get,\n \"/dehydrated_device\",\n undefined,\n undefined,\n {\n prefix: UnstablePrefix,\n },\n );\n } catch (error) {\n const err = error as MatrixError;\n if (err.errcode === \"M_UNRECOGNIZED\") {\n return false;\n } else if (err.errcode === \"M_NOT_FOUND\") {\n return true;\n }\n throw error;\n }\n return true;\n }\n\n /**\n * Start using device dehydration.\n *\n * - Rehydrates a dehydrated device, if one is available and `opts.rehydrate`\n * is `true`.\n * - Creates a new dehydration key, if necessary, and stores it in Secret\n * Storage.\n * - If `opts.createNewKey` is set to true, always creates a new key.\n * - If a dehydration key is not available, creates a new one.\n * - Creates a new dehydrated device, and schedules periodically creating\n * new dehydrated devices.\n *\n * @param opts - options for device dehydration. For backwards compatibility\n * with old code, a boolean can be given here, which will be treated as\n * the `createNewKey` option. However, this is deprecated.\n */\n public async start(opts: StartDehydrationOpts | boolean = {}): Promise<void> {\n if (typeof opts === \"boolean\") {\n opts = { createNewKey: opts };\n }\n\n if (opts.onlyIfKeyCached && !(await this.olmMachine.dehydratedDevices().getDehydratedDeviceKey())) {\n return;\n }\n this.stop();\n if (opts.rehydrate !== false) {\n try {\n await this.rehydrateDeviceIfAvailable();\n } catch (e) {\n // If rehydration fails, there isn't much we can do about it. Log\n // the error, and create a new device.\n this.logger.info(\"dehydration: Error rehydrating device:\", e);\n this.emit(CryptoEvent.RehydrationError, (e as Error).message);\n }\n }\n if (opts.createNewKey) {\n await this.resetKey();\n }\n await this.scheduleDeviceDehydration();\n }\n\n /**\n * Return whether the dehydration key is stored in Secret Storage.\n */\n public async isKeyStored(): Promise<boolean> {\n return Boolean(await this.secretStorage.isStored(SECRET_STORAGE_NAME));\n }\n\n /**\n * Reset the dehydration key.\n *\n * Creates a new key and stores it in secret storage.\n *\n * @returns The newly-generated key.\n */\n public async resetKey(): Promise<RustSdkCryptoJs.DehydratedDeviceKey> {\n const key = RustSdkCryptoJs.DehydratedDeviceKey.createRandomKey();\n await this.secretStorage.store(SECRET_STORAGE_NAME, key.toBase64());\n // Also cache it in the rust SDK's crypto store.\n await this.cacheKey(key);\n return key;\n }\n\n /**\n * Get and cache the encryption key from secret storage.\n *\n * If `create` is `true`, creates a new key if no existing key is present.\n *\n * @returns the key, if available, or `null` if no key is available\n */\n private async getKey(create: boolean): Promise<RustSdkCryptoJs.DehydratedDeviceKey | null> {\n const cachedKey = await this.olmMachine.dehydratedDevices().getDehydratedDeviceKey();\n if (cachedKey) return cachedKey;\n const keyB64 = await this.secretStorage.get(SECRET_STORAGE_NAME);\n if (keyB64 === undefined) {\n if (!create) {\n return null;\n }\n return await this.resetKey();\n }\n\n // We successfully found the key in secret storage: decode it, and cache it in\n // the rust SDK's crypto store.\n const bytes = decodeBase64(keyB64);\n try {\n const key = RustSdkCryptoJs.DehydratedDeviceKey.createKeyFromArray(bytes);\n await this.cacheKey(key);\n return key;\n } finally {\n bytes.fill(0);\n }\n }\n\n /**\n * Rehydrate the dehydrated device stored on the server.\n *\n * Checks if there is a dehydrated device on the server. If so, rehydrates\n * the device and processes the to-device events.\n *\n * Returns whether or not a dehydrated device was found.\n */\n public async rehydrateDeviceIfAvailable(): Promise<boolean> {\n const key = await this.getKey(false);\n if (!key) {\n return false;\n }\n\n let dehydratedDeviceResp;\n try {\n dehydratedDeviceResp = await this.http.authedRequest<DehydratedDeviceResp>(\n Method.Get,\n \"/dehydrated_device\",\n undefined,\n undefined,\n {\n prefix: UnstablePrefix,\n },\n );\n } catch (error) {\n const err = error as MatrixError;\n // We ignore M_NOT_FOUND (there is no dehydrated device, so nothing\n // us to do) and M_UNRECOGNIZED (the server does not understand the\n // endpoint). We pass through any other errors.\n if (err.errcode === \"M_NOT_FOUND\" || err.errcode === \"M_UNRECOGNIZED\") {\n this.logger.info(\"dehydration: No dehydrated device\");\n return false;\n }\n throw err;\n }\n\n this.logger.info(\"dehydration: dehydrated device found\");\n this.emit(CryptoEvent.RehydrationStarted);\n\n const rehydratedDevice = await this.olmMachine\n .dehydratedDevices()\n .rehydrate(\n key,\n new RustSdkCryptoJs.DeviceId(dehydratedDeviceResp.device_id),\n JSON.stringify(dehydratedDeviceResp.device_data),\n );\n\n this.logger.info(\"dehydration: device rehydrated\");\n\n let nextBatch: string | undefined = undefined;\n let toDeviceCount = 0;\n let roomKeyCount = 0;\n const path = encodeUri(\"/dehydrated_device/$device_id/events\", {\n $device_id: dehydratedDeviceResp.device_id,\n });\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const eventResp: DehydratedDeviceEventsResp = await this.http.authedRequest<DehydratedDeviceEventsResp>(\n Method.Post,\n path,\n undefined,\n nextBatch ? { next_batch: nextBatch } : {},\n {\n prefix: UnstablePrefix,\n },\n );\n\n if (eventResp.events.length === 0) {\n break;\n }\n toDeviceCount += eventResp.events.length;\n nextBatch = eventResp.next_batch;\n const roomKeyInfos = await rehydratedDevice.receiveEvents(JSON.stringify(eventResp.events));\n roomKeyCount += roomKeyInfos.length;\n\n this.emit(CryptoEvent.RehydrationProgress, roomKeyCount, toDeviceCount);\n }\n this.logger.info(`dehydration: received ${roomKeyCount} room keys from ${toDeviceCount} to-device events`);\n this.emit(CryptoEvent.RehydrationCompleted);\n\n return true;\n }\n\n /**\n * Creates and uploads a new dehydrated device.\n *\n * Creates and stores a new key in secret storage if none is available.\n */\n public async createAndUploadDehydratedDevice(): Promise<void> {\n const key = (await this.getKey(true))!;\n\n const dehydratedDevice = await this.olmMachine.dehydratedDevices().create();\n this.emit(CryptoEvent.DehydratedDeviceCreated);\n const request = await dehydratedDevice.keysForUpload(\"Dehydrated device\", key);\n\n await this.outgoingRequestProcessor.makeOutgoingRequest(request);\n this.emit(CryptoEvent.DehydratedDeviceUploaded);\n\n this.logger.info(\"dehydration: uploaded device\");\n }\n\n /**\n * Schedule periodic creation of dehydrated devices.\n */\n public async scheduleDeviceDehydration(): Promise<void> {\n // cancel any previously-scheduled tasks\n this.stop();\n\n await this.createAndUploadDehydratedDevice();\n this.intervalId = setInterval(() => {\n this.createAndUploadDehydratedDevice().catch((error) => {\n this.emit(CryptoEvent.DehydratedDeviceRotationError, error.message);\n this.logger.error(\"Error creating dehydrated device:\", error);\n });\n }, DEHYDRATION_INTERVAL);\n }\n\n /**\n * Stop the dehydrated device manager.\n *\n * Cancels any scheduled dehydration tasks.\n */\n public stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n }\n\n /**\n * Delete the current dehydrated device and stop the dehydrated device manager.\n */\n public async delete(): Promise<void> {\n this.stop();\n try {\n await this.http.authedRequest(\n Method.Delete,\n \"/dehydrated_device\",\n undefined,\n {},\n {\n prefix: UnstablePrefix,\n },\n );\n } catch (error) {\n const err = error as MatrixError;\n // If dehydrated devices aren't supported, or no dehydrated device\n // is found, we don't consider it an error, because we we'll end up\n // with no dehydrated device.\n if (err.errcode === \"M_UNRECOGNIZED\") {\n return;\n } else if (err.errcode === \"M_NOT_FOUND\") {\n return;\n }\n throw error;\n }\n }\n}\n\n/**\n * The events fired by the DehydratedDeviceManager\n * @internal\n */\ntype DehydratedDevicesEvents =\n | CryptoEvent.DehydratedDeviceCreated\n | CryptoEvent.DehydratedDeviceUploaded\n | CryptoEvent.RehydrationStarted\n | CryptoEvent.RehydrationProgress\n | CryptoEvent.RehydrationCompleted\n | CryptoEvent.RehydrationError\n | CryptoEvent.DehydrationKeyCached\n | CryptoEvent.DehydratedDeviceRotationError;\n\n/**\n * A map of the {@link DehydratedDeviceEvents} fired by the {@link DehydratedDeviceManager} and their payloads.\n * @internal\n */\ntype DehydratedDevicesEventMap = Pick<CryptoEventHandlerMap, DehydratedDevicesEvents>;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"DehydratedDeviceManager.js","names":["RustSdkCryptoJs","encodeUri","Method","decodeBase64","CryptoEvent","TypedEventEmitter","UnstablePrefix","SECRET_STORAGE_NAME","DEHYDRATION_INTERVAL","DehydratedDeviceManager","constructor","logger","olmMachine","http","outgoingRequestProcessor","secretStorage","cacheKey","key","_this","_asyncToGenerator","dehydratedDevices","saveDehydratedDeviceKey","emit","DehydrationKeyCached","isSupported","_this2","authedRequest","Get","undefined","prefix","error","err","errcode","start","_arguments","arguments","_this3","opts","length","createNewKey","onlyIfKeyCached","getDehydratedDeviceKey","stop","rehydrate","rehydrateDeviceIfAvailable","e","info","RehydrationError","message","resetKey","scheduleDeviceDehydration","isKeyStored","_this4","Boolean","isStored","_this5","DehydratedDeviceKey","createRandomKey","store","toBase64","getKey","create","_this6","cachedKey","keyB64","get","bytes","createKeyFromArray","fill","_this7","dehydratedDeviceResp","RehydrationStarted","rehydratedDevice","DeviceId","device_id","JSON","stringify","device_data","nextBatch","toDeviceCount","roomKeyCount","path","$device_id","eventResp","Post","next_batch","events","roomKeyInfos","receiveEvents","RehydrationProgress","concat","RehydrationCompleted","createAndUploadDehydratedDevice","_this8","dehydratedDevice","DehydratedDeviceCreated","request","keysForUpload","makeOutgoingRequest","DehydratedDeviceUploaded","_this9","intervalId","setInterval","catch","DehydratedDeviceRotationError","clearInterval","delete","_this0","Delete"],"sources":["../../src/rust-crypto/DehydratedDeviceManager.ts"],"sourcesContent":["/*\nCopyright 2024 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport * as RustSdkCryptoJs from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type OutgoingRequestProcessor } from \"./OutgoingRequestProcessor.ts\";\nimport { encodeUri } from \"../utils.ts\";\nimport { type IHttpOpts, type MatrixError, type MatrixHttpApi, Method } from \"../http-api/index.ts\";\nimport { type IToDeviceEvent } from \"../sync-accumulator.ts\";\nimport { type ServerSideSecretStorage } from \"../secret-storage.ts\";\nimport { decodeBase64 } from \"../base64.ts\";\nimport { type Logger } from \"../logger.ts\";\nimport { CryptoEvent, type CryptoEventHandlerMap, type StartDehydrationOpts } from \"../crypto-api/index.ts\";\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\n\n/**\n * The response body of `GET /_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device`.\n */\ninterface DehydratedDeviceResp {\n device_id: string;\n device_data: {\n algorithm: string;\n };\n}\n/**\n * The response body of `POST /_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/events`.\n */\ninterface DehydratedDeviceEventsResp {\n events: IToDeviceEvent[];\n next_batch: string;\n}\n\n/**\n * The unstable URL prefix for dehydrated device endpoints\n */\nexport const UnstablePrefix = \"/_matrix/client/unstable/org.matrix.msc3814.v1\";\n/**\n * The name used for the dehydration key in Secret Storage\n */\nconst SECRET_STORAGE_NAME = \"org.matrix.msc3814\";\n\n/**\n * The interval between creating dehydrated devices. (one week)\n */\nconst DEHYDRATION_INTERVAL = 7 * 24 * 60 * 60 * 1000;\n\n/**\n * Manages dehydrated devices\n *\n * We have one of these per `RustCrypto`. It's responsible for\n *\n * * determining server support for dehydrated devices\n * * creating new dehydrated devices when requested, including periodically\n * replacing the dehydrated device with a new one\n * * rehydrating a device when requested, and when present\n *\n * @internal\n */\nexport class DehydratedDeviceManager extends TypedEventEmitter<DehydratedDevicesEvents, DehydratedDevicesEventMap> {\n /** the ID of the interval for periodically replacing the dehydrated device */\n private intervalId?: ReturnType<typeof setInterval>;\n\n public constructor(\n private readonly logger: Logger,\n private readonly olmMachine: RustSdkCryptoJs.OlmMachine,\n private readonly http: MatrixHttpApi<IHttpOpts & { onlyData: true }>,\n private readonly outgoingRequestProcessor: OutgoingRequestProcessor,\n private readonly secretStorage: ServerSideSecretStorage,\n ) {\n super();\n }\n\n private async cacheKey(key: RustSdkCryptoJs.DehydratedDeviceKey): Promise<void> {\n await this.olmMachine.dehydratedDevices().saveDehydratedDeviceKey(key);\n this.emit(CryptoEvent.DehydrationKeyCached);\n }\n\n /**\n * Return whether the server supports dehydrated devices.\n */\n public async isSupported(): Promise<boolean> {\n // call the endpoint to get a dehydrated device. If it returns an\n // M_UNRECOGNIZED error, then dehydration is unsupported. If it returns\n // a successful response, or an M_NOT_FOUND, then dehydration is supported.\n // Any other exceptions are passed through.\n try {\n await this.http.authedRequest<DehydratedDeviceResp>(\n Method.Get,\n \"/dehydrated_device\",\n undefined,\n undefined,\n {\n prefix: UnstablePrefix,\n },\n );\n } catch (error) {\n const err = error as MatrixError;\n if (err.errcode === \"M_UNRECOGNIZED\") {\n return false;\n } else if (err.errcode === \"M_NOT_FOUND\") {\n return true;\n }\n throw error;\n }\n return true;\n }\n\n /**\n * Start using device dehydration.\n *\n * - Rehydrates a dehydrated device, if one is available and `opts.rehydrate`\n * is `true`.\n * - Creates a new dehydration key, if necessary, and stores it in Secret\n * Storage.\n * - If `opts.createNewKey` is set to true, always creates a new key.\n * - If a dehydration key is not available, creates a new one.\n * - Creates a new dehydrated device, and schedules periodically creating\n * new dehydrated devices.\n *\n * @param opts - options for device dehydration. For backwards compatibility\n * with old code, a boolean can be given here, which will be treated as\n * the `createNewKey` option. However, this is deprecated.\n */\n public async start(opts: StartDehydrationOpts | boolean = {}): Promise<void> {\n if (typeof opts === \"boolean\") {\n opts = { createNewKey: opts };\n }\n\n if (opts.onlyIfKeyCached && !(await this.olmMachine.dehydratedDevices().getDehydratedDeviceKey())) {\n return;\n }\n this.stop();\n if (opts.rehydrate !== false) {\n try {\n await this.rehydrateDeviceIfAvailable();\n } catch (e) {\n // If rehydration fails, there isn't much we can do about it. Log\n // the error, and create a new device.\n this.logger.info(\"dehydration: Error rehydrating device:\", e);\n this.emit(CryptoEvent.RehydrationError, (e as Error).message);\n }\n }\n if (opts.createNewKey) {\n await this.resetKey();\n }\n await this.scheduleDeviceDehydration();\n }\n\n /**\n * Return whether the dehydration key is stored in Secret Storage.\n */\n public async isKeyStored(): Promise<boolean> {\n return Boolean(await this.secretStorage.isStored(SECRET_STORAGE_NAME));\n }\n\n /**\n * Reset the dehydration key.\n *\n * Creates a new key and stores it in secret storage.\n *\n * @returns The newly-generated key.\n */\n public async resetKey(): Promise<RustSdkCryptoJs.DehydratedDeviceKey> {\n const key = RustSdkCryptoJs.DehydratedDeviceKey.createRandomKey();\n await this.secretStorage.store(SECRET_STORAGE_NAME, key.toBase64());\n // Also cache it in the rust SDK's crypto store.\n await this.cacheKey(key);\n return key;\n }\n\n /**\n * Get and cache the encryption key from secret storage.\n *\n * If `create` is `true`, creates a new key if no existing key is present.\n *\n * @returns the key, if available, or `null` if no key is available\n */\n private async getKey(create: boolean): Promise<RustSdkCryptoJs.DehydratedDeviceKey | null> {\n const cachedKey = await this.olmMachine.dehydratedDevices().getDehydratedDeviceKey();\n if (cachedKey) return cachedKey;\n const keyB64 = await this.secretStorage.get(SECRET_STORAGE_NAME);\n if (keyB64 === undefined) {\n if (!create) {\n return null;\n }\n return await this.resetKey();\n }\n\n // We successfully found the key in secret storage: decode it, and cache it in\n // the rust SDK's crypto store.\n const bytes = decodeBase64(keyB64);\n try {\n const key = RustSdkCryptoJs.DehydratedDeviceKey.createKeyFromArray(bytes);\n await this.cacheKey(key);\n return key;\n } finally {\n bytes.fill(0);\n }\n }\n\n /**\n * Rehydrate the dehydrated device stored on the server.\n *\n * Checks if there is a dehydrated device on the server. If so, rehydrates\n * the device and processes the to-device events.\n *\n * Returns whether or not a dehydrated device was found.\n */\n public async rehydrateDeviceIfAvailable(): Promise<boolean> {\n const key = await this.getKey(false);\n if (!key) {\n return false;\n }\n\n let dehydratedDeviceResp;\n try {\n dehydratedDeviceResp = await this.http.authedRequest<DehydratedDeviceResp>(\n Method.Get,\n \"/dehydrated_device\",\n undefined,\n undefined,\n {\n prefix: UnstablePrefix,\n },\n );\n } catch (error) {\n const err = error as MatrixError;\n // We ignore M_NOT_FOUND (there is no dehydrated device, so nothing\n // us to do) and M_UNRECOGNIZED (the server does not understand the\n // endpoint). We pass through any other errors.\n if (err.errcode === \"M_NOT_FOUND\" || err.errcode === \"M_UNRECOGNIZED\") {\n this.logger.info(\"dehydration: No dehydrated device\");\n return false;\n }\n throw err;\n }\n\n this.logger.info(\"dehydration: dehydrated device found\");\n this.emit(CryptoEvent.RehydrationStarted);\n\n const rehydratedDevice = await this.olmMachine\n .dehydratedDevices()\n .rehydrate(\n key,\n new RustSdkCryptoJs.DeviceId(dehydratedDeviceResp.device_id),\n JSON.stringify(dehydratedDeviceResp.device_data),\n );\n\n this.logger.info(\"dehydration: device rehydrated\");\n\n let nextBatch: string | undefined = undefined;\n let toDeviceCount = 0;\n let roomKeyCount = 0;\n const path = encodeUri(\"/dehydrated_device/$device_id/events\", {\n $device_id: dehydratedDeviceResp.device_id,\n });\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const eventResp: DehydratedDeviceEventsResp = await this.http.authedRequest<DehydratedDeviceEventsResp>(\n Method.Post,\n path,\n undefined,\n nextBatch ? { next_batch: nextBatch } : {},\n {\n prefix: UnstablePrefix,\n },\n );\n\n if (eventResp.events.length === 0) {\n break;\n }\n toDeviceCount += eventResp.events.length;\n nextBatch = eventResp.next_batch;\n const roomKeyInfos = await rehydratedDevice.receiveEvents(JSON.stringify(eventResp.events));\n roomKeyCount += roomKeyInfos.length;\n\n this.emit(CryptoEvent.RehydrationProgress, roomKeyCount, toDeviceCount);\n }\n this.logger.info(`dehydration: received ${roomKeyCount} room keys from ${toDeviceCount} to-device events`);\n this.emit(CryptoEvent.RehydrationCompleted);\n\n return true;\n }\n\n /**\n * Creates and uploads a new dehydrated device.\n *\n * Creates and stores a new key in secret storage if none is available.\n */\n public async createAndUploadDehydratedDevice(): Promise<void> {\n const key = (await this.getKey(true))!;\n\n const dehydratedDevice = await this.olmMachine.dehydratedDevices().create();\n this.emit(CryptoEvent.DehydratedDeviceCreated);\n const request = await dehydratedDevice.keysForUpload(\"Dehydrated device\", key);\n\n await this.outgoingRequestProcessor.makeOutgoingRequest(request);\n this.emit(CryptoEvent.DehydratedDeviceUploaded);\n\n this.logger.info(\"dehydration: uploaded device\");\n }\n\n /**\n * Schedule periodic creation of dehydrated devices.\n */\n public async scheduleDeviceDehydration(): Promise<void> {\n // cancel any previously-scheduled tasks\n this.stop();\n\n await this.createAndUploadDehydratedDevice();\n this.intervalId = setInterval(() => {\n this.createAndUploadDehydratedDevice().catch((error) => {\n this.emit(CryptoEvent.DehydratedDeviceRotationError, error.message);\n this.logger.error(\"Error creating dehydrated device:\", error);\n });\n }, DEHYDRATION_INTERVAL);\n }\n\n /**\n * Stop the dehydrated device manager.\n *\n * Cancels any scheduled dehydration tasks.\n */\n public stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n }\n\n /**\n * Delete the current dehydrated device and stop the dehydrated device manager.\n */\n public async delete(): Promise<void> {\n this.stop();\n try {\n await this.http.authedRequest(\n Method.Delete,\n \"/dehydrated_device\",\n undefined,\n {},\n {\n prefix: UnstablePrefix,\n },\n );\n } catch (error) {\n const err = error as MatrixError;\n // If dehydrated devices aren't supported, or no dehydrated device\n // is found, we don't consider it an error, because we we'll end up\n // with no dehydrated device.\n if (err.errcode === \"M_UNRECOGNIZED\") {\n return;\n } else if (err.errcode === \"M_NOT_FOUND\") {\n return;\n }\n throw error;\n }\n }\n}\n\n/**\n * The events fired by the DehydratedDeviceManager\n * @internal\n */\ntype DehydratedDevicesEvents =\n | CryptoEvent.DehydratedDeviceCreated\n | CryptoEvent.DehydratedDeviceUploaded\n | CryptoEvent.RehydrationStarted\n | CryptoEvent.RehydrationProgress\n | CryptoEvent.RehydrationCompleted\n | CryptoEvent.RehydrationError\n | CryptoEvent.DehydrationKeyCached\n | CryptoEvent.DehydratedDeviceRotationError;\n\n/**\n * A map of the {@link DehydratedDeviceEvents} fired by the {@link DehydratedDeviceManager} and their payloads.\n * @internal\n */\ntype DehydratedDevicesEventMap = Pick<CryptoEventHandlerMap, DehydratedDevicesEvents>;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -25,10 +25,9 @@ limitations under the License.
|
|
|
25
25
|
*/
|
|
26
26
|
export class KeyClaimManager {
|
|
27
27
|
constructor(olmMachine, outgoingRequestProcessor) {
|
|
28
|
+
_defineProperty(this, "stopped", false);
|
|
28
29
|
this.olmMachine = olmMachine;
|
|
29
30
|
this.outgoingRequestProcessor = outgoingRequestProcessor;
|
|
30
|
-
_defineProperty(this, "currentClaimPromise", void 0);
|
|
31
|
-
_defineProperty(this, "stopped", false);
|
|
32
31
|
this.currentClaimPromise = Promise.resolve();
|
|
33
32
|
}
|
|
34
33
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyClaimManager.js","names":["KeyClaimManager","constructor","olmMachine","outgoingRequestProcessor","_defineProperty","currentClaimPromise","Promise","resolve","stop","stopped","ensureSessionsForUsers","logger","userList","prom","catch","then","ensureSessionsForUsersInner","_this","_asyncToGenerator","Error","info","claimRequest","getMissingSessions","map","u","clone","makeOutgoingRequest"],"sources":["../../src/rust-crypto/KeyClaimManager.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type OlmMachine, type UserId } from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type OutgoingRequestProcessor } from \"./OutgoingRequestProcessor.ts\";\nimport { type LogSpan } from \"../logger.ts\";\n\n/**\n * KeyClaimManager: linearises calls to OlmMachine.getMissingSessions to avoid races\n *\n * We have one of these per `RustCrypto` (and hence per `MatrixClient`).\n *\n * @internal\n */\nexport class KeyClaimManager {\n private currentClaimPromise: Promise<void>;\n private stopped = false;\n\n public constructor(\n private readonly olmMachine: OlmMachine,\n private readonly outgoingRequestProcessor: OutgoingRequestProcessor,\n ) {\n this.currentClaimPromise = Promise.resolve();\n }\n\n /**\n * Tell the KeyClaimManager to immediately stop processing requests.\n *\n * Any further calls, and any still in the queue, will fail with an error.\n */\n public stop(): void {\n this.stopped = true;\n }\n\n /**\n * Given a list of users, attempt to ensure that we have Olm Sessions active with each of their devices\n *\n * If we don't have an active olm session, we will claim a one-time key and start one.\n * @param logger - logger to use\n * @param userList - list of userIDs to claim\n */\n public ensureSessionsForUsers(logger: LogSpan, userList: Array<UserId>): Promise<void> {\n // The Rust-SDK requires that we only have one getMissingSessions process in flight at once. This little dance\n // ensures that, by only having one call to ensureSessionsForUsersInner active at once (and making them\n // queue up in order).\n const prom = this.currentClaimPromise\n .catch(() => {\n // any errors in the previous claim will have been reported already, so there is nothing to do here.\n // we just throw away the error and start anew.\n })\n .then(() => this.ensureSessionsForUsersInner(logger, userList));\n this.currentClaimPromise = prom;\n return prom;\n }\n\n private async ensureSessionsForUsersInner(logger: LogSpan, userList: Array<UserId>): Promise<void> {\n // bail out quickly if we've been stopped.\n if (this.stopped) {\n throw new Error(`Cannot ensure Olm sessions: shutting down`);\n }\n logger.info(\"Checking for missing Olm sessions\");\n // By passing the userId array to rust we transfer ownership of the items to rust, causing\n // them to be invalidated on the JS side as soon as the method is called.\n // As we haven't created the `userList` let's clone the users, to not break the caller from re-using it.\n const claimRequest = await this.olmMachine.getMissingSessions(userList.map((u) => u.clone()));\n if (claimRequest) {\n logger.info(\"Making /keys/claim request\");\n await this.outgoingRequestProcessor.makeOutgoingRequest(claimRequest);\n }\n logger.info(\"Olm sessions prepared\");\n }\n}\n"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,eAAe,CAAC;EAIlBC,WAAWA,CACGC,UAAsB,EACtBC,wBAAkD,EACrE;IAAA,
|
|
1
|
+
{"version":3,"file":"KeyClaimManager.js","names":["KeyClaimManager","constructor","olmMachine","outgoingRequestProcessor","_defineProperty","currentClaimPromise","Promise","resolve","stop","stopped","ensureSessionsForUsers","logger","userList","prom","catch","then","ensureSessionsForUsersInner","_this","_asyncToGenerator","Error","info","claimRequest","getMissingSessions","map","u","clone","makeOutgoingRequest"],"sources":["../../src/rust-crypto/KeyClaimManager.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type OlmMachine, type UserId } from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type OutgoingRequestProcessor } from \"./OutgoingRequestProcessor.ts\";\nimport { type LogSpan } from \"../logger.ts\";\n\n/**\n * KeyClaimManager: linearises calls to OlmMachine.getMissingSessions to avoid races\n *\n * We have one of these per `RustCrypto` (and hence per `MatrixClient`).\n *\n * @internal\n */\nexport class KeyClaimManager {\n private currentClaimPromise: Promise<void>;\n private stopped = false;\n\n public constructor(\n private readonly olmMachine: OlmMachine,\n private readonly outgoingRequestProcessor: OutgoingRequestProcessor,\n ) {\n this.currentClaimPromise = Promise.resolve();\n }\n\n /**\n * Tell the KeyClaimManager to immediately stop processing requests.\n *\n * Any further calls, and any still in the queue, will fail with an error.\n */\n public stop(): void {\n this.stopped = true;\n }\n\n /**\n * Given a list of users, attempt to ensure that we have Olm Sessions active with each of their devices\n *\n * If we don't have an active olm session, we will claim a one-time key and start one.\n * @param logger - logger to use\n * @param userList - list of userIDs to claim\n */\n public ensureSessionsForUsers(logger: LogSpan, userList: Array<UserId>): Promise<void> {\n // The Rust-SDK requires that we only have one getMissingSessions process in flight at once. This little dance\n // ensures that, by only having one call to ensureSessionsForUsersInner active at once (and making them\n // queue up in order).\n const prom = this.currentClaimPromise\n .catch(() => {\n // any errors in the previous claim will have been reported already, so there is nothing to do here.\n // we just throw away the error and start anew.\n })\n .then(() => this.ensureSessionsForUsersInner(logger, userList));\n this.currentClaimPromise = prom;\n return prom;\n }\n\n private async ensureSessionsForUsersInner(logger: LogSpan, userList: Array<UserId>): Promise<void> {\n // bail out quickly if we've been stopped.\n if (this.stopped) {\n throw new Error(`Cannot ensure Olm sessions: shutting down`);\n }\n logger.info(\"Checking for missing Olm sessions\");\n // By passing the userId array to rust we transfer ownership of the items to rust, causing\n // them to be invalidated on the JS side as soon as the method is called.\n // As we haven't created the `userList` let's clone the users, to not break the caller from re-using it.\n const claimRequest = await this.olmMachine.getMissingSessions(userList.map((u) => u.clone()));\n if (claimRequest) {\n logger.info(\"Making /keys/claim request\");\n await this.outgoingRequestProcessor.makeOutgoingRequest(claimRequest);\n }\n logger.info(\"Olm sessions prepared\");\n }\n}\n"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,eAAe,CAAC;EAIlBC,WAAWA,CACGC,UAAsB,EACtBC,wBAAkD,EACrE;IAAAC,eAAA,kBALgB,KAAK;IAAA,KAGFF,UAAsB,GAAtBA,UAAsB;IAAA,KACtBC,wBAAkD,GAAlDA,wBAAkD;IAEnE,IAAI,CAACE,mBAAmB,GAAGC,OAAO,CAACC,OAAO,CAAC,CAAC;EAChD;;EAEA;AACJ;AACA;AACA;AACA;EACWC,IAAIA,CAAA,EAAS;IAChB,IAAI,CAACC,OAAO,GAAG,IAAI;EACvB;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;EACWC,sBAAsBA,CAACC,MAAe,EAAEC,QAAuB,EAAiB;IACnF;IACA;IACA;IACA,IAAMC,IAAI,GAAG,IAAI,CAACR,mBAAmB,CAChCS,KAAK,CAAC,MAAM;MACT;MACA;IAAA,CACH,CAAC,CACDC,IAAI,CAAC,MAAM,IAAI,CAACC,2BAA2B,CAACL,MAAM,EAAEC,QAAQ,CAAC,CAAC;IACnE,IAAI,CAACP,mBAAmB,GAAGQ,IAAI;IAC/B,OAAOA,IAAI;EACf;EAEcG,2BAA2BA,CAACL,MAAe,EAAEC,QAAuB,EAAiB;IAAA,IAAAK,KAAA;IAAA,OAAAC,iBAAA;MAC/F;MACA,IAAID,KAAI,CAACR,OAAO,EAAE;QACd,MAAM,IAAIU,KAAK,4CAA4C,CAAC;MAChE;MACAR,MAAM,CAACS,IAAI,CAAC,mCAAmC,CAAC;MAChD;MACA;MACA;MACA,IAAMC,YAAY,SAASJ,KAAI,CAACf,UAAU,CAACoB,kBAAkB,CAACV,QAAQ,CAACW,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,KAAK,CAAC,CAAC,CAAC,CAAC;MAC7F,IAAIJ,YAAY,EAAE;QACdV,MAAM,CAACS,IAAI,CAAC,4BAA4B,CAAC;QACzC,MAAMH,KAAI,CAACd,wBAAwB,CAACuB,mBAAmB,CAACL,YAAY,CAAC;MACzE;MACAV,MAAM,CAACS,IAAI,CAAC,uBAAuB,CAAC;IAAC;EACzC;AACJ","ignoreList":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
3
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
4
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
5
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -112,8 +113,14 @@ export class OutgoingRequestProcessor {
|
|
|
112
113
|
// a bit of extra logging, to help trace to-device messages through the system
|
|
113
114
|
var parsedBody = JSON.parse(request.body);
|
|
114
115
|
var messageList = [];
|
|
115
|
-
for (var
|
|
116
|
-
|
|
116
|
+
for (var _ref4 of Object.entries(parsedBody.messages)) {
|
|
117
|
+
var _ref3 = _slicedToArray(_ref4, 2);
|
|
118
|
+
var userId = _ref3[0];
|
|
119
|
+
var perUserMessages = _ref3[1];
|
|
120
|
+
for (var _ref7 of Object.entries(perUserMessages)) {
|
|
121
|
+
var _ref6 = _slicedToArray(_ref7, 2);
|
|
122
|
+
var deviceId = _ref6[0];
|
|
123
|
+
var message = _ref6[1];
|
|
117
124
|
messageList.push("".concat(userId, "/").concat(deviceId, " (msgid ").concat(message[ToDeviceMessageId], ")"));
|
|
118
125
|
}
|
|
119
126
|
}
|
|
@@ -130,7 +137,7 @@ export class OutgoingRequestProcessor {
|
|
|
130
137
|
}
|
|
131
138
|
var parsedBody = JSON.parse(body);
|
|
132
139
|
var makeRequest = /*#__PURE__*/function () {
|
|
133
|
-
var
|
|
140
|
+
var _ref8 = _asyncToGenerator(function* (auth) {
|
|
134
141
|
var newBody = _objectSpread({}, parsedBody);
|
|
135
142
|
if (auth !== null) {
|
|
136
143
|
newBody.auth = auth;
|
|
@@ -139,7 +146,7 @@ export class OutgoingRequestProcessor {
|
|
|
139
146
|
return JSON.parse(resp);
|
|
140
147
|
});
|
|
141
148
|
return function makeRequest(_x) {
|
|
142
|
-
return
|
|
149
|
+
return _ref8.apply(this, arguments);
|
|
143
150
|
};
|
|
144
151
|
}();
|
|
145
152
|
var resp = yield uiaCallback(makeRequest);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OutgoingRequestProcessor.js","names":["KeysBackupRequest","KeysClaimRequest","KeysQueryRequest","KeysUploadRequest","PutDehydratedDeviceRequest","RoomMessageRequest","SignatureUploadRequest","ToDeviceRequest","UploadSigningKeysRequest","calculateRetryBackoff","Method","logDuration","sleep","ToDeviceMessageId","UnstablePrefix","DehydrationUnstablePrefix","OutgoingRequestProcessor","constructor","logger","olmMachine","http","makeOutgoingRequest","msg","uiaCallback","_this","_asyncToGenerator","resp","requestWithRetry","Post","body","Put","version","sendToDeviceRequest","path","concat","encodeURIComponent","room_id","event_type","txn_id","makeRequestWithUIA","rawJsonRequest","warn","Object","getPrototypeOf","id","type","markRequestAsSent","e","Error","message","debug","trace","request","_this2","parsedBody","JSON","parse","messageList","userId","perUserMessages","entries","messages","deviceId","push","info","method","queryParams","_this3","makeRequest","_ref2","auth","newBody","_objectSpread","stringify","_x","apply","arguments","_this4","currentRetryCount","backoff","_this5","opts","json","headers","prefix","localTimeoutMs","authedRequest"],"sources":["../../src/rust-crypto/OutgoingRequestProcessor.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport {\n KeysBackupRequest,\n KeysClaimRequest,\n KeysQueryRequest,\n KeysUploadRequest,\n type OlmMachine,\n type OutgoingRequest,\n PutDehydratedDeviceRequest,\n RoomMessageRequest,\n SignatureUploadRequest,\n ToDeviceRequest,\n UploadSigningKeysRequest,\n} from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type Logger } from \"../logger.ts\";\nimport { calculateRetryBackoff, type IHttpOpts, type MatrixHttpApi, Method } from \"../http-api/index.ts\";\nimport { logDuration, type QueryDict, sleep } from \"../utils.ts\";\nimport { type AuthDict, type UIAuthCallback } from \"../interactive-auth.ts\";\nimport { ToDeviceMessageId } from \"../@types/event.ts\";\nimport { UnstablePrefix as DehydrationUnstablePrefix } from \"./DehydratedDeviceManager.ts\";\n\n/**\n * OutgoingRequestManager: turns `OutgoingRequest`s from the rust sdk into HTTP requests\n *\n * We have one of these per `RustCrypto` (and hence per `MatrixClient`), not that it does anything terribly complicated.\n * It's responsible for:\n *\n * * holding the reference to the `MatrixHttpApi`\n * * turning `OutgoingRequest`s from the rust backend into HTTP requests, and sending them\n * * sending the results of such requests back to the rust backend.\n *\n * @internal\n */\nexport class OutgoingRequestProcessor {\n public constructor(\n private readonly logger: Logger,\n private readonly olmMachine: OlmMachine,\n private readonly http: MatrixHttpApi<IHttpOpts & { onlyData: true }>,\n ) {}\n\n public async makeOutgoingRequest<T>(\n msg: OutgoingRequest | UploadSigningKeysRequest | PutDehydratedDeviceRequest,\n uiaCallback?: UIAuthCallback<T>,\n ): Promise<void> {\n let resp: string;\n\n /* refer https://docs.rs/matrix-sdk-crypto/0.6.0/matrix_sdk_crypto/requests/enum.OutgoingRequests.html\n * for the complete list of request types\n */\n if (msg instanceof KeysUploadRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/upload\", {}, msg.body);\n } else if (msg instanceof KeysQueryRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/query\", {}, msg.body);\n } else if (msg instanceof KeysClaimRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/claim\", {}, msg.body);\n } else if (msg instanceof SignatureUploadRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/signatures/upload\", {}, msg.body);\n } else if (msg instanceof KeysBackupRequest) {\n resp = await this.requestWithRetry(\n Method.Put,\n \"/_matrix/client/v3/room_keys/keys\",\n { version: msg.version },\n msg.body,\n );\n } else if (msg instanceof ToDeviceRequest) {\n resp = await this.sendToDeviceRequest(msg);\n } else if (msg instanceof RoomMessageRequest) {\n const path =\n `/_matrix/client/v3/rooms/${encodeURIComponent(msg.room_id)}/send/` +\n `${encodeURIComponent(msg.event_type)}/${encodeURIComponent(msg.txn_id)}`;\n resp = await this.requestWithRetry(Method.Put, path, {}, msg.body);\n } else if (msg instanceof UploadSigningKeysRequest) {\n await this.makeRequestWithUIA(\n Method.Post,\n \"/_matrix/client/v3/keys/device_signing/upload\",\n {},\n msg.body,\n uiaCallback,\n );\n // SigningKeysUploadRequest does not implement OutgoingRequest and does not need to be marked as sent.\n return;\n } else if (msg instanceof PutDehydratedDeviceRequest) {\n const path = DehydrationUnstablePrefix + \"/dehydrated_device\";\n await this.rawJsonRequest(Method.Put, path, {}, msg.body);\n // PutDehydratedDeviceRequest does not implement OutgoingRequest and does not need to be marked as sent.\n return;\n } else {\n this.logger.warn(\"Unsupported outgoing message\", Object.getPrototypeOf(msg));\n resp = \"\";\n }\n\n if (msg.id) {\n try {\n await logDuration(this.logger, `Mark Request as sent ${msg.type}`, async () => {\n await this.olmMachine.markRequestAsSent(msg.id!, msg.type, resp);\n });\n } catch (e) {\n // Ignore errors which are caused by the olmMachine having been freed. The exact error message depends\n // on whether we are using a release or develop build of rust-sdk-crypto-wasm.\n if (\n e instanceof Error &&\n (e.message === \"Attempt to use a moved value\" || e.message === \"null pointer passed to rust\")\n ) {\n this.logger.debug(`Ignoring error '${e.message}': client is likely shutting down`);\n } else {\n throw e;\n }\n }\n } else {\n this.logger.trace(`Outgoing request type:${msg.type} does not have an ID`);\n }\n }\n\n /**\n * Send the HTTP request for a `ToDeviceRequest`\n *\n * @param request - request to send\n * @returns JSON-serialized body of the response, if successful\n */\n private async sendToDeviceRequest(request: ToDeviceRequest): Promise<string> {\n // a bit of extra logging, to help trace to-device messages through the system\n const parsedBody: { messages: Record<string, Record<string, Record<string, any>>> } = JSON.parse(request.body);\n\n const messageList = [];\n for (const [userId, perUserMessages] of Object.entries(parsedBody.messages)) {\n for (const [deviceId, message] of Object.entries(perUserMessages)) {\n messageList.push(`${userId}/${deviceId} (msgid ${message[ToDeviceMessageId]})`);\n }\n }\n\n this.logger.info(\n `Sending batch of to-device messages. type=${request.event_type} txnid=${request.txn_id}`,\n messageList,\n );\n\n const path =\n `/_matrix/client/v3/sendToDevice/${encodeURIComponent(request.event_type)}/` +\n encodeURIComponent(request.txn_id);\n return await this.requestWithRetry(Method.Put, path, {}, request.body);\n }\n\n private async makeRequestWithUIA<T>(\n method: Method,\n path: string,\n queryParams: QueryDict,\n body: string,\n uiaCallback: UIAuthCallback<T> | undefined,\n ): Promise<string> {\n if (!uiaCallback) {\n return await this.requestWithRetry(method, path, queryParams, body);\n }\n\n const parsedBody = JSON.parse(body);\n const makeRequest = async (auth: AuthDict | null): Promise<T> => {\n const newBody: Record<string, any> = {\n ...parsedBody,\n };\n if (auth !== null) {\n newBody.auth = auth;\n }\n const resp = await this.requestWithRetry(method, path, queryParams, JSON.stringify(newBody));\n return JSON.parse(resp) as T;\n };\n\n const resp = await uiaCallback(makeRequest);\n return JSON.stringify(resp);\n }\n\n private async requestWithRetry(\n method: Method,\n path: string,\n queryParams: QueryDict,\n body: string,\n ): Promise<string> {\n let currentRetryCount = 0;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n return await this.rawJsonRequest(method, path, queryParams, body);\n } catch (e) {\n currentRetryCount++;\n const backoff = calculateRetryBackoff(e, currentRetryCount, true);\n if (backoff < 0) {\n // Max number of retries reached, or error is not retryable. rethrow the error\n throw e;\n }\n // wait for the specified time and then retry the request\n await sleep(backoff);\n }\n }\n }\n\n private async rawJsonRequest(method: Method, path: string, queryParams: QueryDict, body: string): Promise<string> {\n const opts = {\n // inhibit the JSON stringification and parsing within HttpApi.\n json: false,\n\n // nevertheless, we are sending, and accept, JSON.\n headers: {\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json\",\n },\n\n // we use the full prefix\n prefix: \"\",\n\n // We set a timeout of 60 seconds to guard against requests getting stuck forever and wedging the\n // request loop (cf https://github.com/element-hq/element-web/issues/29534).\n //\n // (XXX: should we do this in the whole of the js-sdk?)\n localTimeoutMs: 60000,\n };\n\n return await this.http.authedRequest<string>(method, path, queryParams, body, opts);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"OutgoingRequestProcessor.js","names":["KeysBackupRequest","KeysClaimRequest","KeysQueryRequest","KeysUploadRequest","PutDehydratedDeviceRequest","RoomMessageRequest","SignatureUploadRequest","ToDeviceRequest","UploadSigningKeysRequest","calculateRetryBackoff","Method","logDuration","sleep","ToDeviceMessageId","UnstablePrefix","DehydrationUnstablePrefix","OutgoingRequestProcessor","constructor","logger","olmMachine","http","makeOutgoingRequest","msg","uiaCallback","_this","_asyncToGenerator","resp","requestWithRetry","Post","body","Put","version","sendToDeviceRequest","path","concat","encodeURIComponent","room_id","event_type","txn_id","makeRequestWithUIA","rawJsonRequest","warn","Object","getPrototypeOf","id","type","markRequestAsSent","e","Error","message","debug","trace","request","_this2","parsedBody","JSON","parse","messageList","_ref4","entries","messages","_ref3","_slicedToArray","userId","perUserMessages","_ref7","_ref6","deviceId","push","info","method","queryParams","_this3","makeRequest","_ref8","auth","newBody","_objectSpread","stringify","_x","apply","arguments","_this4","currentRetryCount","backoff","_this5","opts","json","headers","prefix","localTimeoutMs","authedRequest"],"sources":["../../src/rust-crypto/OutgoingRequestProcessor.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport {\n KeysBackupRequest,\n KeysClaimRequest,\n KeysQueryRequest,\n KeysUploadRequest,\n type OlmMachine,\n type OutgoingRequest,\n PutDehydratedDeviceRequest,\n RoomMessageRequest,\n SignatureUploadRequest,\n ToDeviceRequest,\n UploadSigningKeysRequest,\n} from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type Logger } from \"../logger.ts\";\nimport { calculateRetryBackoff, type IHttpOpts, type MatrixHttpApi, Method } from \"../http-api/index.ts\";\nimport { logDuration, type QueryDict, sleep } from \"../utils.ts\";\nimport { type AuthDict, type UIAuthCallback } from \"../interactive-auth.ts\";\nimport { ToDeviceMessageId } from \"../@types/event.ts\";\nimport { UnstablePrefix as DehydrationUnstablePrefix } from \"./DehydratedDeviceManager.ts\";\n\n/**\n * OutgoingRequestManager: turns `OutgoingRequest`s from the rust sdk into HTTP requests\n *\n * We have one of these per `RustCrypto` (and hence per `MatrixClient`), not that it does anything terribly complicated.\n * It's responsible for:\n *\n * * holding the reference to the `MatrixHttpApi`\n * * turning `OutgoingRequest`s from the rust backend into HTTP requests, and sending them\n * * sending the results of such requests back to the rust backend.\n *\n * @internal\n */\nexport class OutgoingRequestProcessor {\n public constructor(\n private readonly logger: Logger,\n private readonly olmMachine: OlmMachine,\n private readonly http: MatrixHttpApi<IHttpOpts & { onlyData: true }>,\n ) {}\n\n public async makeOutgoingRequest<T>(\n msg: OutgoingRequest | UploadSigningKeysRequest | PutDehydratedDeviceRequest,\n uiaCallback?: UIAuthCallback<T>,\n ): Promise<void> {\n let resp: string;\n\n /* refer https://docs.rs/matrix-sdk-crypto/0.6.0/matrix_sdk_crypto/requests/enum.OutgoingRequests.html\n * for the complete list of request types\n */\n if (msg instanceof KeysUploadRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/upload\", {}, msg.body);\n } else if (msg instanceof KeysQueryRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/query\", {}, msg.body);\n } else if (msg instanceof KeysClaimRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/claim\", {}, msg.body);\n } else if (msg instanceof SignatureUploadRequest) {\n resp = await this.requestWithRetry(Method.Post, \"/_matrix/client/v3/keys/signatures/upload\", {}, msg.body);\n } else if (msg instanceof KeysBackupRequest) {\n resp = await this.requestWithRetry(\n Method.Put,\n \"/_matrix/client/v3/room_keys/keys\",\n { version: msg.version },\n msg.body,\n );\n } else if (msg instanceof ToDeviceRequest) {\n resp = await this.sendToDeviceRequest(msg);\n } else if (msg instanceof RoomMessageRequest) {\n const path =\n `/_matrix/client/v3/rooms/${encodeURIComponent(msg.room_id)}/send/` +\n `${encodeURIComponent(msg.event_type)}/${encodeURIComponent(msg.txn_id)}`;\n resp = await this.requestWithRetry(Method.Put, path, {}, msg.body);\n } else if (msg instanceof UploadSigningKeysRequest) {\n await this.makeRequestWithUIA(\n Method.Post,\n \"/_matrix/client/v3/keys/device_signing/upload\",\n {},\n msg.body,\n uiaCallback,\n );\n // SigningKeysUploadRequest does not implement OutgoingRequest and does not need to be marked as sent.\n return;\n } else if (msg instanceof PutDehydratedDeviceRequest) {\n const path = DehydrationUnstablePrefix + \"/dehydrated_device\";\n await this.rawJsonRequest(Method.Put, path, {}, msg.body);\n // PutDehydratedDeviceRequest does not implement OutgoingRequest and does not need to be marked as sent.\n return;\n } else {\n this.logger.warn(\"Unsupported outgoing message\", Object.getPrototypeOf(msg));\n resp = \"\";\n }\n\n if (msg.id) {\n try {\n await logDuration(this.logger, `Mark Request as sent ${msg.type}`, async () => {\n await this.olmMachine.markRequestAsSent(msg.id!, msg.type, resp);\n });\n } catch (e) {\n // Ignore errors which are caused by the olmMachine having been freed. The exact error message depends\n // on whether we are using a release or develop build of rust-sdk-crypto-wasm.\n if (\n e instanceof Error &&\n (e.message === \"Attempt to use a moved value\" || e.message === \"null pointer passed to rust\")\n ) {\n this.logger.debug(`Ignoring error '${e.message}': client is likely shutting down`);\n } else {\n throw e;\n }\n }\n } else {\n this.logger.trace(`Outgoing request type:${msg.type} does not have an ID`);\n }\n }\n\n /**\n * Send the HTTP request for a `ToDeviceRequest`\n *\n * @param request - request to send\n * @returns JSON-serialized body of the response, if successful\n */\n private async sendToDeviceRequest(request: ToDeviceRequest): Promise<string> {\n // a bit of extra logging, to help trace to-device messages through the system\n const parsedBody: { messages: Record<string, Record<string, Record<string, any>>> } = JSON.parse(request.body);\n\n const messageList = [];\n for (const [userId, perUserMessages] of Object.entries(parsedBody.messages)) {\n for (const [deviceId, message] of Object.entries(perUserMessages)) {\n messageList.push(`${userId}/${deviceId} (msgid ${message[ToDeviceMessageId]})`);\n }\n }\n\n this.logger.info(\n `Sending batch of to-device messages. type=${request.event_type} txnid=${request.txn_id}`,\n messageList,\n );\n\n const path =\n `/_matrix/client/v3/sendToDevice/${encodeURIComponent(request.event_type)}/` +\n encodeURIComponent(request.txn_id);\n return await this.requestWithRetry(Method.Put, path, {}, request.body);\n }\n\n private async makeRequestWithUIA<T>(\n method: Method,\n path: string,\n queryParams: QueryDict,\n body: string,\n uiaCallback: UIAuthCallback<T> | undefined,\n ): Promise<string> {\n if (!uiaCallback) {\n return await this.requestWithRetry(method, path, queryParams, body);\n }\n\n const parsedBody = JSON.parse(body);\n const makeRequest = async (auth: AuthDict | null): Promise<T> => {\n const newBody: Record<string, any> = {\n ...parsedBody,\n };\n if (auth !== null) {\n newBody.auth = auth;\n }\n const resp = await this.requestWithRetry(method, path, queryParams, JSON.stringify(newBody));\n return JSON.parse(resp) as T;\n };\n\n const resp = await uiaCallback(makeRequest);\n return JSON.stringify(resp);\n }\n\n private async requestWithRetry(\n method: Method,\n path: string,\n queryParams: QueryDict,\n body: string,\n ): Promise<string> {\n let currentRetryCount = 0;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n return await this.rawJsonRequest(method, path, queryParams, body);\n } catch (e) {\n currentRetryCount++;\n const backoff = calculateRetryBackoff(e, currentRetryCount, true);\n if (backoff < 0) {\n // Max number of retries reached, or error is not retryable. rethrow the error\n throw e;\n }\n // wait for the specified time and then retry the request\n await sleep(backoff);\n }\n }\n }\n\n private async rawJsonRequest(method: Method, path: string, queryParams: QueryDict, body: string): Promise<string> {\n const opts = {\n // inhibit the JSON stringification and parsing within HttpApi.\n json: false,\n\n // nevertheless, we are sending, and accept, JSON.\n headers: {\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json\",\n },\n\n // we use the full prefix\n prefix: \"\",\n\n // We set a timeout of 60 seconds to guard against requests getting stuck forever and wedging the\n // request loop (cf https://github.com/element-hq/element-web/issues/29534).\n //\n // (XXX: should we do this in the whole of the js-sdk?)\n localTimeoutMs: 60000,\n };\n\n return await this.http.authedRequest<string>(method, path, queryParams, body, opts);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -23,23 +23,23 @@ import { logDuration } from "../utils.js";
|
|
|
23
23
|
* Ensure that only one loop is going on at once, and that the requests are processed in order.
|
|
24
24
|
*/
|
|
25
25
|
export class OutgoingRequestsManager {
|
|
26
|
+
/**
|
|
27
|
+
* If there are additional calls to doProcessOutgoingRequests() while there is a current call running
|
|
28
|
+
* we need to remember in order to call `doProcessOutgoingRequests` again (as there could be new requests).
|
|
29
|
+
*
|
|
30
|
+
* If this is defined, it is an indication that we need to do another iteration; in this case the deferred
|
|
31
|
+
* will resolve once that next iteration completes. If it is undefined, there have been no new calls
|
|
32
|
+
* to `doProcessOutgoingRequests` since the current iteration started.
|
|
33
|
+
*/
|
|
34
|
+
|
|
26
35
|
constructor(logger, olmMachine, outgoingRequestProcessor) {
|
|
27
|
-
this.logger = logger;
|
|
28
|
-
this.olmMachine = olmMachine;
|
|
29
|
-
this.outgoingRequestProcessor = outgoingRequestProcessor;
|
|
30
36
|
/** whether {@link stop} has been called */
|
|
31
37
|
_defineProperty(this, "stopped", false);
|
|
32
38
|
/** whether {@link outgoingRequestLoop} is currently running */
|
|
33
39
|
_defineProperty(this, "outgoingRequestLoopRunning", false);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
* If this is defined, it is an indication that we need to do another iteration; in this case the deferred
|
|
39
|
-
* will resolve once that next iteration completes. If it is undefined, there have been no new calls
|
|
40
|
-
* to `doProcessOutgoingRequests` since the current iteration started.
|
|
41
|
-
*/
|
|
42
|
-
_defineProperty(this, "nextLoopDeferred", void 0);
|
|
40
|
+
this.logger = logger;
|
|
41
|
+
this.olmMachine = olmMachine;
|
|
42
|
+
this.outgoingRequestProcessor = outgoingRequestProcessor;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OutgoingRequestsManager.js","names":["logDuration","OutgoingRequestsManager","constructor","logger","olmMachine","outgoingRequestProcessor","_defineProperty","stop","stopped","doProcessOutgoingRequests","nextLoopDeferred","Promise","withResolvers","result","promise","outgoingRequestLoopRunning","outgoingRequestLoop","catch","e","error","_this","_asyncToGenerator","Error","loopTickResolvers","undefined","processOutgoingRequests","then","resolve","reject","_this2","outgoingRequests","successes","_loop","request","v","concat","type","makeOutgoingRequest","_ret","warn"],"sources":["../../src/rust-crypto/OutgoingRequestsManager.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type OlmMachine, type OutgoingRequest } from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type OutgoingRequestProcessor } from \"./OutgoingRequestProcessor.ts\";\nimport { type Logger } from \"../logger.ts\";\nimport { logDuration } from \"../utils.ts\";\n\n/**\n * OutgoingRequestsManager: responsible for processing outgoing requests from the OlmMachine.\n * Ensure that only one loop is going on at once, and that the requests are processed in order.\n */\nexport class OutgoingRequestsManager {\n /** whether {@link stop} has been called */\n private stopped = false;\n\n /** whether {@link outgoingRequestLoop} is currently running */\n private outgoingRequestLoopRunning = false;\n\n /**\n * If there are additional calls to doProcessOutgoingRequests() while there is a current call running\n * we need to remember in order to call `doProcessOutgoingRequests` again (as there could be new requests).\n *\n * If this is defined, it is an indication that we need to do another iteration; in this case the deferred\n * will resolve once that next iteration completes. If it is undefined, there have been no new calls\n * to `doProcessOutgoingRequests` since the current iteration started.\n */\n private nextLoopDeferred?: PromiseWithResolvers<void>;\n\n public constructor(\n private readonly logger: Logger,\n private readonly olmMachine: OlmMachine,\n public readonly outgoingRequestProcessor: OutgoingRequestProcessor,\n ) {}\n\n /**\n * Shut down as soon as possible the current loop of outgoing requests processing.\n */\n public stop(): void {\n this.stopped = true;\n }\n\n /**\n * Process the OutgoingRequests from the OlmMachine.\n *\n * This should be called at the end of each sync, to process any OlmMachine OutgoingRequests created by the rust sdk.\n * In some cases if OutgoingRequests need to be sent immediately, this can be called directly.\n *\n * Calls to doProcessOutgoingRequests() are processed synchronously, one after the other, in order.\n * If doProcessOutgoingRequests() is called while another call is still being processed, it will be queued.\n * Multiple calls to doProcessOutgoingRequests() when a call is already processing will be batched together.\n */\n public doProcessOutgoingRequests(): Promise<void> {\n // Flag that we need at least one more iteration of the loop.\n //\n // It is important that we do this even if the loop is currently running. There is potential for a race whereby\n // a request is added to the queue *after* `OlmMachine.outgoingRequests` checks the queue, but *before* it\n // returns. In such a case, the item could sit there unnoticed for some time.\n //\n // In order to circumvent the race, we set a flag which tells the loop to go round once again even if the\n // queue appears to be empty.\n if (!this.nextLoopDeferred) {\n this.nextLoopDeferred = Promise.withResolvers();\n }\n\n // ... and wait for it to complete.\n const result = this.nextLoopDeferred.promise;\n\n // set the loop going if it is not already.\n if (!this.outgoingRequestLoopRunning) {\n this.outgoingRequestLoop().catch((e) => {\n // this should not happen; outgoingRequestLoop should return any errors via `nextLoopDeferred`.\n /* istanbul ignore next */\n this.logger.error(\"Uncaught error in outgoing request loop\", e);\n });\n }\n return result;\n }\n\n private async outgoingRequestLoop(): Promise<void> {\n /* istanbul ignore if */\n if (this.outgoingRequestLoopRunning) {\n throw new Error(\"Cannot run two outgoing request loops\");\n }\n this.outgoingRequestLoopRunning = true;\n try {\n while (!this.stopped && this.nextLoopDeferred) {\n const loopTickResolvers = this.nextLoopDeferred;\n\n // reset `nextLoopDeferred` so that any future calls to `doProcessOutgoingRequests` are queued\n // for another additional iteration.\n this.nextLoopDeferred = undefined;\n\n // make the requests and feed the results back to the `nextLoopDeferred`\n await this.processOutgoingRequests().then(loopTickResolvers.resolve, loopTickResolvers.reject);\n }\n } finally {\n this.outgoingRequestLoopRunning = false;\n }\n\n if (this.nextLoopDeferred) {\n // the loop was stopped, but there was a call to `doProcessOutgoingRequests`. Make sure that\n // we reject the promise in case anything is waiting for it.\n this.nextLoopDeferred.reject(new Error(\"OutgoingRequestsManager was stopped\"));\n }\n }\n\n /**\n * Make a single request to `olmMachine.outgoingRequests` and do the corresponding requests.\n */\n private async processOutgoingRequests(): Promise<void> {\n if (this.stopped) return;\n\n const outgoingRequests: OutgoingRequest[] = await this.olmMachine.outgoingRequests();\n\n let successes = 0;\n for (const request of outgoingRequests) {\n if (this.stopped) return;\n try {\n await logDuration(this.logger, `Make outgoing request ${request.type}`, async () => {\n await this.outgoingRequestProcessor.makeOutgoingRequest(request);\n successes++;\n });\n } catch (e) {\n // as part of the loop we silently ignore errors, but log them.\n // The rust sdk will retry the request later as it won't have been marked as sent.\n this.logger.error(`Failed to process outgoing request ${request.type}: ${e}`);\n }\n }\n\n // If we successfully handled any requests this time, more may have been queued as\n // part of that handling.\n //\n // For example, we may have processed a `/keys/claim` request, which\n // meant the rust side could establish an Olm session and is now ready to\n // send out an `m.secret.send` message.\n // (See https://github.com/element-hq/element-web/issues/30988.)\n //\n // So, if we have successfully processed any requests, flag that we need to make another\n // pass around the outgoing-requests loop, to make sure we handle any\n // pending requests immediately.\n //\n // If all requests failed (or there weren't any) we don't want to retry them in a tight\n // loop. They will be retried after the next sync.\n // (See https://github.com/element-hq/element-web/issues/31790.)\n if (successes > 0) {\n // We call doProcessOutgoingRequests but since we expect that we are\n // already processing outgoing requests, this call will not kick off\n // the processing loop, but just set `nextLoopDeferred` and return,\n // which will mean we loop one more time.\n this.doProcessOutgoingRequests().catch((e) => {\n this.logger.warn(\"processOutgoingRequests: Error re-checking outgoing requests\", e);\n });\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"OutgoingRequestsManager.js","names":["logDuration","OutgoingRequestsManager","constructor","logger","olmMachine","outgoingRequestProcessor","_defineProperty","stop","stopped","doProcessOutgoingRequests","nextLoopDeferred","Promise","withResolvers","result","promise","outgoingRequestLoopRunning","outgoingRequestLoop","catch","e","error","_this","_asyncToGenerator","Error","loopTickResolvers","undefined","processOutgoingRequests","then","resolve","reject","_this2","outgoingRequests","successes","_loop","request","v","concat","type","makeOutgoingRequest","_ret","warn"],"sources":["../../src/rust-crypto/OutgoingRequestsManager.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type OlmMachine, type OutgoingRequest } from \"@matrix-org/matrix-sdk-crypto-wasm\";\n\nimport { type OutgoingRequestProcessor } from \"./OutgoingRequestProcessor.ts\";\nimport { type Logger } from \"../logger.ts\";\nimport { logDuration } from \"../utils.ts\";\n\n/**\n * OutgoingRequestsManager: responsible for processing outgoing requests from the OlmMachine.\n * Ensure that only one loop is going on at once, and that the requests are processed in order.\n */\nexport class OutgoingRequestsManager {\n /** whether {@link stop} has been called */\n private stopped = false;\n\n /** whether {@link outgoingRequestLoop} is currently running */\n private outgoingRequestLoopRunning = false;\n\n /**\n * If there are additional calls to doProcessOutgoingRequests() while there is a current call running\n * we need to remember in order to call `doProcessOutgoingRequests` again (as there could be new requests).\n *\n * If this is defined, it is an indication that we need to do another iteration; in this case the deferred\n * will resolve once that next iteration completes. If it is undefined, there have been no new calls\n * to `doProcessOutgoingRequests` since the current iteration started.\n */\n private nextLoopDeferred?: PromiseWithResolvers<void>;\n\n public constructor(\n private readonly logger: Logger,\n private readonly olmMachine: OlmMachine,\n public readonly outgoingRequestProcessor: OutgoingRequestProcessor,\n ) {}\n\n /**\n * Shut down as soon as possible the current loop of outgoing requests processing.\n */\n public stop(): void {\n this.stopped = true;\n }\n\n /**\n * Process the OutgoingRequests from the OlmMachine.\n *\n * This should be called at the end of each sync, to process any OlmMachine OutgoingRequests created by the rust sdk.\n * In some cases if OutgoingRequests need to be sent immediately, this can be called directly.\n *\n * Calls to doProcessOutgoingRequests() are processed synchronously, one after the other, in order.\n * If doProcessOutgoingRequests() is called while another call is still being processed, it will be queued.\n * Multiple calls to doProcessOutgoingRequests() when a call is already processing will be batched together.\n */\n public doProcessOutgoingRequests(): Promise<void> {\n // Flag that we need at least one more iteration of the loop.\n //\n // It is important that we do this even if the loop is currently running. There is potential for a race whereby\n // a request is added to the queue *after* `OlmMachine.outgoingRequests` checks the queue, but *before* it\n // returns. In such a case, the item could sit there unnoticed for some time.\n //\n // In order to circumvent the race, we set a flag which tells the loop to go round once again even if the\n // queue appears to be empty.\n if (!this.nextLoopDeferred) {\n this.nextLoopDeferred = Promise.withResolvers();\n }\n\n // ... and wait for it to complete.\n const result = this.nextLoopDeferred.promise;\n\n // set the loop going if it is not already.\n if (!this.outgoingRequestLoopRunning) {\n this.outgoingRequestLoop().catch((e) => {\n // this should not happen; outgoingRequestLoop should return any errors via `nextLoopDeferred`.\n /* istanbul ignore next */\n this.logger.error(\"Uncaught error in outgoing request loop\", e);\n });\n }\n return result;\n }\n\n private async outgoingRequestLoop(): Promise<void> {\n /* istanbul ignore if */\n if (this.outgoingRequestLoopRunning) {\n throw new Error(\"Cannot run two outgoing request loops\");\n }\n this.outgoingRequestLoopRunning = true;\n try {\n while (!this.stopped && this.nextLoopDeferred) {\n const loopTickResolvers = this.nextLoopDeferred;\n\n // reset `nextLoopDeferred` so that any future calls to `doProcessOutgoingRequests` are queued\n // for another additional iteration.\n this.nextLoopDeferred = undefined;\n\n // make the requests and feed the results back to the `nextLoopDeferred`\n await this.processOutgoingRequests().then(loopTickResolvers.resolve, loopTickResolvers.reject);\n }\n } finally {\n this.outgoingRequestLoopRunning = false;\n }\n\n if (this.nextLoopDeferred) {\n // the loop was stopped, but there was a call to `doProcessOutgoingRequests`. Make sure that\n // we reject the promise in case anything is waiting for it.\n this.nextLoopDeferred.reject(new Error(\"OutgoingRequestsManager was stopped\"));\n }\n }\n\n /**\n * Make a single request to `olmMachine.outgoingRequests` and do the corresponding requests.\n */\n private async processOutgoingRequests(): Promise<void> {\n if (this.stopped) return;\n\n const outgoingRequests: OutgoingRequest[] = await this.olmMachine.outgoingRequests();\n\n let successes = 0;\n for (const request of outgoingRequests) {\n if (this.stopped) return;\n try {\n await logDuration(this.logger, `Make outgoing request ${request.type}`, async () => {\n await this.outgoingRequestProcessor.makeOutgoingRequest(request);\n successes++;\n });\n } catch (e) {\n // as part of the loop we silently ignore errors, but log them.\n // The rust sdk will retry the request later as it won't have been marked as sent.\n this.logger.error(`Failed to process outgoing request ${request.type}: ${e}`);\n }\n }\n\n // If we successfully handled any requests this time, more may have been queued as\n // part of that handling.\n //\n // For example, we may have processed a `/keys/claim` request, which\n // meant the rust side could establish an Olm session and is now ready to\n // send out an `m.secret.send` message.\n // (See https://github.com/element-hq/element-web/issues/30988.)\n //\n // So, if we have successfully processed any requests, flag that we need to make another\n // pass around the outgoing-requests loop, to make sure we handle any\n // pending requests immediately.\n //\n // If all requests failed (or there weren't any) we don't want to retry them in a tight\n // loop. They will be retried after the next sync.\n // (See https://github.com/element-hq/element-web/issues/31790.)\n if (successes > 0) {\n // We call doProcessOutgoingRequests but since we expect that we are\n // already processing outgoing requests, this call will not kick off\n // the processing loop, but just set `nextLoopDeferred` and return,\n // which will mean we loop one more time.\n this.doProcessOutgoingRequests().catch((e) => {\n this.logger.warn(\"processOutgoingRequests: Error re-checking outgoing requests\", e);\n });\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -77,9 +77,6 @@ export class PerSessionKeyBackupDownloader {
|
|
|
77
77
|
* @param logger - The logger to use.
|
|
78
78
|
*/
|
|
79
79
|
constructor(logger, olmMachine, http, backupManager) {
|
|
80
|
-
this.olmMachine = olmMachine;
|
|
81
|
-
this.http = http;
|
|
82
|
-
this.backupManager = backupManager;
|
|
83
80
|
_defineProperty(this, "stopped", false);
|
|
84
81
|
/**
|
|
85
82
|
* The version and decryption key to use with current backup if all set up correctly.
|
|
@@ -90,8 +87,6 @@ export class PerSessionKeyBackupDownloader {
|
|
|
90
87
|
/** We remember when a session was requested and not found in backup to avoid query again too soon.
|
|
91
88
|
* Map of session_id to timestamp */
|
|
92
89
|
_defineProperty(this, "sessionLastCheckAttemptedTime", new Map());
|
|
93
|
-
/** The logger to use */
|
|
94
|
-
_defineProperty(this, "logger", void 0);
|
|
95
90
|
/** Whether the download loop is running. */
|
|
96
91
|
_defineProperty(this, "downloadLoopRunning", false);
|
|
97
92
|
/** The list of requests that are queued. */
|
|
@@ -115,6 +110,9 @@ export class PerSessionKeyBackupDownloader {
|
|
|
115
110
|
}
|
|
116
111
|
});
|
|
117
112
|
});
|
|
113
|
+
this.olmMachine = olmMachine;
|
|
114
|
+
this.http = http;
|
|
115
|
+
this.backupManager = backupManager;
|
|
118
116
|
this.logger = logger.getChild("[PerSessionKeyBackupDownloader]");
|
|
119
117
|
backupManager.on(CryptoEvent.KeyBackupStatus, this.onBackupStatusChanged);
|
|
120
118
|
backupManager.on(CryptoEvent.KeyBackupFailed, this.onBackupStatusChanged);
|