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
pull/749/head
lilia 10 years ago
parent 0fc673f25f
commit bc03bdbfc4

@ -37771,31 +37771,21 @@ axolotlInternal.RecipientRecord = function() {
}(); }();
})(); })();
/*
* vim: ts=4:sw=4:expandtab
*/
;(function() { ;(function() {
'use strict'; 'use strict';
window.textsecure = window.textsecure || {}; window.textsecure = window.textsecure || {};
window.textsecure.storage = window.textsecure.storage || {}; window.textsecure.storage = window.textsecure.storage || {};
textsecure.storage.axolotl = new AxolotlStore(); textsecure.storage.axolotl = new AxolotlStore();
var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl); var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl);
window.textsecure = window.textsecure || {}; window.textsecure = window.textsecure || {};
window.textsecure.protocol_wrapper = { window.textsecure.protocol_wrapper = {
decrypt: function(source, sourceDevice, type, blob) { decryptWhisperMessage: function(fromAddress, blob) {
if (sourceDevice === null) { sourceDevice = 0; } return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob));
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"));
}
}, },
closeOpenSessionForDevice: function(encodedNumber) { closeOpenSessionForDevice: function(encodedNumber) {
return axolotlInstance.closeOpenSessionForDevice(encodedNumber) return axolotlInstance.closeOpenSessionForDevice(encodedNumber)
@ -37817,35 +37807,24 @@ axolotlInternal.RecipientRecord = function() {
}, },
getRegistrationId: function(encodedNumber) { getRegistrationId: function(encodedNumber) {
return axolotlInstance.getRegistrationId(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.
function handleIdentityKeyError(from, blob, e) { // create an error that the UI will pick up and ask the
if (e.message === 'Unknown identity key') { // user if they want to re-negotiate
// create an error that the UI will pick up and ask the throw new textsecure.IncomingIdentityKeyError(from, blob.toArrayBuffer(), e.identityKey);
// user if they want to re-negotiate }
throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey); throw e;
});
} }
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); this.dispatchEvent(ev);
}, },
decrypt: function(envelope, ciphertext) { decrypt: function(envelope, ciphertext) {
return textsecure.protocol_wrapper.decrypt( var fromAddress = [envelope.source , (envelope.sourceDevice || 0)].join('.');
envelope.source, var promise;
envelope.sourceDevice, switch(envelope.type) {
envelope.type, case textsecure.protobuf.Envelope.Type.CIPHERTEXT:
ciphertext promise = textsecure.protocol_wrapper.decryptWhisperMessage(fromAddress, ciphertext);
).catch(function(error) { 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'); var ev = new Event('error');
ev.error = error; ev.error = error;
ev.proto = envelope; ev.proto = envelope;
@ -39420,6 +39406,18 @@ MessageReceiver.prototype = {
then(decryptAttachment). then(decryptAttachment).
then(updateAttachment); 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) { processDecrypted: function(decrypted, source) {
// Now that its decrypted, validate the message and clean it up for consumer processing // 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 // 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.getStatus = messageReceiver.getStatus.bind(messageReceiver);
this.close = messageReceiver.close.bind(messageReceiver); this.close = messageReceiver.close.bind(messageReceiver);
messageReceiver.connect(); messageReceiver.connect();
textsecure.replay.registerFunction(messageReceiver.tryMessageAgain.bind(messageReceiver), textsecure.replay.Type.INIT_SESSION);
}; };
textsecure.MessageReceiver.prototype = { textsecure.MessageReceiver.prototype = {
@ -39682,7 +39682,7 @@ MessageSender.prototype = {
} }
}; };
function getKeysForNumber(number, updateDevices) { var getKeysForNumber = function(number, updateDevices) {
var handleResult = function(response) { var handleResult = function(response) {
return Promise.all(response.devices.map(function(device) { return Promise.all(response.devices.map(function(device) {
if (updateDevices === undefined || updateDevices.indexOf(device.deviceId) > -1) if (updateDevices === undefined || updateDevices.indexOf(device.deviceId) > -1)
@ -39714,7 +39714,7 @@ MessageSender.prototype = {
return Promise.all(promises); return Promise.all(promises);
} }
} }.bind(this);
var doSendMessage = function(number, devicesForNumber, recurse) { var doSendMessage = function(number, devicesForNumber, recurse) {
return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) { return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) {

@ -1,28 +1,18 @@
/*
* vim: ts=4:sw=4:expandtab
*/
;(function() { ;(function() {
'use strict'; 'use strict';
window.textsecure = window.textsecure || {}; window.textsecure = window.textsecure || {};
window.textsecure.storage = window.textsecure.storage || {}; window.textsecure.storage = window.textsecure.storage || {};
textsecure.storage.axolotl = new AxolotlStore(); textsecure.storage.axolotl = new AxolotlStore();
var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl); var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl);
window.textsecure = window.textsecure || {}; window.textsecure = window.textsecure || {};
window.textsecure.protocol_wrapper = { window.textsecure.protocol_wrapper = {
decrypt: function(source, sourceDevice, type, blob) { decryptWhisperMessage: function(fromAddress, blob) {
if (sourceDevice === null) { sourceDevice = 0; } return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob));
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"));
}
}, },
closeOpenSessionForDevice: function(encodedNumber) { closeOpenSessionForDevice: function(encodedNumber) {
return axolotlInstance.closeOpenSessionForDevice(encodedNumber) return axolotlInstance.closeOpenSessionForDevice(encodedNumber)
@ -44,33 +34,22 @@
}, },
getRegistrationId: function(encodedNumber) { getRegistrationId: function(encodedNumber) {
return axolotlInstance.getRegistrationId(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.
function handleIdentityKeyError(from, blob, e) { // create an error that the UI will pick up and ask the
if (e.message === 'Unknown identity key') { // user if they want to re-negotiate
// create an error that the UI will pick up and ask the throw new textsecure.IncomingIdentityKeyError(from, blob.toArrayBuffer(), e.identityKey);
// user if they want to re-negotiate }
throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey); throw e;
});
} }
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);
})(); })();

@ -94,12 +94,19 @@ MessageReceiver.prototype = {
this.dispatchEvent(ev); this.dispatchEvent(ev);
}, },
decrypt: function(envelope, ciphertext) { decrypt: function(envelope, ciphertext) {
return textsecure.protocol_wrapper.decrypt( var fromAddress = [envelope.source , (envelope.sourceDevice || 0)].join('.');
envelope.source, var promise;
envelope.sourceDevice, switch(envelope.type) {
envelope.type, case textsecure.protobuf.Envelope.Type.CIPHERTEXT:
ciphertext promise = textsecure.protocol_wrapper.decryptWhisperMessage(fromAddress, ciphertext);
).catch(function(error) { 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'); var ev = new Event('error');
ev.error = error; ev.error = error;
ev.proto = envelope; ev.proto = envelope;
@ -238,6 +245,18 @@ MessageReceiver.prototype = {
then(decryptAttachment). then(decryptAttachment).
then(updateAttachment); 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) { processDecrypted: function(decrypted, source) {
// Now that its decrypted, validate the message and clean it up for consumer processing // 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 // 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.getStatus = messageReceiver.getStatus.bind(messageReceiver);
this.close = messageReceiver.close.bind(messageReceiver); this.close = messageReceiver.close.bind(messageReceiver);
messageReceiver.connect(); messageReceiver.connect();
textsecure.replay.registerFunction(messageReceiver.tryMessageAgain.bind(messageReceiver), textsecure.replay.Type.INIT_SESSION);
}; };
textsecure.MessageReceiver.prototype = { textsecure.MessageReceiver.prototype = {

@ -101,7 +101,7 @@ MessageSender.prototype = {
} }
}; };
function getKeysForNumber(number, updateDevices) { var getKeysForNumber = function(number, updateDevices) {
var handleResult = function(response) { var handleResult = function(response) {
return Promise.all(response.devices.map(function(device) { return Promise.all(response.devices.map(function(device) {
if (updateDevices === undefined || updateDevices.indexOf(device.deviceId) > -1) if (updateDevices === undefined || updateDevices.indexOf(device.deviceId) > -1)
@ -133,7 +133,7 @@ MessageSender.prototype = {
return Promise.all(promises); return Promise.all(promises);
} }
} }.bind(this);
var doSendMessage = function(number, devicesForNumber, recurse) { var doSendMessage = function(number, devicesForNumber, recurse) {
return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) { return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) {

Loading…
Cancel
Save