diff --git a/js/conversation_controller.js b/js/conversation_controller.js index 7a15d689a..796dd20ed 100644 --- a/js/conversation_controller.js +++ b/js/conversation_controller.js @@ -185,7 +185,6 @@ await window.Signal.Data.saveConversation(conversation.attributes, { Conversation: Whisper.Conversation, }); - window.LokiSnodeAPI.refreshSwarmNodesForPubKey(id); } catch (error) { window.log.error( 'Conversation save failed! ', @@ -200,9 +199,10 @@ return conversation; }; - conversation.initialPromise = create().then(() => - conversation.updateProfileAvatar() - ); + conversation.initialPromise = create().then(async () => { + window.lokiSnodeAPI.refreshSwarmNodesForPubKey(id); + conversation.updateProfileAvatar(); + }); return conversation; }, diff --git a/js/models/conversations.js b/js/models/conversations.js index 91c3616c1..d8709a37c 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -78,7 +78,7 @@ friendRequestStatus: FriendRequestStatusEnum.none, unlockTimestamp: null, // Timestamp used for expiring friend requests. sessionResetStatus: SessionResetEnum.none, - swarmNodes: new Set([]), + swarmNodes: [], isOnline: false, }; }, @@ -1406,6 +1406,12 @@ }, }; }, + async updateSwarmNodes(swarmNodes) { + this.set({ swarmNodes }); + await window.Signal.Data.updateConversation(this.id, this.attributes, { + Conversation: Whisper.Conversation, + }); + }, async updateLastMessage() { if (!this.id) { return; diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index e802dab13..e91812cc3 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -1,6 +1,6 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable no-loop-func */ -/* global log, dcodeIO, window, callWorker, Whisper, lokiP2pAPI */ +/* global log, dcodeIO, window, callWorker, lokiP2pAPI, lokiSnodeAPI */ const nodeFetch = require('node-fetch'); const _ = require('lodash'); @@ -109,7 +109,7 @@ class LokiMessageAPI { let successfulRequests = 0; let canResolve = true; - let swarmNodes = await window.Signal.Data.getSwarmNodesByPubkey(pubKey); + let swarmNodes = await lokiSnodeAPI.getSwarmNodesForPubKey(pubKey); const nodeComplete = nodeUrl => { completedNodes.push(nodeUrl); @@ -148,7 +148,7 @@ class LokiMessageAPI { nodeComplete(nodeUrl); } else { log.error('Loki SendMessages:', e); - if (window.LokiSnodeAPI.unreachableNode(pubKey, nodeUrl)) { + if (lokiSnodeAPI.unreachableNode(pubKey, nodeUrl)) { nodeComplete(nodeUrl); } } @@ -160,7 +160,7 @@ class LokiMessageAPI { throw new window.textsecure.DNSResolutionError('Sending messages'); } if (swarmNodes.length === 0) { - const freshNodes = await window.LokiSnodeAPI.getFreshSwarmNodes(pubKey); + const freshNodes = await lokiSnodeAPI.getFreshSwarmNodes(pubKey); swarmNodes = _.difference(freshNodes, completedNodes); if (swarmNodes.length === 0) { if (successfulRequests !== 0) { @@ -172,13 +172,11 @@ class LokiMessageAPI { new Error('Ran out of swarm nodes to query') ); } - await window.Signal.Data.saveSwarmNodesForPubKey(pubKey, swarmNodes, { - Conversation: Whisper.Conversation, - }); + lokiSnodeAPI.updateSwarmNodes(pubKey, swarmNodes); } const remainingRequests = - MINIMUM_SUCCESSFUL_REQUESTS - completedNodes.length; + MINIMUM_SUCCESSFUL_REQUESTS - successfulRequests; await Promise.all( swarmNodes @@ -196,7 +194,7 @@ class LokiMessageAPI { let ourSwarmNodes; try { - ourSwarmNodes = await window.LokiSnodeAPI.getOurSwarmNodes(); + ourSwarmNodes = await lokiSnodeAPI.getOurSwarmNodes(); } catch (e) { throw new window.textsecure.EmptySwarmError(ourKey, e); } @@ -224,7 +222,7 @@ class LokiMessageAPI { nodeComplete(nodeUrl); if (result.lastHash) { - window.LokiSnodeAPI.updateLastHash(nodeUrl, result.lastHash); + lokiSnodeAPI.updateLastHash(nodeUrl, result.lastHash); callback(result.messages); } successfulRequests += 1; @@ -242,7 +240,7 @@ class LokiMessageAPI { nodeComplete(nodeUrl); } else { log.error('Loki RetrieveMessages:', e); - if (window.LokiSnodeAPI.unreachableNode(ourKey, nodeUrl)) { + if (lokiSnodeAPI.unreachableNode(ourKey, nodeUrl)) { nodeComplete(nodeUrl); } } @@ -255,7 +253,7 @@ class LokiMessageAPI { } if (Object.keys(ourSwarmNodes).length === 0) { try { - ourSwarmNodes = await window.LokiSnodeAPI.getOurSwarmNodes(); + ourSwarmNodes = await lokiSnodeAPI.getOurSwarmNodes(); // Filter out the nodes we have already got responses from completedNodes.forEach(nodeUrl => delete ourSwarmNodes[nodeUrl]); } catch (e) { @@ -277,7 +275,7 @@ class LokiMessageAPI { } const remainingRequests = - MINIMUM_SUCCESSFUL_REQUESTS - completedNodes.length; + MINIMUM_SUCCESSFUL_REQUESTS - successfulRequests; await Promise.all( Object.entries(ourSwarmNodes) diff --git a/js/modules/loki_snode_api.js b/js/modules/loki_snode_api.js index 2fe719633..76e41e893 100644 --- a/js/modules/loki_snode_api.js +++ b/js/modules/loki_snode_api.js @@ -1,5 +1,5 @@ /* eslint-disable class-methods-use-this */ -/* global log, window, Whisper */ +/* global log, window, ConversationController */ const fetch = require('node-fetch'); const is = require('@sindresorhus/is'); @@ -58,17 +58,10 @@ class LokiSnodeAPI { if (this.contactSwarmNodes[nodeUrl].failureCount < FAILURE_THRESHOLD) { return false; } - const conversation = window.ConversationController.get(pubKey); + const conversation = ConversationController.get(pubKey); const swarmNodes = conversation.get('swarmNodes'); if (swarmNodes.delete(nodeUrl)) { - conversation.set({ swarmNodes }); - await window.Signal.Data.updateConversation( - conversation.id, - conversation.attributes, - { - Conversation: Whisper.Conversation, - } - ); + await conversation.updateSwarmNodes(swarmNodes); delete this.contactSwarmNodes[nodeUrl]; } return true; @@ -84,6 +77,32 @@ class LokiSnodeAPI { } } + async getSwarmNodesForPubKey(pubKey) { + let conversation; + let swarmNodes; + try { + conversation = ConversationController.get(pubKey); + swarmNodes = conversation.get('swarmNodes'); + } catch (e) { + throw new window.textsecure.ReplayableError({ + message: 'Could not get conversation', + }); + } + return swarmNodes; + } + + async updateSwarmNodes(pubKey, newNodes) { + let conversation; + try { + conversation = ConversationController.get(pubKey); + } catch (e) { + throw new window.textsecure.ReplayableError({ + message: 'Could not get conversation', + }); + } + await conversation.updateSwarmNodes(newNodes); + } + async getOurSwarmNodes() { if ( !this.ourSwarmNodes || @@ -108,9 +127,12 @@ class LokiSnodeAPI { async refreshSwarmNodesForPubKey(pubKey) { const newNodes = await this.getFreshSwarmNodes(pubKey); - await window.Signal.Data.saveSwarmNodesForPubKey(pubKey, newNodes, { - Conversation: Whisper.Conversation, - }); + try { + const conversation = ConversationController.get(pubKey); + await conversation.updateSwarmNodes(newNodes); + } catch (e) { + throw e; + } } async getFreshSwarmNodes(pubKey) { diff --git a/preload.js b/preload.js index 65a788d89..2b3e673b7 100644 --- a/preload.js +++ b/preload.js @@ -288,7 +288,7 @@ window.WebAPI = initializeWebAPI({ const LokiSnodeAPI = require('./js/modules/loki_snode_api'); -window.LokiSnodeAPI = new LokiSnodeAPI({ +window.lokiSnodeAPI = new LokiSnodeAPI({ url: config.serverUrl, swarmServerPort: config.swarmServerPort, });