@ -1,5 +1,5 @@
/* eslint-disable class-methods-use-this */
/* global window, textsecure, ConversationController, log, process, Buffer, StringView, dcodeIO */
/* global window, textsecure, log, process, Buffer, StringView, dcodeIO */
// not sure I like this name but it's been than util
const primitives = require ( './loki_primitives' ) ;
@ -7,12 +7,8 @@ const primitives = require('./loki_primitives');
const is = require ( '@sindresorhus/is' ) ;
const nodeFetch = require ( 'node-fetch' ) ;
const RANDOM _SNODES _TO _USE _FOR _PUBKEY _SWARM = 3 ;
const MIN _GUARD _COUNT = 2 ;
const compareSnodes = ( current , search ) =>
current . pubkey _ed25519 === search . pubkey _ed25519 ;
class LokiSnodeAPI {
constructor ( { serverUrl , localUrl } ) {
if ( ! is . string ( serverUrl ) ) {
@ -316,103 +312,6 @@ class LokiSnodeAPI {
} ) ;
}
async updateLastHash ( convoId , snodeAddress , hash , expiresAt ) {
// FIXME: handle rejections
await window . Signal . Data . updateLastHash ( {
convoId ,
snode : snodeAddress ,
hash ,
expiresAt ,
} ) ;
}
// called by loki_message:::sendMessage & loki_message:::startLongPolling
async getSwarmNodesForPubKey ( pubKey , options = { } ) {
const { fetchHashes } = options ;
try {
const conversation = ConversationController . get ( pubKey ) ;
if ( ! conversation ) {
throw new Error ( ` Could not find conversation ' ${ pubKey } ' ` ) ;
}
const swarmNodes = [ ... conversation . get ( 'swarmNodes' ) ] ;
// always? include lashHash
if ( fetchHashes ) {
await Promise . all (
Object . keys ( swarmNodes ) . map ( async j => {
const node = swarmNodes [ j ] ;
// FIXME make a batch function call
const lastHash = await window . Signal . Data . getLastHashBySnode (
pubKey ,
node . address
) ;
log . debug (
` LokiSnodeAPI::getSwarmNodesForPubKey - ${ j } ${ node . ip } : ${ node . port } `
) ;
swarmNodes [ j ] = {
... node ,
lastHash ,
} ;
} )
) ;
}
return swarmNodes ;
} catch ( e ) {
log . error ( 'getSwarmNodesForPubKey expection: ' , e ) ;
throw new window . textsecure . ReplayableError ( {
message : 'Could not get conversation' ,
} ) ;
}
}
async updateSwarmNodes ( pubKey , newNodes ) {
try {
const filteredNodes = newNodes . filter ( snode => snode . ip !== '0.0.0.0' ) ;
const conversation = ConversationController . get ( pubKey ) ;
await conversation . updateSwarmNodes ( filteredNodes ) ;
return filteredNodes ;
} catch ( e ) {
log . error (
` LokiSnodeAPI::updateSwarmNodes - error ${ e . code } ${ e . message } `
) ;
throw new window . textsecure . ReplayableError ( {
message : 'Could not get conversation' ,
} ) ;
}
}
// FIXME: in it's own PR, reorder functions: put _getFreshSwarmNodes and it's callee
// only loki_message::startLongPolling calls this...
async refreshSwarmNodesForPubKey ( pubKey ) {
// FIXME: handle rejections
const newNodes = await this . _getFreshSwarmNodes ( pubKey ) ;
log . debug (
'LokiSnodeAPI::refreshSwarmNodesForPubKey - newNodes' ,
newNodes . length
) ;
const filteredNodes = this . updateSwarmNodes ( pubKey , newNodes ) ;
return filteredNodes ;
}
async _getFreshSwarmNodes ( pubKey ) {
return primitives . allowOnlyOneAtATime ( ` swarmRefresh ${ pubKey } ` , async ( ) => {
let newSwarmNodes = [ ] ;
try {
newSwarmNodes = await this . _getSwarmNodes ( pubKey ) ;
} catch ( e ) {
log . error (
'LokiSnodeAPI::_getFreshSwarmNodes - error' ,
e . code ,
e . message
) ;
// TODO: Handle these errors sensibly
newSwarmNodes = [ ] ;
}
return newSwarmNodes ;
} ) ;
}
async getLnsMapping ( lnsName , timeout ) {
// Returns { pubkey, error }
// pubkey is
@ -530,33 +429,6 @@ class LokiSnodeAPI {
return { pubkey , error } ;
}
async _getSwarmNodes ( pubKey ) {
const snodes = [ ] ;
// creates a range: [0, 1, 2]
const questions = [ ... Array ( RANDOM _SNODES _TO _USE _FOR _PUBKEY _SWARM ) . keys ( ) ] ;
// FIXME: handle rejections
await Promise . all (
questions . map ( async qNum => {
// allow exceptions to pass through upwards
const resList = await window . NewSnodeAPI . getSnodesForPubkey ( pubKey ) ;
log . info (
` LokiSnodeAPI::_getSwarmNodes - question ${ qNum } got ` ,
resList . length ,
'snodes'
) ;
resList . map ( item => {
const hasItem = snodes . some ( n => compareSnodes ( n , item ) ) ;
if ( ! hasItem ) {
snodes . push ( item ) ;
}
return true ;
} ) ;
} )
) ;
// should we only activate entries that are in all results? yes
return snodes ;
}
}
module . exports = LokiSnodeAPI ;