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
This commit is contained in:
parent
0fc673f25f
commit
bc03bdbfc4
4 changed files with 102 additions and 102 deletions
|
@ -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; }
|
|
||||||
var fromAddress = [source, sourceDevice].join('.');
|
|
||||||
switch(type) {
|
|
||||||
case textsecure.protobuf.Envelope.Type.CIPHERTEXT:
|
|
||||||
return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob));
|
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) {
|
||||||
|
|
||||||
function handleIdentityKeyError(from, blob, e) {
|
|
||||||
if (e.message === 'Unknown identity key') {
|
if (e.message === 'Unknown identity key') {
|
||||||
|
blob.reset(); // restore the version byte.
|
||||||
|
|
||||||
// create an error that the UI will pick up and ask the
|
// create an error that the UI will pick up and ask the
|
||||||
// user if they want to re-negotiate
|
// user if they want to re-negotiate
|
||||||
throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey);
|
throw new textsecure.IncomingIdentityKeyError(from, blob.toArrayBuffer(), 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; }
|
|
||||||
var fromAddress = [source, sourceDevice].join('.');
|
|
||||||
switch(type) {
|
|
||||||
case textsecure.protobuf.Envelope.Type.CIPHERTEXT:
|
|
||||||
return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob));
|
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) {
|
||||||
|
|
||||||
function handleIdentityKeyError(from, blob, e) {
|
|
||||||
if (e.message === 'Unknown identity key') {
|
if (e.message === 'Unknown identity key') {
|
||||||
|
blob.reset(); // restore the version byte.
|
||||||
|
|
||||||
// create an error that the UI will pick up and ask the
|
// create an error that the UI will pick up and ask the
|
||||||
// user if they want to re-negotiate
|
// user if they want to re-negotiate
|
||||||
throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey);
|
throw new textsecure.IncomingIdentityKeyError(from, blob.toArrayBuffer(), 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…
Add table
Add a link
Reference in a new issue