From 804fc076ccc5f8dfc6a2ef2607ed856d3ede6379 Mon Sep 17 00:00:00 2001 From: Beaudan Date: Thu, 4 Jul 2019 12:19:07 +1000 Subject: [PATCH 1/3] Refresh swarm list 1 time for outgoing messages --- js/modules/loki_message_api.js | 48 +++++++++++++++++++++++-------- libtextsecure/outgoing_message.js | 2 +- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index fdf12735e..6f9dbe7b8 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -70,7 +70,7 @@ const trySendP2p = async (pubKey, data64, isPing, messageEventData) => { class LokiMessageAPI { constructor(ourKey) { this.jobQueue = new window.JobQueue(); - this.sendingSwarmNodes = {}; + this.sendingData = {}; this.ourKey = ourKey; } @@ -102,13 +102,13 @@ class LokiMessageAPI { ttl ); // Using timestamp as a unique identifier - this.sendingSwarmNodes[timestamp] = lokiSnodeAPI.getSwarmNodesForPubKey( - pubKey - ); - if (this.sendingSwarmNodes[timestamp].length < numConnections) { - const freshNodes = await lokiSnodeAPI.getFreshSwarmNodes(pubKey); - await lokiSnodeAPI.updateSwarmNodes(pubKey, freshNodes); - this.sendingSwarmNodes[timestamp] = freshNodes; + const swarm = await lokiSnodeAPI.getSwarmNodesForPubKey(pubKey); + this.sendingData[timestamp] = { + swarm, + freshList: false, + }; + if (this.sendingData[timestamp].swarm.length < numConnections) { + await this.refreshSendingSwarm(pubKey, timestamp); } const params = { @@ -124,7 +124,7 @@ class LokiMessageAPI { const connectionPromise = this.openSendConnection(params).finally(() => { completedConnections += 1; if (completedConnections >= numConnections) { - delete this.sendingSwarmNodes[timestamp]; + delete this.sendingData[timestamp]; } }); promises.push(connectionPromise); @@ -167,9 +167,17 @@ class LokiMessageAPI { log.info(`Successful storage message to ${pubKey}`); } + async refreshSendingSwarm(pubKey, timestamp) { + const freshNodes = await lokiSnodeAPI.getFreshSwarmNodes(pubKey); + await lokiSnodeAPI.updateSwarmNodes(pubKey, freshNodes); + this.sendingData[timestamp].swarm = freshNodes; + this.sendingData[timestamp].freshList = true; + return true; + } + async openSendConnection(params) { - while (!_.isEmpty(this.sendingSwarmNodes[params.timestamp])) { - const snode = this.sendingSwarmNodes[params.timestamp].shift(); + while (!_.isEmpty(this.sendingData[params.timestamp].swarm)) { + const snode = this.sendingData[params.timestamp].swarm.shift(); // TODO: Revert back to using snode address instead of IP const successfulSend = await this.sendToNode( snode.ip, @@ -180,6 +188,21 @@ class LokiMessageAPI { return true; } } + + if (!this.sendingData[params.timestamp].freshList) { + // Ensure that there is only a single refresh per outgoing message + if (!this.sendingData[params.timestamp].refreshPromise) { + this.sendingData[ + params.timestamp + ].refreshPromise = this.refreshSendingSwarm( + params.pubKey, + params.timestamp + ); + } + await this.sendingData[params.timestamp].refreshPromise; + // Retry with a fresh list again + return this.openSendConnection(params); + } return false; } @@ -202,7 +225,8 @@ class LokiMessageAPI { if (e instanceof textsecure.WrongSwarmError) { const { newSwarm } = e; await lokiSnodeAPI.updateSwarmNodes(params.pubKey, newSwarm); - this.sendingSwarmNodes[params.timestamp] = newSwarm; + this.sendingData[params.timestamp].swarm = newSwarm; + this.sendingData[params.timestamp].freshList = true; return false; } else if (e instanceof textsecure.WrongDifficultyError) { const { newDifficulty } = e; diff --git a/libtextsecure/outgoing_message.js b/libtextsecure/outgoing_message.js index 5700b860d..abb4b3b9c 100644 --- a/libtextsecure/outgoing_message.js +++ b/libtextsecure/outgoing_message.js @@ -12,7 +12,7 @@ /* eslint-disable more/no-then */ /* eslint-disable no-unreachable */ -const NUM_SEND_CONNECTIONS = 2; +const NUM_SEND_CONNECTIONS = 3; function OutgoingMessage( server, From b49be51f36358d0defe8509027cd423b5fd99a78 Mon Sep 17 00:00:00 2001 From: Beaudan Date: Thu, 4 Jul 2019 12:28:52 +1000 Subject: [PATCH 2/3] Don't return early if recalculating PoW --- js/modules/loki_message_api.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index 6f9dbe7b8..9a6f08e15 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -153,7 +153,11 @@ class LokiMessageAPI { } catch (e) { if (e instanceof textsecure.WrongDifficultyError) { // Force nonce recalculation - this.sendMessage(pubKey, data, messageTimeStamp, ttl, options); + // NOTE: Currently if there are snodes with conflicting difficulties we + // will send the message twice (or more). Won't affect client side but snodes + // could store the same message multiple times because they will have different + // timestamps (and therefore nonces) + await this.sendMessage(pubKey, data, messageTimeStamp, ttl, options); return; } throw e; From 9910ef0c13d1525593fcf154a9a0ac18ee387bea Mon Sep 17 00:00:00 2001 From: Beaudan Date: Thu, 4 Jul 2019 13:09:29 +1000 Subject: [PATCH 3/3] Rename bool --- js/modules/loki_message_api.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index 9a6f08e15..c16b6f35f 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -105,7 +105,7 @@ class LokiMessageAPI { const swarm = await lokiSnodeAPI.getSwarmNodesForPubKey(pubKey); this.sendingData[timestamp] = { swarm, - freshList: false, + hasFreshList: false, }; if (this.sendingData[timestamp].swarm.length < numConnections) { await this.refreshSendingSwarm(pubKey, timestamp); @@ -175,7 +175,7 @@ class LokiMessageAPI { const freshNodes = await lokiSnodeAPI.getFreshSwarmNodes(pubKey); await lokiSnodeAPI.updateSwarmNodes(pubKey, freshNodes); this.sendingData[timestamp].swarm = freshNodes; - this.sendingData[timestamp].freshList = true; + this.sendingData[timestamp].hasFreshList = true; return true; } @@ -193,7 +193,7 @@ class LokiMessageAPI { } } - if (!this.sendingData[params.timestamp].freshList) { + if (!this.sendingData[params.timestamp].hasFreshList) { // Ensure that there is only a single refresh per outgoing message if (!this.sendingData[params.timestamp].refreshPromise) { this.sendingData[ @@ -230,7 +230,7 @@ class LokiMessageAPI { const { newSwarm } = e; await lokiSnodeAPI.updateSwarmNodes(params.pubKey, newSwarm); this.sendingData[params.timestamp].swarm = newSwarm; - this.sendingData[params.timestamp].freshList = true; + this.sendingData[params.timestamp].hasFreshList = true; return false; } else if (e instanceof textsecure.WrongDifficultyError) { const { newDifficulty } = e;