From bc03bdbfc435678e185e01465d1b4df45e394b76 Mon Sep 17 00:00:00 2001 From: lilia Date: Fri, 25 Sep 2015 17:25:25 -0700 Subject: [PATCH] Move tryMessageAgain to MessageReceiver `tryMessageAgain` is the routine called when re-trying a message that failed to decrypt due to an IncomingIdentityKeyError. This handling needs to move to MessageReceiver because it depends on `processDecrypted` to handle incoming message protos, which depends on a server instance in order to download attachments. // FREEBIE --- js/libtextsecure.js | 102 +++++++++++++++--------------- libtextsecure/axolotl_wrapper.js | 65 +++++++------------ libtextsecure/message_receiver.js | 33 ++++++++-- libtextsecure/sendmessage.js | 4 +- 4 files changed, 102 insertions(+), 102 deletions(-) diff --git a/js/libtextsecure.js b/js/libtextsecure.js index 713b67adad..d9b4cdc609 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -37771,31 +37771,21 @@ axolotlInternal.RecipientRecord = function() { }(); })(); +/* + * vim: ts=4:sw=4:expandtab + */ ;(function() { 'use strict'; window.textsecure = window.textsecure || {}; window.textsecure.storage = window.textsecure.storage || {}; + textsecure.storage.axolotl = new AxolotlStore(); var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl); window.textsecure = window.textsecure || {}; window.textsecure.protocol_wrapper = { - decrypt: function(source, sourceDevice, type, blob) { - if (sourceDevice === null) { sourceDevice = 0; } - var fromAddress = [source, sourceDevice].join('.'); - switch(type) { - case textsecure.protobuf.Envelope.Type.CIPHERTEXT: - return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob)); - case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE: - if (blob.readUint8() != ((3 << 4) | 3)) - throw new Error("Bad version byte"); - var blob = blob.toArrayBuffer(); - return axolotlInstance.handlePreKeyWhisperMessage(fromAddress, blob).catch(function(e) { - handleIdentityKeyError(fromAddress, blob, e); - }); - default: - return new Promise.reject(new Error("Unknown message type")); - } + decryptWhisperMessage: function(fromAddress, blob) { + return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob)); }, closeOpenSessionForDevice: function(encodedNumber) { return axolotlInstance.closeOpenSessionForDevice(encodedNumber) @@ -37817,35 +37807,24 @@ axolotlInternal.RecipientRecord = function() { }, getRegistrationId: function(encodedNumber) { return axolotlInstance.getRegistrationId(encodedNumber); + }, + handlePreKeyWhisperMessage: function(from, blob) { + blob.mark(); + if (blob.readUint8() != ((3 << 4) | 3)) { + throw new Error("Bad version byte"); + } + return axolotlInstance.handlePreKeyWhisperMessage(from, blob.toArrayBuffer()).catch(function(e) { + if (e.message === 'Unknown identity key') { + blob.reset(); // restore the version byte. + + // create an error that the UI will pick up and ask the + // user if they want to re-negotiate + throw new textsecure.IncomingIdentityKeyError(from, blob.toArrayBuffer(), e.identityKey); + } + throw e; + }); } }; - - function handleIdentityKeyError(from, blob, e) { - if (e.message === 'Unknown identity key') { - // create an error that the UI will pick up and ask the - // user if they want to re-negotiate - throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey); - } - throw e; - } - - var tryMessageAgain = function(from, encodedMessage) { - return axolotlInstance.handlePreKeyWhisperMessage(from, encodedMessage).then(function(res) { - var finalMessage = textsecure.protobuf.DataMessage.decode(res[0]); - - if ((finalMessage.flags & textsecure.protobuf.DataMessage.Flags.END_SESSION) - == textsecure.protobuf.DataMessage.Flags.END_SESSION && - finalMessage.sync !== null) - res[1](); - - return processDecrypted(finalMessage); - }).catch(function(e) { - handleIdentityKeyError(from, encodedMessage, e); - }); - }; - - textsecure.replay.registerFunction(tryMessageAgain, textsecure.replay.Type.INIT_SESSION); - })(); /* @@ -39276,12 +39255,19 @@ MessageReceiver.prototype = { this.dispatchEvent(ev); }, decrypt: function(envelope, ciphertext) { - return textsecure.protocol_wrapper.decrypt( - envelope.source, - envelope.sourceDevice, - envelope.type, - ciphertext - ).catch(function(error) { + var fromAddress = [envelope.source , (envelope.sourceDevice || 0)].join('.'); + var promise; + switch(envelope.type) { + case textsecure.protobuf.Envelope.Type.CIPHERTEXT: + promise = textsecure.protocol_wrapper.decryptWhisperMessage(fromAddress, ciphertext); + break; + case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE: + promise = textsecure.protocol_wrapper.handlePreKeyWhisperMessage(fromAddress, ciphertext); + break; + default: + promise = Promise.reject(new Error("Unknown message type")); + } + return promise.catch(function(error) { var ev = new Event('error'); ev.error = error; ev.proto = envelope; @@ -39420,6 +39406,18 @@ MessageReceiver.prototype = { then(decryptAttachment). then(updateAttachment); }, + tryMessageAgain: function(from, encodedMessage) { + return textsecure.protocol_wrapper.handlePreKeyWhisperMessage(from, encodedMessage).then(function(res) { + var finalMessage = textsecure.protobuf.DataMessage.decode(res[0]); + + if ((finalMessage.flags & textsecure.protobuf.DataMessage.Flags.END_SESSION) + == textsecure.protobuf.DataMessage.Flags.END_SESSION && + finalMessage.sync !== null) + res[1](); + + return this.processDecrypted(finalMessage); + }.bind(this)); + }, processDecrypted: function(decrypted, source) { // Now that its decrypted, validate the message and clean it up for consumer processing // Note that messages may (generally) only perform one action and we ignore remaining fields @@ -39572,6 +39570,8 @@ textsecure.MessageReceiver = function(url, username, password, signalingKey) { this.getStatus = messageReceiver.getStatus.bind(messageReceiver); this.close = messageReceiver.close.bind(messageReceiver); messageReceiver.connect(); + + textsecure.replay.registerFunction(messageReceiver.tryMessageAgain.bind(messageReceiver), textsecure.replay.Type.INIT_SESSION); }; textsecure.MessageReceiver.prototype = { @@ -39682,7 +39682,7 @@ MessageSender.prototype = { } }; - function getKeysForNumber(number, updateDevices) { + var getKeysForNumber = function(number, updateDevices) { var handleResult = function(response) { return Promise.all(response.devices.map(function(device) { if (updateDevices === undefined || updateDevices.indexOf(device.deviceId) > -1) @@ -39714,7 +39714,7 @@ MessageSender.prototype = { return Promise.all(promises); } - } + }.bind(this); var doSendMessage = function(number, devicesForNumber, recurse) { return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) { diff --git a/libtextsecure/axolotl_wrapper.js b/libtextsecure/axolotl_wrapper.js index 406707f5b3..d8f9ff3f2b 100644 --- a/libtextsecure/axolotl_wrapper.js +++ b/libtextsecure/axolotl_wrapper.js @@ -1,28 +1,18 @@ +/* + * vim: ts=4:sw=4:expandtab + */ ;(function() { 'use strict'; window.textsecure = window.textsecure || {}; window.textsecure.storage = window.textsecure.storage || {}; + textsecure.storage.axolotl = new AxolotlStore(); var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl); window.textsecure = window.textsecure || {}; window.textsecure.protocol_wrapper = { - decrypt: function(source, sourceDevice, type, blob) { - if (sourceDevice === null) { sourceDevice = 0; } - var fromAddress = [source, sourceDevice].join('.'); - switch(type) { - case textsecure.protobuf.Envelope.Type.CIPHERTEXT: - return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob)); - case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE: - if (blob.readUint8() != ((3 << 4) | 3)) - throw new Error("Bad version byte"); - var blob = blob.toArrayBuffer(); - return axolotlInstance.handlePreKeyWhisperMessage(fromAddress, blob).catch(function(e) { - handleIdentityKeyError(fromAddress, blob, e); - }); - default: - return new Promise.reject(new Error("Unknown message type")); - } + decryptWhisperMessage: function(fromAddress, blob) { + return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob)); }, closeOpenSessionForDevice: function(encodedNumber) { return axolotlInstance.closeOpenSessionForDevice(encodedNumber) @@ -44,33 +34,22 @@ }, getRegistrationId: function(encodedNumber) { return axolotlInstance.getRegistrationId(encodedNumber); + }, + handlePreKeyWhisperMessage: function(from, blob) { + blob.mark(); + if (blob.readUint8() != ((3 << 4) | 3)) { + throw new Error("Bad version byte"); + } + return axolotlInstance.handlePreKeyWhisperMessage(from, blob.toArrayBuffer()).catch(function(e) { + if (e.message === 'Unknown identity key') { + blob.reset(); // restore the version byte. + + // create an error that the UI will pick up and ask the + // user if they want to re-negotiate + throw new textsecure.IncomingIdentityKeyError(from, blob.toArrayBuffer(), e.identityKey); + } + throw e; + }); } }; - - function handleIdentityKeyError(from, blob, e) { - if (e.message === 'Unknown identity key') { - // create an error that the UI will pick up and ask the - // user if they want to re-negotiate - throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey); - } - throw e; - } - - var tryMessageAgain = function(from, encodedMessage) { - return axolotlInstance.handlePreKeyWhisperMessage(from, encodedMessage).then(function(res) { - var finalMessage = textsecure.protobuf.DataMessage.decode(res[0]); - - if ((finalMessage.flags & textsecure.protobuf.DataMessage.Flags.END_SESSION) - == textsecure.protobuf.DataMessage.Flags.END_SESSION && - finalMessage.sync !== null) - res[1](); - - return processDecrypted(finalMessage); - }).catch(function(e) { - handleIdentityKeyError(from, encodedMessage, e); - }); - }; - - textsecure.replay.registerFunction(tryMessageAgain, textsecure.replay.Type.INIT_SESSION); - })(); diff --git a/libtextsecure/message_receiver.js b/libtextsecure/message_receiver.js index 521e6d7fd2..c5f5c8f6d4 100644 --- a/libtextsecure/message_receiver.js +++ b/libtextsecure/message_receiver.js @@ -94,12 +94,19 @@ MessageReceiver.prototype = { this.dispatchEvent(ev); }, decrypt: function(envelope, ciphertext) { - return textsecure.protocol_wrapper.decrypt( - envelope.source, - envelope.sourceDevice, - envelope.type, - ciphertext - ).catch(function(error) { + var fromAddress = [envelope.source , (envelope.sourceDevice || 0)].join('.'); + var promise; + switch(envelope.type) { + case textsecure.protobuf.Envelope.Type.CIPHERTEXT: + promise = textsecure.protocol_wrapper.decryptWhisperMessage(fromAddress, ciphertext); + break; + case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE: + promise = textsecure.protocol_wrapper.handlePreKeyWhisperMessage(fromAddress, ciphertext); + break; + default: + promise = Promise.reject(new Error("Unknown message type")); + } + return promise.catch(function(error) { var ev = new Event('error'); ev.error = error; ev.proto = envelope; @@ -238,6 +245,18 @@ MessageReceiver.prototype = { then(decryptAttachment). then(updateAttachment); }, + tryMessageAgain: function(from, encodedMessage) { + return textsecure.protocol_wrapper.handlePreKeyWhisperMessage(from, encodedMessage).then(function(res) { + var finalMessage = textsecure.protobuf.DataMessage.decode(res[0]); + + if ((finalMessage.flags & textsecure.protobuf.DataMessage.Flags.END_SESSION) + == textsecure.protobuf.DataMessage.Flags.END_SESSION && + finalMessage.sync !== null) + res[1](); + + return this.processDecrypted(finalMessage); + }.bind(this)); + }, processDecrypted: function(decrypted, source) { // Now that its decrypted, validate the message and clean it up for consumer processing // Note that messages may (generally) only perform one action and we ignore remaining fields @@ -390,6 +409,8 @@ textsecure.MessageReceiver = function(url, username, password, signalingKey) { this.getStatus = messageReceiver.getStatus.bind(messageReceiver); this.close = messageReceiver.close.bind(messageReceiver); messageReceiver.connect(); + + textsecure.replay.registerFunction(messageReceiver.tryMessageAgain.bind(messageReceiver), textsecure.replay.Type.INIT_SESSION); }; textsecure.MessageReceiver.prototype = { diff --git a/libtextsecure/sendmessage.js b/libtextsecure/sendmessage.js index 380339c2af..8a7f6370ff 100644 --- a/libtextsecure/sendmessage.js +++ b/libtextsecure/sendmessage.js @@ -101,7 +101,7 @@ MessageSender.prototype = { } }; - function getKeysForNumber(number, updateDevices) { + var getKeysForNumber = function(number, updateDevices) { var handleResult = function(response) { return Promise.all(response.devices.map(function(device) { if (updateDevices === undefined || updateDevices.indexOf(device.deviceId) > -1) @@ -133,7 +133,7 @@ MessageSender.prototype = { return Promise.all(promises); } - } + }.bind(this); var doSendMessage = function(number, devicesForNumber, recurse) { return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) {