Merge pull request #441 from sachaaaaa/outgoing_messages

[multi-device] Outgoing messages
pull/454/head
sachaaaaa 6 years ago committed by GitHub
commit eaddf18cc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -113,18 +113,8 @@
} }
} }
function savePairingAuthorisation({ function savePairingAuthorisation(authorisation) {
primaryDevicePubKey, return window.Signal.Data.createOrUpdatePairingAuthorisation(authorisation);
secondaryDevicePubKey,
requestSignature,
grantSignature,
}) {
return window.Signal.Data.createOrUpdatePairingAuthorisation({
primaryDevicePubKey,
secondaryDevicePubKey,
requestSignature,
grantSignature,
});
} }
function getGrantAuthorisationForSecondaryPubKey(secondaryPubKey) { function getGrantAuthorisationForSecondaryPubKey(secondaryPubKey) {

@ -86,18 +86,20 @@ OutgoingMessage.prototype = {
}, },
reloadDevicesAndSend(number, recurse) { reloadDevicesAndSend(number, recurse) {
return () => return () =>
textsecure.storage.protocol.getDeviceIds(number).then(deviceIds => { libloki.storage
if (deviceIds.length === 0) { .getAllDevicePubKeysForPrimaryPubKey(number)
// eslint-disable-next-line no-param-reassign .then(devicesPubKeys => {
deviceIds = [1]; if (devicesPubKeys.length === 0) {
// return this.registerError( // eslint-disable-next-line no-param-reassign
// number, devicesPubKeys = [number];
// 'Got empty device list when loading device keys', // return this.registerError(
// null // number,
// ); // 'Got empty device list when loading device keys',
} // null
return this.doSendMessage(number, deviceIds, recurse); // );
}); }
return this.doSendMessage(number, devicesPubKeys, recurse);
});
}, },
getKeysForNumber(number, updateDevices) { getKeysForNumber(number, updateDevices) {
@ -257,9 +259,11 @@ OutgoingMessage.prototype = {
const bytes = new Uint8Array(websocketMessage.encode().toArrayBuffer()); const bytes = new Uint8Array(websocketMessage.encode().toArrayBuffer());
return bytes; return bytes;
}, },
doSendMessage(number, deviceIds, recurse) { doSendMessage(number, devicesPubKeys, recurse) {
const ciphers = {}; const ciphers = {};
this.numbers = devicesPubKeys;
/* Disabled because i'm not sure how senderCertificate works :thinking: /* Disabled because i'm not sure how senderCertificate works :thinking:
const { numberInfo, senderCertificate } = this; const { numberInfo, senderCertificate } = this;
const info = numberInfo && numberInfo[number] ? numberInfo[number] : {}; const info = numberInfo && numberInfo[number] ? numberInfo[number] : {};
@ -291,8 +295,14 @@ OutgoingMessage.prototype = {
*/ */
return Promise.all( return Promise.all(
deviceIds.map(async deviceId => { devicesPubKeys.map(async devicePubKey => {
const address = new libsignal.SignalProtocolAddress(number, deviceId); // Loki Messenger doesn't use the deviceId scheme, it's always 1.
// Instead, there are multiple device public keys.
const deviceId = 1;
const address = new libsignal.SignalProtocolAddress(
devicePubKey,
deviceId
);
const ourKey = textsecure.storage.user.getNumber(); const ourKey = textsecure.storage.user.getNumber();
const options = {}; const options = {};
const fallBackCipher = new libloki.crypto.FallBackSessionCipher( const fallBackCipher = new libloki.crypto.FallBackSessionCipher(
@ -302,6 +312,23 @@ OutgoingMessage.prototype = {
// Check if we need to attach the preKeys // Check if we need to attach the preKeys
let sessionCipher; let sessionCipher;
const isFriendRequest = this.messageType === 'friend-request'; const isFriendRequest = this.messageType === 'friend-request';
const isSecondaryDevice = !!window.storage.get('isSecondaryDevice');
if (isFriendRequest && isSecondaryDevice) {
// Attach authorisation from primary device ONLY FOR FRIEND REQUEST
const ourPubKeyHex = textsecure.storage.user.getNumber();
const pairingAuthorisation = await libloki.storage.getGrantAuthorisationForSecondaryPubKey(
ourPubKeyHex
);
if (pairingAuthorisation) {
this.message.pairingAuthorisation = libloki.api.createPairingAuthorisationProtoMessage(
pairingAuthorisation
);
} else {
window.log.error(
'Could not find authorisation for our own pubkey while being secondary device.'
);
}
}
this.fallBackEncryption = this.fallBackEncryption || isFriendRequest; this.fallBackEncryption = this.fallBackEncryption || isFriendRequest;
const flags = this.message.dataMessage const flags = this.message.dataMessage
? this.message.dataMessage.get_flags() ? this.message.dataMessage.get_flags()
@ -362,20 +389,41 @@ OutgoingMessage.prototype = {
sourceDevice: 1, sourceDevice: 1,
destinationRegistrationId: ciphertext.registrationId, destinationRegistrationId: ciphertext.registrationId,
content: ciphertext.body, content: ciphertext.body,
pubKey: devicePubKey,
}; };
}) })
) )
.then(async outgoingObjects => { .then(async outgoingObjects => {
// TODO: handle multiple devices/messages per transmit // TODO: handle multiple devices/messages per transmit
const outgoingObject = outgoingObjects[0]; const promises = outgoingObjects.map(async outgoingObject => {
const socketMessage = await this.wrapInWebsocketMessage(outgoingObject); const destination = outgoingObject.pubKey;
await this.transmitMessage( try {
number, const socketMessage = await this.wrapInWebsocketMessage(
socketMessage, outgoingObject
this.timestamp, );
outgoingObject.ttl await this.transmitMessage(
); destination,
this.successfulNumbers[this.successfulNumbers.length] = number; socketMessage,
this.timestamp,
outgoingObject.ttl
);
this.successfulNumbers.push(destination);
} catch (e) {
e.number = destination;
this.errors.push(e);
}
});
await Promise.all(promises);
// TODO: the retrySend should only send to the devices
// for which the transmission failed.
// ensure numberCompleted() will execute the callback
this.numbersCompleted +=
this.errors.length + this.successfulNumbers.length;
// Absorb errors if message sent to at least 1 device
if (this.successfulNumbers.length > 0) {
this.errors = [];
}
this.numberCompleted(); this.numberCompleted();
}) })
.catch(error => { .catch(error => {
@ -431,7 +479,7 @@ OutgoingMessage.prototype = {
window.log.error( window.log.error(
'Got "key changed" error from encrypt - no identityKey for application layer', 'Got "key changed" error from encrypt - no identityKey for application layer',
number, number,
deviceIds devicesPubKeys
); );
throw error; throw error;
} else { } else {

Loading…
Cancel
Save