diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index 4bede184c..724d46bac 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -96,7 +96,11 @@ class LokiMessageAPI { successfulRequests += 1; } catch (e) { log.warn('Loki send message:', e); - if (e instanceof textsecure.NotFoundError) { + if (e instanceof textsecure.WrongSwarmError) { + const { newSwarm } = e; + await lokiSnodeAPI.updateSwarmNodes(pubKey, newSwarm); + completedNodes.push(nodeUrl); + } else if (e instanceof textsecure.NotFoundError) { canResolve = false; } else if (e instanceof textsecure.HTTPError) { // We mark the node as complete as we could still reach it @@ -186,7 +190,11 @@ class LokiMessageAPI { successfulRequests += 1; } catch (e) { log.warn('Loki retrieve messages:', e); - if (e instanceof textsecure.NotFoundError) { + if (e instanceof textsecure.WrongSwarmError) { + const { newSwarm } = e; + lokiSnodeAPI.updateOurSwarmNodes(newSwarm); + completedNodes.push(nodeUrl); + } else if (e instanceof textsecure.NotFoundError) { canResolve = false; } else if (e instanceof textsecure.HTTPError) { // We mark the node as complete as we could still reach it diff --git a/js/modules/loki_rpc.js b/js/modules/loki_rpc.js index 23f9a01d5..378f948a7 100644 --- a/js/modules/loki_rpc.js +++ b/js/modules/loki_rpc.js @@ -38,6 +38,26 @@ const fetch = async (url, options = {}) => { method, }); + if (response.status === 421) { + let newSwarm = await response.text(); + if (doEncryptChannel) { + try { + newSwarm = await libloki.crypto.snodeCipher.decrypt( + address, + newSwarm + ); + } catch (e) { + log.warn(`Could not decrypt response from ${address}`, e); + } + try { + newSwarm = newSwarm === '' ? {} : JSON.parse(newSwarm); + } catch (e) { + log.warn(`Could not parse string to json ${newSwarm}`, e); + } + } + throw new textsecure.WrongSwarmError(newSwarm); + } + if (!response.ok) { throw new textsecure.HTTPError('Loki_rpc error', response); } diff --git a/js/modules/loki_snode_api.js b/js/modules/loki_snode_api.js index c89caa2a6..8edd758ba 100644 --- a/js/modules/loki_snode_api.js +++ b/js/modules/loki_snode_api.js @@ -139,6 +139,15 @@ class LokiSnodeAPI { } } + updateOurSwarmNodes(newNodes) { + this.ourSwarmNodes = {}; + newNodes.forEach(url => { + this.ourSwarmNodes[url] = { + failureCount: 0, + }; + }); + } + async getOurSwarmNodes() { if ( !this.ourSwarmNodes || diff --git a/libtextsecure/errors.js b/libtextsecure/errors.js index f3be62b07..78f9fcfb1 100644 --- a/libtextsecure/errors.js +++ b/libtextsecure/errors.js @@ -209,6 +209,19 @@ } } + function WrongSwarmError(newSwarm) { + this.name = 'WrongSwarmError'; + this.newSwarm = newSwarm; + + Error.call(this, this.name); + + // Maintains proper stack trace, where our error was thrown (only available on V8) + // via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } + } + window.textsecure.UnregisteredUserError = UnregisteredUserError; window.textsecure.SendMessageNetworkError = SendMessageNetworkError; window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError; @@ -223,4 +236,5 @@ window.textsecure.LokiIpError = LokiIpError; window.textsecure.HTTPError = HTTPError; window.textsecure.NotFoundError = NotFoundError; + window.textsecure.WrongSwarmError = WrongSwarmError; })();