Merge pull request #613 from BeaudanBrown/bugfixes

[multi-device] Bugfixes and throttle pairing check
pull/622/head
Beaudan Campbell-Brown 6 years ago committed by GitHub
commit 5a630118ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1235,15 +1235,19 @@
if (activeAt !== null) { if (activeAt !== null) {
activeAt = activeAt || Date.now(); activeAt = activeAt || Date.now();
} }
const ourAuthorisations = await libloki.storage.getPrimaryDeviceMapping( const ourPrimaryKey = window.storage.get('primaryDevicePubKey');
window.storage.get('primaryDevicePubKey') const ourDevices = await libloki.storage.getAllDevicePubKeysForPrimaryPubKey(
ourPrimaryKey
); );
const isSecondaryDevice = // TODO: We should probably just *not* send any secondary devices and
ourAuthorisations && // just load them all and send FRs when we get the mapping
ourAuthorisations.some(auth => auth.secondaryDevicePubKey === id); const isOurSecondaryDevice =
id !== ourPrimaryKey &&
if (isSecondaryDevice) { ourDevices &&
await conversation.setSecondaryStatus(true); ourDevices.some(devicePubKey => devicePubKey === id);
if (isOurSecondaryDevice) {
await conversation.setSecondaryStatus(true, ourPrimaryKey);
} }
if (conversation.isFriendRequestStatusNone()) { if (conversation.isFriendRequestStatusNone()) {

@ -766,9 +766,15 @@
isSecondaryDevice() { isSecondaryDevice() {
return !!this.get('secondaryStatus'); return !!this.get('secondaryStatus');
}, },
async setSecondaryStatus(newStatus) { getPrimaryDevicePubKey() {
return this.get('primaryDevicePubKey') || this.id;
},
async setSecondaryStatus(newStatus, primaryDevicePubKey) {
if (this.get('secondaryStatus') !== newStatus) { if (this.get('secondaryStatus') !== newStatus) {
this.set({ secondaryStatus: newStatus }); this.set({
secondaryStatus: newStatus,
primaryDevicePubKey,
});
await window.Signal.Data.updateConversation(this.id, this.attributes, { await window.Signal.Data.updateConversation(this.id, this.attributes, {
Conversation: Whisper.Conversation, Conversation: Whisper.Conversation,
}); });
@ -804,7 +810,17 @@
if (!response) { if (!response) {
return; return;
} }
const pending = await this.getFriendRequests(direction, status); const primaryConversation = ConversationController.get(
this.getPrimaryDevicePubKey()
);
// Should never happen
if (!primaryConversation) {
return;
}
const pending = await primaryConversation.getFriendRequests(
direction,
status
);
await Promise.all( await Promise.all(
pending.map(async request => { pending.map(async request => {
if (request.hasErrors()) { if (request.hasErrors()) {
@ -815,7 +831,7 @@
await window.Signal.Data.saveMessage(request.attributes, { await window.Signal.Data.saveMessage(request.attributes, {
Message: Whisper.Message, Message: Whisper.Message,
}); });
this.trigger('updateMessage', request); primaryConversation.trigger('updateMessage', request);
}) })
); );
}, },

@ -367,8 +367,6 @@
await window.Signal.Data.saveMessage(this.attributes, { await window.Signal.Data.saveMessage(this.attributes, {
Message: Whisper.Message, Message: Whisper.Message,
}); });
const pubKey = this.get('conversationId');
await libloki.storage.saveAllPairingAuthorisationsFor(pubKey);
conversation.onAcceptFriendRequest(); conversation.onAcceptFriendRequest();
}, },
async declineFriendRequest() { async declineFriendRequest() {

@ -213,7 +213,7 @@
Whisper.events.off('devicePairingRequestReceived'); Whisper.events.off('devicePairingRequestReceived');
}); });
dialog.once('devicePairingRequestAccepted', (pubKey, cb) => dialog.on('devicePairingRequestAccepted', (pubKey, cb) =>
Whisper.events.trigger('devicePairingRequestAccepted', pubKey, cb) Whisper.events.trigger('devicePairingRequestAccepted', pubKey, cb)
); );
dialog.on('devicePairingRequestRejected', pubKey => dialog.on('devicePairingRequestRejected', pubKey =>

@ -92,7 +92,7 @@
if (!errors) { if (!errors) {
this.$('.transmissionStatus').text(i18n('provideDeviceAlias')); this.$('.transmissionStatus').text(i18n('provideDeviceAlias'));
this.$('#deviceAliasView').show(); this.$('#deviceAliasView').show();
this.$('#deviceAlias').on('keydown', e => { this.$('#deviceAlias').on('input', e => {
if (e.target.value.trim()) { if (e.target.value.trim()) {
this.$('.requestAcceptedView .ok').removeAttr('disabled'); this.$('.requestAcceptedView .ok').removeAttr('disabled');
} else { } else {

@ -114,7 +114,7 @@
buffers.forEach(buffer => { buffers.forEach(buffer => {
// bytebuffer container expands and increments // bytebuffer container expands and increments
// offset automatically // offset automatically
result.writeVarint32(buffer.limit); result.writeInt32(buffer.limit);
result.append(buffer); result.append(buffer);
}); });
result.limit = result.offset; result.limit = result.offset;

@ -5,6 +5,9 @@
(function() { (function() {
window.libloki = window.libloki || {}; window.libloki = window.libloki || {};
const timers = {};
const REFRESH_DELAY = 60 * 1000;
async function getPreKeyBundleForContact(pubKey) { async function getPreKeyBundleForContact(pubKey) {
const myKeyPair = await textsecure.storage.protocol.getIdentityKeyPair(); const myKeyPair = await textsecure.storage.protocol.getIdentityKeyPair();
const identityKey = myKeyPair.pubKey; const identityKey = myKeyPair.pubKey;
@ -149,6 +152,12 @@
// if the device is a secondary device, // if the device is a secondary device,
// fetch the device mappings for its primary device // fetch the device mappings for its primary device
async function saveAllPairingAuthorisationsFor(pubKey) { async function saveAllPairingAuthorisationsFor(pubKey) {
// Will be false if there is no timer
const cacheValid = timers[pubKey] > Date.now();
if (cacheValid) {
return;
}
timers[pubKey] = Date.now() + REFRESH_DELAY;
const authorisations = await getPrimaryDeviceMapping(pubKey); const authorisations = await getPrimaryDeviceMapping(pubKey);
await Promise.all( await Promise.all(
authorisations.map(authorisation => authorisations.map(authorisation =>
@ -163,7 +172,10 @@
authorisation.secondaryDevicePubKey, authorisation.secondaryDevicePubKey,
'private' 'private'
); );
await conversation.setSecondaryStatus(true); await conversation.setSecondaryStatus(
true,
authorisation.primaryDevicePubKey
);
await window.Signal.Data.createOrUpdatePairingAuthorisation(authorisation); await window.Signal.Data.createOrUpdatePairingAuthorisation(authorisation);
} }
@ -199,6 +211,7 @@
// Transforms signatures from base64 to ArrayBuffer! // Transforms signatures from base64 to ArrayBuffer!
async function getAuthorisationForSecondaryPubKey(secondaryPubKey) { async function getAuthorisationForSecondaryPubKey(secondaryPubKey) {
await saveAllPairingAuthorisationsFor(secondaryPubKey);
const authorisation = await window.Signal.Data.getAuthorisationForSecondaryPubKey( const authorisation = await window.Signal.Data.getAuthorisationForSecondaryPubKey(
secondaryPubKey secondaryPubKey
); );

@ -596,7 +596,7 @@
// throws if invalid // throws if invalid
this.validatePubKeyHex(secondaryDevicePubKey); this.validatePubKeyHex(secondaryDevicePubKey);
// we need a conversation for sending a message // we need a conversation for sending a message
await ConversationController.getOrCreateAndWait( const secondaryConversation = await ConversationController.getOrCreateAndWait(
secondaryDevicePubKey, secondaryDevicePubKey,
'private' 'private'
); );
@ -626,6 +626,13 @@
authorisation, authorisation,
secondaryDevicePubKey secondaryDevicePubKey
); );
// Always be friends with secondary devices
await secondaryConversation.setFriendRequestStatus(
window.friends.friendRequestStatusEnum.friends,
{
blockSync: true,
}
);
}, },
validatePubKeyHex(pubKey) { validatePubKeyHex(pubKey) {
const c = new Whisper.Conversation({ const c = new Whisper.Conversation({

@ -14,7 +14,7 @@ ProtoParser.prototype = {
if (this.buffer.limit === this.buffer.offset) { if (this.buffer.limit === this.buffer.offset) {
return undefined; // eof return undefined; // eof
} }
const len = this.buffer.readVarint32(); const len = this.buffer.readInt32();
const nextBuffer = this.buffer const nextBuffer = this.buffer
.slice(this.buffer.offset, this.buffer.offset + len) .slice(this.buffer.offset, this.buffer.offset + len)
.toArrayBuffer(); .toArrayBuffer();

@ -1104,13 +1104,13 @@ MessageReceiver.prototype.extend({
window.log.info( window.log.info(
`Received pairing authorisation from ${primaryDevicePubKey}` `Received pairing authorisation from ${primaryDevicePubKey}`
); );
await libloki.storage.savePairingAuthorisation(pairingAuthorisation);
// Set current device as secondary. // Set current device as secondary.
// This will ensure the authorisation is sent // This will ensure the authorisation is sent
// along with each friend request. // along with each friend request.
window.storage.remove('secondaryDeviceStatus'); window.storage.remove('secondaryDeviceStatus');
window.storage.put('isSecondaryDevice', true); window.storage.put('isSecondaryDevice', true);
window.storage.put('primaryDevicePubKey', primaryDevicePubKey); window.storage.put('primaryDevicePubKey', primaryDevicePubKey);
await libloki.storage.savePairingAuthorisation(pairingAuthorisation);
const primaryConversation = await ConversationController.getOrCreateAndWait( const primaryConversation = await ConversationController.getOrCreateAndWait(
primaryDevicePubKey, primaryDevicePubKey,
'private' 'private'
@ -1464,16 +1464,11 @@ MessageReceiver.prototype.extend({
async handleSyncMessage(envelope, syncMessage) { async handleSyncMessage(envelope, syncMessage) {
const ourNumber = textsecure.storage.user.getNumber(); const ourNumber = textsecure.storage.user.getNumber();
// NOTE: Maybe we should be caching this list? // NOTE: Maybe we should be caching this list?
const ourAuthorisations = await libloki.storage.getPrimaryDeviceMapping( const ourDevices = await libloki.storage.getAllDevicePubKeysForPrimaryPubKey(
ourNumber window.storage.get('primaryDevicePubKey')
); );
const validSyncSender = const validSyncSender =
ourAuthorisations && ourDevices && ourDevices.some(devicePubKey => devicePubKey === ourNumber);
ourAuthorisations.some(
auth =>
auth.secondaryDevicePubKey === ourNumber ||
auth.primaryDevicePubKey === ourNumber
);
if (!validSyncSender) { if (!validSyncSender) {
throw new Error( throw new Error(
"Received sync message from a device we aren't paired with" "Received sync message from a device we aren't paired with"

@ -18,7 +18,7 @@ describe('ContactBuffer', () => {
const contactInfoBuffer = contactInfo.encode().toArrayBuffer(); const contactInfoBuffer = contactInfo.encode().toArrayBuffer();
for (let i = 0; i < 3; i += 1) { for (let i = 0; i < 3; i += 1) {
buffer.writeVarint32(contactInfoBuffer.byteLength); buffer.writeInt32(contactInfoBuffer.byteLength);
buffer.append(contactInfoBuffer); buffer.append(contactInfoBuffer);
buffer.append(avatarBuffer.clone()); buffer.append(avatarBuffer.clone());
} }
@ -69,7 +69,7 @@ describe('GroupBuffer', () => {
const groupInfoBuffer = groupInfo.encode().toArrayBuffer(); const groupInfoBuffer = groupInfo.encode().toArrayBuffer();
for (let i = 0; i < 3; i += 1) { for (let i = 0; i < 3; i += 1) {
buffer.writeVarint32(groupInfoBuffer.byteLength); buffer.writeInt32(groupInfoBuffer.byteLength);
buffer.append(groupInfoBuffer); buffer.append(groupInfoBuffer);
buffer.append(avatarBuffer.clone()); buffer.append(avatarBuffer.clone());
} }

Loading…
Cancel
Save