diff --git a/js/modules/loki_snode_api.js b/js/modules/loki_snode_api.js index fad22234d..9f805bb8b 100644 --- a/js/modules/loki_snode_api.js +++ b/js/modules/loki_snode_api.js @@ -50,8 +50,15 @@ class LokiSnodeAPI { } async getMyLokiIp() { - const address = await resolveCname(this.localUrl); - return resolve4(address); + try { + const address = await resolveCname(this.localUrl); + return resolve4(address); + } catch (e) { + throw new window.textsecure.LokiIpError( + 'Failed to resolve localhost.loki', + e + ); + } } async getMyLokiAddress() { diff --git a/libtextsecure/errors.js b/libtextsecure/errors.js index 7f972492e..d6788957c 100644 --- a/libtextsecure/errors.js +++ b/libtextsecure/errors.js @@ -167,6 +167,22 @@ } inherit(ReplayableError, DNSResolutionError); + function LokiIpError(message, resolutionError) { + this.name = 'LokiIpError'; + this.message = message; + this.error = resolutionError; + + Error.call(this, message); + + // 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); + } + + appendStack(this, resolutionError); + } + window.textsecure.UnregisteredUserError = UnregisteredUserError; window.textsecure.SendMessageNetworkError = SendMessageNetworkError; window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError; @@ -178,4 +194,5 @@ window.textsecure.PoWError = PoWError; window.textsecure.EmptySwarmError = EmptySwarmError; window.textsecure.DNSResolutionError = DNSResolutionError; + window.textsecure.LokiIpError = LokiIpError; })(); diff --git a/libtextsecure/message_receiver.js b/libtextsecure/message_receiver.js index 2913c79a1..83d75c497 100644 --- a/libtextsecure/message_receiver.js +++ b/libtextsecure/message_receiver.js @@ -83,13 +83,8 @@ MessageReceiver.prototype.extend({ this.onEmpty(); } }); - window.lokiSnodeAPI.getMyLokiIp().then(myLokiIp => { - localLokiServer.start(localServerPort, myLokiIp).then(port => { - window.log.info(`Local Server started at ${myLokiIp}:${port}`); - libloki.api.broadcastOnlineStatus(); - localLokiServer.on('message', this.handleP2pMessage.bind(this)); - }); - }); + localLokiServer.on('message', this.handleP2pMessage.bind(this)); + this.startLocalServer(); // TODO: Rework this socket stuff to work with online messaging const useWebSocket = false; @@ -120,6 +115,28 @@ MessageReceiver.prototype.extend({ // all cached envelopes are processed. this.incoming = [this.pending]; }, + async startLocalServer() { + try { + const myLokiIp = await window.lokiSnodeAPI.getMyLokiIp(); + const myServerPort = await localLokiServer.start( + localServerPort, + myLokiIp + ); + window.log.info(`Local Server started at ${myLokiIp}:${myServerPort}`); + libloki.api.broadcastOnlineStatus(); + } catch (e) { + if (e instanceof textsecure.LokiIpError) { + window.log.warn( + 'Failed to get my loki address to bind server to, will retry in 30 seconds' + ); + } else { + window.log.warn( + 'Failed to start local loki server, will retry in 30 seconds' + ); + } + setTimeout(this.startLocalServer.bind(this), 30 * 1000); + } + }, handleP2pMessage(message) { this.httpPollingResource.handleMessage(message, true); },