Merge pull request #38 from Mikunj/fix/duplicate-messages

[Pending] Fix duplicate messages
pull/40/head
sachaaaaa 7 years ago committed by GitHub
commit 19e664bf38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -685,6 +685,10 @@
friendStatus: 'pending',
direction: 'incoming',
preKeyBundle: null,
timestamp: null,
source: null,
sourceDevice: null,
received_at: null,
...options,
};
@ -695,13 +699,13 @@
return;
}
const lastMessage = this.get('timestamp') || Date.now();
const timestamp = _options.timestamp || this.get('timestamp') || Date.now();
window.log.info(
'adding friend request for',
this.ourNumber,
this.idForLogging(),
lastMessage
timestamp
);
this.lastMessageStatus = 'sending';
@ -731,12 +735,12 @@
}
// Add the new message
const timestamp = Date.now();
const received_at = _options.received_at || Date.now();
const message = {
conversationId: this.id,
type: 'friend-request',
sent_at: lastMessage,
received_at: timestamp,
sent_at: timestamp,
received_at,
unread: 1,
from: this.id,
to: this.ourNumber,
@ -744,6 +748,8 @@
direction: _options.direction,
body,
preKeyBundle: _options.preKeyBundle,
source: _options.source,
sourceDevice: _options.sourceDevice,
};
const id = await window.Signal.Data.saveMessage(message, {

@ -664,13 +664,14 @@ async function searchConversations(query, { ConversationCollection }) {
}
// Message
const MESSAGE_PRE_KEYS = ['identityKey', 'preKey', 'signature', 'signedKey'].map(k => `preKeyBundle.${k}`);
async function getMessageCount() {
return channels.getMessageCount();
}
async function saveMessage(data, { forceSave, Message } = {}) {
const id = await channels.saveMessage(_cleanData(data), { forceSave });
const updated = keysFromArrayBuffer(MESSAGE_PRE_KEYS, data);
const id = await channels.saveMessage(_cleanData(updated), { forceSave });
Message.refreshExpirationTimer();
return id;
}
@ -713,7 +714,8 @@ async function saveLegacyMessage(data) {
}
async function saveMessages(arrayOfMessages, { forceSave } = {}) {
await channels.saveMessages(_cleanData(arrayOfMessages), { forceSave });
const updated = arrayOfMessages.map(m => keysFromArrayBuffer(MESSAGE_PRE_KEYS, m));
await channels.saveMessages(_cleanData(updated), { forceSave });
}
async function removeMessage(id, { Message }) {
@ -738,13 +740,16 @@ async function getMessageById(id, { Message }) {
return null;
}
return new Message(message);
const encoded = keysToArrayBuffer(MESSAGE_PRE_KEYS, message);
return new Message(encoded);
}
// For testing only
async function getAllMessages({ MessageCollection }) {
const messages = await channels.getAllMessages();
return new MessageCollection(messages);
const encoded = messages.map(m => keysToArrayBuffer(MESSAGE_PRE_KEYS, m));
return new MessageCollection(encoded);
}
async function getAllMessageIds() {
@ -766,7 +771,9 @@ async function getMessageBySender(
return null;
}
return new Message(messages[0]);
const encoded = keysToArrayBuffer(MESSAGE_PRE_KEYS, messages[0]);
return new Message(encoded);
}
async function getUnreadByConversation(conversationId, { MessageCollection }) {
@ -784,7 +791,9 @@ async function getMessagesByConversation(
type,
});
return new MessageCollection(messages);
const encoded = messages.map(m => keysToArrayBuffer(MESSAGE_PRE_KEYS, m));
return new MessageCollection(encoded);
}
async function removeAllMessagesInConversation(
@ -819,22 +828,26 @@ async function removeAllMessagesInConversation(
async function getMessagesBySentAt(sentAt, { MessageCollection }) {
const messages = await channels.getMessagesBySentAt(sentAt);
return new MessageCollection(messages);
const encoded = messages.map(m => keysToArrayBuffer(MESSAGE_PRE_KEYS, m));
return new MessageCollection(encoded);
}
async function getExpiredMessages({ MessageCollection }) {
const messages = await channels.getExpiredMessages();
return new MessageCollection(messages);
const encoded = messages.map(m => keysToArrayBuffer(MESSAGE_PRE_KEYS, m));
return new MessageCollection(encoded);
}
async function getOutgoingWithoutExpiresAt({ MessageCollection }) {
const messages = await channels.getOutgoingWithoutExpiresAt();
return new MessageCollection(messages);
const encoded = messages.map(m => keysToArrayBuffer(MESSAGE_PRE_KEYS, m));
return new MessageCollection(encoded);
}
async function getNextExpiringMessage({ MessageCollection }) {
const messages = await channels.getNextExpiringMessage();
return new MessageCollection(messages);
const encoded = messages.map(m => keysToArrayBuffer(MESSAGE_PRE_KEYS, m));
return new MessageCollection(encoded);
}
// Unprocessed

@ -178,12 +178,13 @@
});
}
},
async showFriendRequest({ pubKey, message, preKeyBundle }) {
async showFriendRequest({ pubKey, message, preKeyBundle, options }) {
const controller = window.ConversationController;
const conversation = await controller.getOrCreateAndWait(pubKey, 'private');
if (conversation) {
conversation.addFriendRequest(message, {
preKeyBundle: preKeyBundle || null,
...options,
});
}
},

@ -934,11 +934,17 @@ MessageReceiver.prototype.extend({
return this.innerHandleContentMessage(envelope, plaintext);
});
},
promptUserToAcceptFriendRequest(pubKey, message, preKeyBundle) {
promptUserToAcceptFriendRequest(envelope, message, preKeyBundleMessage) {
window.Whisper.events.trigger('showFriendRequest', {
pubKey,
pubKey: envelope.source,
message,
preKeyBundle,
preKeyBundle: this.decodePreKeyBundleMessage(preKeyBundleMessage),
options: {
source: envelope.source,
sourceDevice: envelope.sourceDevice,
timestamp: envelope.timestamp.toNumber(),
receivedAt: envelope.receivedAt,
},
});
},
// A handler function for when a friend request is accepted or declined
@ -973,52 +979,49 @@ MessageReceiver.prototype.extend({
const content = textsecure.protobuf.Content.decode(plaintext);
if (envelope.type === textsecure.protobuf.Envelope.Type.FRIEND_REQUEST) {
// only prompt friend request if there is no conversation yet
let conversation;
try {
conversation = ConversationController.get(envelope.source);
} catch (e) { }
// only prompt friend request if there is no conversation yet
if (!conversation) {
this.promptUserToAcceptFriendRequest(
envelope.source,
envelope,
content.dataMessage.body,
content.preKeyBundle,
content.preKeyBundleMessage,
);
return;
}
}
// Check if our friend request got accepted
if (content.preKeyBundle) {
// By default we don't want to save the preKey
let savePreKey = false;
// The conversation
let conversation = null;
try {
conversation = ConversationController.get(envelope.source);
// We only want to save the preKey if we have a outgoing friend request which is pending
const pending = await conversation.getPendingFriendRequests('outgoing');
const successful = pending.filter(p => !p.hasErrors());
// Save the key only if we have an outgoing friend request
savePreKey = (successful.length > 0);
} catch (e) {}
// Save the pre key if we have a conversation
if (savePreKey && conversation) {
await this.handlePreKeyBundleMessage(
envelope.source,
content.preKeyBundle
);
// Update the conversation
await conversation.onFriendRequestAccepted();
} else {
const keyExchangeComplete = conversation.isKeyExchangeCompleted();
// Check here if we received preKeys from the other user
// We are certain that other user accepted the friend request IF:
// - The message has a preKeyBundleMessage
// - We have an outgoing friend request that is pending
// The second check is crucial because it makes sure we don't save the preKeys of the incoming friend request (which is saved only when we press accept)
if (!keyExchangeComplete && content.preKeyBundleMessage) {
// Check for any outgoing friend requests
const pending = await conversation.getPendingFriendRequests('outgoing');
const successful = pending.filter(p => !p.hasErrors());
// Save the key only if we have an outgoing friend request
const savePreKey = (successful.length > 0);
// Save the pre key
if (savePreKey) {
await this.handlePreKeyBundleMessage(
envelope.source,
this.decodePreKeyBundleMessage(content.preKeyBundleMessage),
);
return;
// Update the conversation
await conversation.onFriendRequestAccepted();
}
}
}
// Exit early since the friend request reply will be a regular empty message
return;
}
if (content.syncMessage) {
@ -1235,8 +1238,7 @@ MessageReceiver.prototype.extend({
return this.removeFromCache(envelope);
},
async handlePreKeyBundleMessage(pubKey, preKeyBundleMessage) {
const { preKeyId, signedKeyId } = preKeyBundleMessage;
decodePreKeyBundleMessage(preKeyBundleMessage) {
const [identityKey, preKey, signedKey, signature] = [
preKeyBundleMessage.identityKey,
preKeyBundleMessage.preKey,
@ -1244,6 +1246,24 @@ MessageReceiver.prototype.extend({
preKeyBundleMessage.signature,
].map(k => dcodeIO.ByteBuffer.wrap(k).toArrayBuffer());
return {
...preKeyBundleMessage,
identityKey,
preKey,
signedKey,
signature,
};
},
async handlePreKeyBundleMessage(pubKey, preKeyBundleMessage) {
const {
preKeyId,
signedKeyId,
identityKey,
preKey,
signedKey,
signature,
} = preKeyBundleMessage;
if (pubKey != StringView.arrayBufferToHex(identityKey)) {
throw new Error(
'Error in handlePreKeyBundleMessage: envelope pubkey does not match pubkey in prekey bundle'

Loading…
Cancel
Save