From 330b2b1b16ed6261629524a8588382b3626ad847 Mon Sep 17 00:00:00 2001 From: Ryan Tharp Date: Tue, 24 Mar 2020 21:59:36 -0700 Subject: [PATCH] sort random pool into versions, getRandomProxySnodeAddress to use 2.0.2 or newer versions --- js/modules/loki_snode_api.js | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/js/modules/loki_snode_api.js b/js/modules/loki_snode_api.js index 8709f2a4b..5f47bab8e 100644 --- a/js/modules/loki_snode_api.js +++ b/js/modules/loki_snode_api.js @@ -3,7 +3,13 @@ const is = require('@sindresorhus/is'); const { lokiRpc } = require('./loki_rpc'); +const https = require('https'); const nodeFetch = require('node-fetch'); +const semver = require('semver'); + +const snodeHttpsAgent = new https.Agent({ + rejectUnauthorized: false, +}); const RANDOM_SNODES_TO_USE_FOR_PUBKEY_SWARM = 3; const SEED_NODE_RETRIES = 3; @@ -18,6 +24,7 @@ class LokiSnodeAPI { this.randomSnodePool = []; this.swarmsPendingReplenish = {}; this.refreshRandomPoolPromise = false; + this.versionPools = {}; this.onionPaths = []; this.guardNodes = []; @@ -254,6 +261,51 @@ class LokiSnodeAPI { ]; } + // use nodes that support more than 1mb + async getRandomProxySnodeAddress() { + /* resolve random snode */ + if (this.randomSnodePool.length === 0) { + // allow exceptions to pass through upwards + await this.refreshRandomPool(); + } + if (this.randomSnodePool.length === 0) { + throw new window.textsecure.SeedNodeError('Invalid seed node response'); + } + const goodVersions = Object.keys(this.versionPools).filter(version => { + return semver.gt(version, '2.0.1') + }) + if (!goodVersions.length) { + return false; + } + console.log('goodVersions', goodVersions); + const goodVersion = goodVersions[Math.floor(Math.random() * goodVersions.length)]; + console.log('goodVersion', goodVersion); + const pool = this.versionPools[goodVersion]; + console.log('poolsize', pool.length); + return pool[ + Math.floor(Math.random() * pool.length) + ]; + } + + async getVersion(node, count, total) { + try { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + const result = await nodeFetch(`https://${node.ip}:${node.port}/get_stats/v1`, { agent: snodeHttpsAgent }); + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1'; + const data = await result.json(); + console.log(`${count}/${total} ${node.ip}:${node.port}`, 'is on', data.version); + if (data.version) { + if (this.versionPools[data.version] === undefined) { + this.versionPools[data.version] = [ node ]; + } else { + this.versionPools[data.version].push(node); + } + } + } catch(e) { + console.log('loki_snode:::getVersion - Error', e.code, e.message); + } + } + async refreshRandomPool(seedNodes = [...window.seedNodeList]) { // if currently not in progress if (this.refreshRandomPoolPromise === false) { @@ -295,6 +347,9 @@ class LokiSnodeAPI { snodes = response.result.service_node_states.filter( snode => snode.public_ip !== '0.0.0.0' ); + // commit changes to be live + // we'll update the version (in case they upgrade) every cycle + this.versionPools = {}; this.randomSnodePool = snodes.map(snode => ({ ip: snode.public_ip, port: snode.storage_port, @@ -312,7 +367,14 @@ class LokiSnodeAPI { clearTimeout(timeoutTimer); timeoutTimer = null; } + // start polling versions resolve(); + let c = 0; + const t = this.randomSnodePool.length; + for(let node of this.randomSnodePool) { + c += 1; + await this.getVersion(node, c, t); + } } catch (e) { log.warn( 'loki_snodes:::refreshRandomPoolPromise - error',