From 9e29289dccbd705c72b80b93f199268f74c00de0 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 6 Mar 2019 12:02:48 -0500 Subject: [PATCH] use a different transaction ID when re-sending a key request --- spec/unit/crypto.spec.js | 52 +++++++++++++++++++++ src/crypto/OutgoingRoomKeyRequestManager.js | 9 ++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/spec/unit/crypto.spec.js b/spec/unit/crypto.spec.js index 0440456d5..2ad57afea 100644 --- a/spec/unit/crypto.spec.js +++ b/spec/unit/crypto.spec.js @@ -127,6 +127,7 @@ describe("Crypto", function() { describe('Key requests', function() { let aliceClient; let bobClient; + let realSetTimeout; beforeEach(async function() { aliceClient = (new TestClient( @@ -137,9 +138,15 @@ describe("Crypto", function() { )).client; await aliceClient.initCrypto(); await bobClient.initCrypto(); + // clobber the setTimeout function to run 10x faster. + realSetTimeout = global.setTimeout; + global.setTimeout = function(f, n) { + return realSetTimeout(f, n/10); + }; }); afterEach(async function() { + global.setTimeout = realSetTimeout; aliceClient.stopClient(); bobClient.stopClient(); }); @@ -297,5 +304,50 @@ describe("Crypto", function() { expect(await cryptoStore.getOutgoingRoomKeyRequest(roomKeyRequestBody)) .toExist(); }); + + it("uses a new txnid for re-requesting keys", async function() { + const event = new MatrixEvent({ + sender: "@bob:example.com", + room_id: "!someroom", + content: { + algorithm: olmlib.MEGOLM_ALGORITHM, + session_id: "sessionid", + sender_key: "senderkey", + }, + }); + /* return a promise and a function. When the function is called, + * the promise will be resolved. + */ + function awaitFunctionCall() { + let func; + const promise = new Promise((resolve, reject) => { + func = function(...args) { + global.setTimeout(() => resolve(args), 10); + return Promise.resolve(); + }; + }); + return {func, promise}; + } + + aliceClient.startClient(); + + let promise; + // make a room key request, and record the transaction ID for the + // sendToDevice call + ({promise, func: aliceClient.sendToDevice} = awaitFunctionCall()); + await aliceClient.cancelAndResendEventRoomKeyRequest(event); + let args = await promise; + const txnId = args[2]; + + // cancel and resend the room key request + ({promise, func: aliceClient.sendToDevice} = awaitFunctionCall()); + await aliceClient.cancelAndResendEventRoomKeyRequest(event); + // the first call to sendToDevice will be the cancellation + args = await promise; + // the second call to sendToDevice will be the key request + ({promise, func: aliceClient.sendToDevice} = awaitFunctionCall()); + args = await promise; + expect(args[2]).toNotBe(txnId); + }); }); }); diff --git a/src/crypto/OutgoingRoomKeyRequestManager.js b/src/crypto/OutgoingRoomKeyRequestManager.js index aeea2d3af..3af19f3c9 100644 --- a/src/crypto/OutgoingRoomKeyRequestManager.js +++ b/src/crypto/OutgoingRoomKeyRequestManager.js @@ -176,6 +176,9 @@ export default class OutgoingRoomKeyRequestManager { req.requestId, ROOM_KEY_REQUEST_STATES.SENT, { state, cancellationTxnId: this._baseApis.makeTxnId(), + // need to use a new transaction ID so that + // the request gets sent + requestTxnId: this._baseApis.makeTxnId(), }, ); if (!updatedReq) { @@ -347,7 +350,7 @@ export default class OutgoingRoomKeyRequestManager { logger.warn( `error in OutgoingRoomKeyRequestManager: ${e}`, ); - }).done(); + }); }; this._sendOutgoingRoomKeyRequestsTimer = global.setTimeout( @@ -398,7 +401,7 @@ export default class OutgoingRoomKeyRequestManager { logger.error("Error sending room key request; will retry later.", e); this._sendOutgoingRoomKeyRequestsTimer = null; this._startTimer(); - }).done(); + }); }); } @@ -418,7 +421,7 @@ export default class OutgoingRoomKeyRequestManager { }; return this._sendMessageToDevices( - requestMessage, req.recipients, req.requestId, + requestMessage, req.recipients, req.requestTxnId || req.requestId, ).then(() => { return this._cryptoStore.updateOutgoingRoomKeyRequest( req.requestId, ROOM_KEY_REQUEST_STATES.UNSENT,