diff --git a/package.json b/package.json index e77cdb2ac02..88668ba5781 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ ], "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/matrix-sdk-crypto-js": "^0.1.0-alpha.2", + "@matrix-org/matrix-sdk-crypto-js": "^0.1.0-alpha.3", "another-json": "^0.2.0", "bs58": "^5.0.0", "content-type": "^1.0.4", diff --git a/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts b/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts new file mode 100644 index 00000000000..28d1e9b3508 --- /dev/null +++ b/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts @@ -0,0 +1,180 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import MockHttpBackend from "matrix-mock-request"; +import { Mocked } from "jest-mock"; +import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-js"; +import { + KeysBackupRequest, + KeysClaimRequest, + KeysQueryRequest, + KeysUploadRequest, + RoomMessageRequest, + SignatureUploadRequest, + ToDeviceRequest, +} from "@matrix-org/matrix-sdk-crypto-js"; + +import { TypedEventEmitter } from "../../../src/models/typed-event-emitter"; +import { HttpApiEvent, HttpApiEventHandlerMap, MatrixHttpApi } from "../../../src"; +import { OutgoingRequestProcessor } from "../../../src/rust-crypto/OutgoingRequestProcessor"; + +describe("OutgoingRequestProcessor", () => { + /** the OutgoingRequestProcessor implementation under test */ + let processor: OutgoingRequestProcessor; + + /** A mock http backend which processor is connected to */ + let httpBackend: MockHttpBackend; + + /** a mocked-up OlmMachine which processor is connected to */ + let olmMachine: Mocked; + + /** wait for a call to olmMachine.markRequestAsSent */ + function awaitCallToMarkAsSent(): Promise { + return new Promise((resolve, _reject) => { + olmMachine.markRequestAsSent.mockImplementationOnce(async () => { + resolve(undefined); + }); + }); + } + + beforeEach(async () => { + httpBackend = new MockHttpBackend(); + + const dummyEventEmitter = new TypedEventEmitter(); + const httpApi = new MatrixHttpApi(dummyEventEmitter, { + baseUrl: "https://example.com", + prefix: "/_matrix", + fetchFn: httpBackend.fetchFn as typeof global.fetch, + onlyData: true, + }); + + olmMachine = { + markRequestAsSent: jest.fn(), + } as unknown as Mocked; + + processor = new OutgoingRequestProcessor(olmMachine, httpApi); + }); + + /* simple requests that map directly to the request body */ + const tests: Array<[string, any, "POST" | "PUT", string]> = [ + ["KeysUploadRequest", KeysUploadRequest, "POST", "https://example.com/_matrix/client/v3/keys/upload"], + ["KeysQueryRequest", KeysQueryRequest, "POST", "https://example.com/_matrix/client/v3/keys/query"], + ["KeysClaimRequest", KeysClaimRequest, "POST", "https://example.com/_matrix/client/v3/keys/claim"], + [ + "SignatureUploadRequest", + SignatureUploadRequest, + "POST", + "https://example.com/_matrix/client/v3/keys/signatures/upload", + ], + ["KeysBackupRequest", KeysBackupRequest, "PUT", "https://example.com/_matrix/client/v3/room_keys/keys"], + ]; + + test.each(tests)(`should handle %ss`, async (_, RequestClass, expectedMethod, expectedPath) => { + // first, mock up a request as we might expect to receive it from the Rust layer ... + const testBody = '{ "foo": "bar" }'; + const outgoingRequest = new RequestClass("1234", testBody); + + // ... then poke it into the OutgoingRequestProcessor under test. + const reqProm = processor.makeOutgoingRequest(outgoingRequest); + + // Now: check that it makes a matching HTTP request ... + const testResponse = '{ "result": 1 }'; + httpBackend + .when(expectedMethod, "/_matrix") + .check((req) => { + expect(req.path).toEqual(expectedPath); + expect(req.rawData).toEqual(testBody); + expect(req.headers["Accept"]).toEqual("application/json"); + expect(req.headers["Content-Type"]).toEqual("application/json"); + }) + .respond(200, testResponse, true); + + // ... and that it calls OlmMachine.markAsSent. + const markSentCallPromise = awaitCallToMarkAsSent(); + await httpBackend.flushAllExpected(); + + await Promise.all([reqProm, markSentCallPromise]); + expect(olmMachine.markRequestAsSent).toHaveBeenCalledWith("1234", outgoingRequest.type, testResponse); + httpBackend.verifyNoOutstandingRequests(); + }); + + it("should handle ToDeviceRequests", async () => { + // first, mock up the ToDeviceRequest as we might expect to receive it from the Rust layer ... + const testBody = '{ "foo": "bar" }'; + const outgoingRequest = new ToDeviceRequest("1234", "test/type", "test/txnid", testBody); + + // ... then poke it into the OutgoingRequestProcessor under test. + const reqProm = processor.makeOutgoingRequest(outgoingRequest); + + // Now: check that it makes a matching HTTP request ... + const testResponse = '{ "result": 1 }'; + httpBackend + .when("PUT", "/_matrix") + .check((req) => { + expect(req.path).toEqual("https://example.com/_matrix/client/v3/sendToDevice/test%2Ftype/test%2Ftxnid"); + expect(req.rawData).toEqual(testBody); + expect(req.headers["Accept"]).toEqual("application/json"); + expect(req.headers["Content-Type"]).toEqual("application/json"); + }) + .respond(200, testResponse, true); + + // ... and that it calls OlmMachine.markAsSent. + const markSentCallPromise = awaitCallToMarkAsSent(); + await httpBackend.flushAllExpected(); + + await Promise.all([reqProm, markSentCallPromise]); + expect(olmMachine.markRequestAsSent).toHaveBeenCalledWith("1234", outgoingRequest.type, testResponse); + httpBackend.verifyNoOutstandingRequests(); + }); + + it("should handle RoomMessageRequests", async () => { + // first, mock up the RoomMessageRequest as we might expect to receive it from the Rust layer ... + const testBody = '{ "foo": "bar" }'; + const outgoingRequest = new RoomMessageRequest("1234", "test/room", "test/txnid", "test/type", testBody); + + // ... then poke it into the OutgoingRequestProcessor under test. + const reqProm = processor.makeOutgoingRequest(outgoingRequest); + + // Now: check that it makes a matching HTTP request ... + const testResponse = '{ "result": 1 }'; + httpBackend + .when("PUT", "/_matrix") + .check((req) => { + expect(req.path).toEqual( + "https://example.com/_matrix/client/v3/room/test%2Froom/send/test%2Ftype/test%2Ftxnid", + ); + expect(req.rawData).toEqual(testBody); + expect(req.headers["Accept"]).toEqual("application/json"); + expect(req.headers["Content-Type"]).toEqual("application/json"); + }) + .respond(200, testResponse, true); + + // ... and that it calls OlmMachine.markAsSent. + const markSentCallPromise = awaitCallToMarkAsSent(); + await httpBackend.flushAllExpected(); + + await Promise.all([reqProm, markSentCallPromise]); + expect(olmMachine.markRequestAsSent).toHaveBeenCalledWith("1234", outgoingRequest.type, testResponse); + httpBackend.verifyNoOutstandingRequests(); + }); + + it("does not explode with unknown requests", async () => { + const outgoingRequest = { id: "5678", type: 987 }; + const markSentCallPromise = awaitCallToMarkAsSent(); + await Promise.all([processor.makeOutgoingRequest(outgoingRequest), markSentCallPromise]); + expect(olmMachine.markRequestAsSent).toHaveBeenCalledWith("5678", 987, ""); + }); +}); diff --git a/spec/unit/rust-crypto.spec.ts b/spec/unit/rust-crypto/rust-crypto.spec.ts similarity index 59% rename from spec/unit/rust-crypto.spec.ts rename to spec/unit/rust-crypto/rust-crypto.spec.ts index 50e2c856caa..1a00acddfae 100644 --- a/spec/unit/rust-crypto.spec.ts +++ b/spec/unit/rust-crypto/rust-crypto.spec.ts @@ -17,24 +17,16 @@ limitations under the License. import "fake-indexeddb/auto"; import { IDBFactory } from "fake-indexeddb"; import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-js"; -import { - KeysBackupRequest, - KeysClaimRequest, - KeysQueryRequest, - KeysUploadRequest, - OlmMachine, - SignatureUploadRequest, -} from "@matrix-org/matrix-sdk-crypto-js"; +import { KeysQueryRequest, OlmMachine } from "@matrix-org/matrix-sdk-crypto-js"; import { Mocked } from "jest-mock"; -import MockHttpBackend from "matrix-mock-request"; -import { RustCrypto } from "../../src/rust-crypto/rust-crypto"; -import { initRustCrypto } from "../../src/rust-crypto"; -import { HttpApiEvent, HttpApiEventHandlerMap, IToDeviceEvent, MatrixClient, MatrixHttpApi } from "../../src"; -import { TypedEventEmitter } from "../../src/models/typed-event-emitter"; -import { mkEvent } from "../test-utils/test-utils"; -import { CryptoBackend } from "../../src/common-crypto/CryptoBackend"; -import { IEventDecryptionResult } from "../../src/@types/crypto"; +import { RustCrypto } from "../../../src/rust-crypto/rust-crypto"; +import { initRustCrypto } from "../../../src/rust-crypto"; +import { IToDeviceEvent, MatrixClient, MatrixHttpApi } from "../../../src"; +import { mkEvent } from "../../test-utils/test-utils"; +import { CryptoBackend } from "../../../src/common-crypto/CryptoBackend"; +import { IEventDecryptionResult } from "../../../src/@types/crypto"; +import { OutgoingRequestProcessor } from "../../../src/rust-crypto/OutgoingRequestProcessor"; afterEach(() => { // reset fake-indexeddb after each test, to make sure we don't leak connections @@ -106,8 +98,8 @@ describe("RustCrypto", () => { /** the RustCrypto implementation under test */ let rustCrypto: RustCrypto; - /** A mock http backend which rustCrypto is connected to */ - let httpBackend: MockHttpBackend; + /** A mock OutgoingRequestProcessor which rustCrypto is connected to */ + let outgoingRequestProcessor: Mocked; /** a mocked-up OlmMachine which rustCrypto is connected to */ let olmMachine: Mocked; @@ -116,28 +108,25 @@ describe("RustCrypto", () => { * the front of the queue, until it is empty. */ let outgoingRequestQueue: Array>; - /** wait for a call to olmMachine.markRequestAsSent */ - function awaitCallToMarkAsSent(): Promise { - return new Promise((resolve, _reject) => { - olmMachine.markRequestAsSent.mockImplementationOnce(async () => { - resolve(undefined); + /** wait for a call to outgoingRequestProcessor.makeOutgoingRequest. + * + * The promise resolves to a callback: the makeOutgoingRequest call will not complete until the returned + * callback is called. + */ + function awaitCallToMakeOutgoingRequest(): Promise<() => void> { + return new Promise<() => void>((resolveCalledPromise, _reject) => { + outgoingRequestProcessor.makeOutgoingRequest.mockImplementationOnce(async () => { + const completePromise = new Promise((resolveCompletePromise, _reject) => { + resolveCalledPromise(resolveCompletePromise); + }); + return completePromise; }); }); } beforeEach(async () => { - httpBackend = new MockHttpBackend(); - await RustSdkCryptoJs.initAsync(); - const dummyEventEmitter = new TypedEventEmitter(); - const httpApi = new MatrixHttpApi(dummyEventEmitter, { - baseUrl: "https://example.com", - prefix: "/_matrix", - fetchFn: httpBackend.fetchFn as typeof global.fetch, - onlyData: true, - }); - // for these tests we use a mock OlmMachine, with an implementation of outgoingRequests that // returns objects from outgoingRequestQueue outgoingRequestQueue = []; @@ -145,91 +134,55 @@ describe("RustCrypto", () => { outgoingRequests: jest.fn().mockImplementation(() => { return Promise.resolve(outgoingRequestQueue.shift() ?? []); }), - markRequestAsSent: jest.fn(), close: jest.fn(), } as unknown as Mocked; - rustCrypto = new RustCrypto(olmMachine, httpApi, TEST_USER, TEST_DEVICE_ID); - }); + outgoingRequestProcessor = { + makeOutgoingRequest: jest.fn(), + } as unknown as Mocked; - it("should poll for outgoing messages", () => { - rustCrypto.onSyncCompleted({}); - expect(olmMachine.outgoingRequests).toHaveBeenCalled(); + rustCrypto = new RustCrypto(olmMachine, {} as MatrixHttpApi, TEST_USER, TEST_DEVICE_ID); + rustCrypto["outgoingRequestProcessor"] = outgoingRequestProcessor; }); - /* simple requests that map directly to the request body */ - const tests: Array<[any, "POST" | "PUT", string]> = [ - [KeysUploadRequest, "POST", "https://example.com/_matrix/client/v3/keys/upload"], - [KeysQueryRequest, "POST", "https://example.com/_matrix/client/v3/keys/query"], - [KeysClaimRequest, "POST", "https://example.com/_matrix/client/v3/keys/claim"], - [SignatureUploadRequest, "POST", "https://example.com/_matrix/client/v3/keys/signatures/upload"], - [KeysBackupRequest, "PUT", "https://example.com/_matrix/client/v3/room_keys/keys"], - ]; - - for (const [RequestClass, expectedMethod, expectedPath] of tests) { - it(`should handle ${RequestClass.name}s`, async () => { - const testBody = '{ "foo": "bar" }'; - const outgoingRequest = new RequestClass("1234", testBody); - outgoingRequestQueue.push([outgoingRequest]); - - const testResponse = '{ "result": 1 }'; - httpBackend - .when(expectedMethod, "/_matrix") - .check((req) => { - expect(req.path).toEqual(expectedPath); - expect(req.rawData).toEqual(testBody); - expect(req.headers["Accept"]).toEqual("application/json"); - expect(req.headers["Content-Type"]).toEqual("application/json"); - }) - .respond(200, testResponse, true); - - rustCrypto.onSyncCompleted({}); - - expect(olmMachine.outgoingRequests).toHaveBeenCalledTimes(1); - - const markSentCallPromise = awaitCallToMarkAsSent(); - await httpBackend.flushAllExpected(); - - await markSentCallPromise; - expect(olmMachine.markRequestAsSent).toHaveBeenCalledWith("1234", outgoingRequest.type, testResponse); - httpBackend.verifyNoOutstandingRequests(); - }); - } - - it("does not explode with unknown requests", async () => { - const outgoingRequest = { id: "5678", type: 987 }; - outgoingRequestQueue.push([outgoingRequest]); + it("should poll for outgoing messages and send them", async () => { + const testReq = new KeysQueryRequest("1234", "{}"); + outgoingRequestQueue.push([testReq]); + const makeRequestPromise = awaitCallToMakeOutgoingRequest(); rustCrypto.onSyncCompleted({}); - await awaitCallToMarkAsSent(); - expect(olmMachine.markRequestAsSent).toHaveBeenCalledWith("5678", 987, ""); + await makeRequestPromise; + expect(olmMachine.outgoingRequests).toHaveBeenCalled(); + expect(outgoingRequestProcessor.makeOutgoingRequest).toHaveBeenCalledWith(testReq); }); it("stops looping when stop() is called", async () => { - const testResponse = '{ "result": 1 }'; - for (let i = 0; i < 5; i++) { outgoingRequestQueue.push([new KeysQueryRequest("1234", "{}")]); - httpBackend.when("POST", "/_matrix").respond(200, testResponse, true); } + let makeRequestPromise = awaitCallToMakeOutgoingRequest(); + rustCrypto.onSyncCompleted({}); expect(rustCrypto["outgoingRequestLoopRunning"]).toBeTruthy(); // go a couple of times round the loop - await httpBackend.flush("/_matrix", 1); - await awaitCallToMarkAsSent(); + let resolveMakeRequest = await makeRequestPromise; + makeRequestPromise = awaitCallToMakeOutgoingRequest(); + resolveMakeRequest(); - await httpBackend.flush("/_matrix", 1); - await awaitCallToMarkAsSent(); + resolveMakeRequest = await makeRequestPromise; + makeRequestPromise = awaitCallToMakeOutgoingRequest(); + resolveMakeRequest(); // a second sync while this is going on shouldn't make any difference rustCrypto.onSyncCompleted({}); - await httpBackend.flush("/_matrix", 1); - await awaitCallToMarkAsSent(); + resolveMakeRequest = await makeRequestPromise; + outgoingRequestProcessor.makeOutgoingRequest.mockReset(); + resolveMakeRequest(); // now stop... rustCrypto.stop(); @@ -241,7 +194,7 @@ describe("RustCrypto", () => { setTimeout(resolve, 100); }); expect(rustCrypto["outgoingRequestLoopRunning"]).toBeFalsy(); - httpBackend.verifyNoOutstandingRequests(); + expect(outgoingRequestProcessor.makeOutgoingRequest).not.toHaveBeenCalled(); expect(olmMachine.outgoingRequests).not.toHaveBeenCalled(); // we sent three, so there should be 2 left diff --git a/src/rust-crypto/OutgoingRequestProcessor.ts b/src/rust-crypto/OutgoingRequestProcessor.ts new file mode 100644 index 00000000000..c0163f8525c --- /dev/null +++ b/src/rust-crypto/OutgoingRequestProcessor.ts @@ -0,0 +1,109 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { + OlmMachine, + KeysBackupRequest, + KeysClaimRequest, + KeysQueryRequest, + KeysUploadRequest, + RoomMessageRequest, + SignatureUploadRequest, + ToDeviceRequest, +} from "@matrix-org/matrix-sdk-crypto-js"; + +import { logger } from "../logger"; +import { IHttpOpts, MatrixHttpApi, Method } from "../http-api"; +import { QueryDict } from "../utils"; + +/** + * Common interface for all the request types returned by `OlmMachine.outgoingRequests`. + */ +export interface OutgoingRequest { + readonly id: string | undefined; + readonly type: number; +} + +/** + * OutgoingRequestManager: turns `OutgoingRequest`s from the rust sdk into HTTP requests + * + * We have one of these per `RustCrypto` (and hence per `MatrixClient`), not that it does anything terribly complicated. + * It's responsible for: + * + * * holding the reference to the `MatrixHttpApi` + * * turning `OutgoingRequest`s from the rust backend into HTTP requests, and sending them + * * sending the results of such requests back to the rust backend. + */ +export class OutgoingRequestProcessor { + public constructor( + private readonly olmMachine: OlmMachine, + private readonly http: MatrixHttpApi, + ) {} + + public async makeOutgoingRequest(msg: OutgoingRequest): Promise { + let resp: string; + + /* refer https://docs.rs/matrix-sdk-crypto/0.6.0/matrix_sdk_crypto/requests/enum.OutgoingRequests.html + * for the complete list of request types + */ + if (msg instanceof KeysUploadRequest) { + resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/upload", {}, msg.body); + } else if (msg instanceof KeysQueryRequest) { + resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/query", {}, msg.body); + } else if (msg instanceof KeysClaimRequest) { + resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/claim", {}, msg.body); + } else if (msg instanceof SignatureUploadRequest) { + resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/signatures/upload", {}, msg.body); + } else if (msg instanceof KeysBackupRequest) { + resp = await this.rawJsonRequest(Method.Put, "/_matrix/client/v3/room_keys/keys", {}, msg.body); + } else if (msg instanceof ToDeviceRequest) { + const path = + `/_matrix/client/v3/sendToDevice/${encodeURIComponent(msg.event_type)}/` + + encodeURIComponent(msg.txn_id); + resp = await this.rawJsonRequest(Method.Put, path, {}, msg.body); + } else if (msg instanceof RoomMessageRequest) { + const path = + `/_matrix/client/v3/room/${encodeURIComponent(msg.room_id)}/send/` + + `${encodeURIComponent(msg.event_type)}/${encodeURIComponent(msg.txn_id)}`; + resp = await this.rawJsonRequest(Method.Put, path, {}, msg.body); + } else { + logger.warn("Unsupported outgoing message", Object.getPrototypeOf(msg)); + resp = ""; + } + + if (msg.id) { + await this.olmMachine.markRequestAsSent(msg.id, msg.type, resp); + } + } + + private async rawJsonRequest(method: Method, path: string, queryParams: QueryDict, body: string): Promise { + const opts = { + // inhibit the JSON stringification and parsing within HttpApi. + json: false, + + // nevertheless, we are sending, and accept, JSON. + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + }, + + // we use the full prefix + prefix: "", + }; + + return await this.http.authedRequest(method, path, queryParams, body, opts); + } +} diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index 667f4d3229a..fd553fc94a5 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -15,14 +15,6 @@ limitations under the License. */ import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-js"; -import { - DecryptedRoomEvent, - KeysBackupRequest, - KeysClaimRequest, - KeysQueryRequest, - KeysUploadRequest, - SignatureUploadRequest, -} from "@matrix-org/matrix-sdk-crypto-js"; import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto"; import type { IToDeviceEvent } from "../sync-accumulator"; @@ -30,17 +22,9 @@ import type { IEncryptedEventInfo } from "../crypto/api"; import { MatrixEvent } from "../models/event"; import { CryptoBackend, OnSyncCompletedData } from "../common-crypto/CryptoBackend"; import { logger } from "../logger"; -import { IHttpOpts, MatrixHttpApi, Method } from "../http-api"; -import { QueryDict } from "../utils"; +import { IHttpOpts, MatrixHttpApi } from "../http-api"; import { DeviceTrustLevel, UserTrustLevel } from "../crypto/CrossSigning"; - -/** - * Common interface for all the request types returned by `OlmMachine.outgoingRequests`. - */ -interface OutgoingRequest { - readonly id: string | undefined; - readonly type: number; -} +import { OutgoingRequest, OutgoingRequestProcessor } from "./OutgoingRequestProcessor"; /** * An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto. @@ -55,12 +39,16 @@ export class RustCrypto implements CryptoBackend { /** whether {@link outgoingRequestLoop} is currently running */ private outgoingRequestLoopRunning = false; + private outgoingRequestProcessor: OutgoingRequestProcessor; + public constructor( private readonly olmMachine: RustSdkCryptoJs.OlmMachine, - private readonly http: MatrixHttpApi, + http: MatrixHttpApi, _userId: string, _deviceId: string, - ) {} + ) { + this.outgoingRequestProcessor = new OutgoingRequestProcessor(olmMachine, http); + } public stop(): void { // stop() may be called multiple times, but attempting to close() the OlmMachine twice @@ -87,7 +75,7 @@ export class RustCrypto implements CryptoBackend { origin_server_ts: event.getTs(), }), new RustSdkCryptoJs.RoomId(event.getRoomId()!), - )) as DecryptedRoomEvent; + )) as RustSdkCryptoJs.DecryptedRoomEvent; return { clearEvent: JSON.parse(res.event), claimedEd25519Key: res.senderClaimedEd25519Key, @@ -190,7 +178,7 @@ export class RustCrypto implements CryptoBackend { return; } for (const msg of outgoingRequests) { - await this.doOutgoingRequest(msg as OutgoingRequest); + await this.outgoingRequestProcessor.makeOutgoingRequest(msg as OutgoingRequest); } } } catch (e) { @@ -199,49 +187,4 @@ export class RustCrypto implements CryptoBackend { this.outgoingRequestLoopRunning = false; } } - - private async doOutgoingRequest(msg: OutgoingRequest): Promise { - let resp: string; - - /* refer https://docs.rs/matrix-sdk-crypto/0.6.0/matrix_sdk_crypto/requests/enum.OutgoingRequests.html - * for the complete list of request types - */ - if (msg instanceof KeysUploadRequest) { - resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/upload", {}, msg.body); - } else if (msg instanceof KeysQueryRequest) { - resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/query", {}, msg.body); - } else if (msg instanceof KeysClaimRequest) { - resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/claim", {}, msg.body); - } else if (msg instanceof SignatureUploadRequest) { - resp = await this.rawJsonRequest(Method.Post, "/_matrix/client/v3/keys/signatures/upload", {}, msg.body); - } else if (msg instanceof KeysBackupRequest) { - resp = await this.rawJsonRequest(Method.Put, "/_matrix/client/v3/room_keys/keys", {}, msg.body); - } else { - // TODO: ToDeviceRequest, RoomMessageRequest - logger.warn("Unsupported outgoing message", Object.getPrototypeOf(msg)); - resp = ""; - } - - if (msg.id) { - await this.olmMachine.markRequestAsSent(msg.id, msg.type, resp); - } - } - - private async rawJsonRequest(method: Method, path: string, queryParams: QueryDict, body: string): Promise { - const opts = { - // inhibit the JSON stringification and parsing within HttpApi. - json: false, - - // nevertheless, we are sending, and accept, JSON. - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - - // we use the full prefix - prefix: "", - }; - - return await this.http.authedRequest(method, path, queryParams, body, opts); - } } diff --git a/yarn.lock b/yarn.lock index 924097c143f..d9cc1ac4a37 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1398,7 +1398,7 @@ dependencies: lodash "^4.17.21" -"@matrix-org/matrix-sdk-crypto-js@^0.1.0-alpha.2": +"@matrix-org/matrix-sdk-crypto-js@^0.1.0-alpha.3": version "0.1.0-alpha.3" resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-js/-/matrix-sdk-crypto-js-0.1.0-alpha.3.tgz#829ea03bcad8051dc1e4f0da18a66d4ba273f78f" integrity sha512-KpEddjC34aobFlUYf2mIaXqkjLC0goRmYnbDZLTd0MwiFtau4b1TrPptQ8XFc90Z2VeAcvf18CBqA2otmZzUKQ==