Procházet zdrojové kódy

Background reconnect for iOS

Reconnect to the SaltyRTC server and wait for the peer handshake without
a push notification.
Danilo Bargen před 7 roky
rodič
revize
82d59ceb33
2 změnil soubory, kde provedl 70 přidání a 13 odebrání
  1. 62 7
      src/controllers/status.ts
  2. 8 6
      src/services/webclient.ts

+ 62 - 7
src/controllers/status.ts

@@ -97,21 +97,28 @@ export class StatusController {
             return;
         }
         this.state = newValue;
+
+        const isWebrtc = this.webClientService.chosenTask === threema.ChosenTask.WebRTC;
+        const isRelayedData = this.webClientService.chosenTask === threema.ChosenTask.RelayedData;
+
         switch (newValue) {
             case 'ok':
                 this.collapseStatusBar();
                 break;
             case 'warning':
-                if (oldValue === 'ok' && this.webClientService.chosenTask === threema.ChosenTask.WebRTC) {
+                if (oldValue === 'ok' && isWebrtc) {
                     this.scheduleStatusBar();
                 }
+                if (this.stateService.wasConnected && isRelayedData) {
+                    this.reconnectIos();
+                }
                 break;
             case 'error':
-                if (this.stateService.wasConnected) {
-                    if (oldValue === 'ok' && this.webClientService.chosenTask === threema.ChosenTask.WebRTC) {
+                if (this.stateService.wasConnected && isWebrtc) {
+                    if (oldValue === 'ok') {
                         this.scheduleStatusBar();
                     }
-                    this.reconnect();
+                    this.reconnectAndroid();
                 }
                 break;
             default:
@@ -139,10 +146,10 @@ export class StatusController {
     }
 
     /**
-     * Attempt to reconnect after a connection loss.
+     * Attempt to reconnect an Android device after a connection loss.
      */
-    private reconnect(): void {
-        this.$log.warn(this.logTag, 'Connection lost. Attempting to reconnect...');
+    private reconnectAndroid(): void {
+        this.$log.warn(this.logTag, 'Connection lost (Android). Attempting to reconnect...');
 
         // Get original keys
         const originalKeyStore = this.webClientService.salty.keyStore;
@@ -232,6 +239,54 @@ export class StatusController {
         // TODO: Handle server closing state
     }
 
+    /**
+     * Attempt to reconnect an iOS device after a connection loss.
+     */
+    private reconnectIos(): void {
+        this.$log.warn(this.logTag, 'Connection lost (iOS). Attempting to reconnect...');
+
+        // Get original keys
+        const originalKeyStore = this.webClientService.salty.keyStore;
+        const originalPeerPermanentKeyBytes = this.webClientService.salty.peerPermanentKeyBytes;
+
+        // Handler for failed reconnection attempts
+        const reconnectionFailed = () => {
+            // Reset state
+            this.stateService.reset();
+
+            // Redirect to welcome page
+            this.$state.go('welcome', {
+                initParams: {
+                    keyStore: originalKeyStore,
+                    peerTrustedKey: originalPeerPermanentKeyBytes,
+                },
+            });
+        };
+
+        const deleteStoredData = false;
+        const resetPush = false;
+        const skipPush = true;
+        const redirect = false;
+        const startTimeout = 500; // Delay connecting a bit to wait for old websocket to close
+        this.$log.debug(this.logTag, 'Stopping old connection');
+        this.webClientService.stop(true, deleteStoredData, resetPush, redirect);
+        this.$timeout(() => {
+            this.$log.debug(this.logTag, 'Starting new connection');
+            this.webClientService.init(originalKeyStore, originalPeerPermanentKeyBytes, false);
+            this.webClientService.start(skipPush).then(
+                () => { /* ok */ },
+                (error) => {
+                    this.$log.error(this.logTag, 'Error state:', error);
+                    reconnectionFailed();
+                },
+                // Progress
+                (progress: threema.ConnectionBuildupStateChange) => {
+                    this.$log.debug(this.logTag, 'Connection buildup advanced:', progress);
+                },
+            );
+        }, startTimeout);
+    }
+
     public wide(): boolean {
         return this.controllerService.getControllerName() !== undefined
             && this.controllerService.getControllerName() === 'messenger';

+ 8 - 6
src/services/webclient.ts

@@ -592,8 +592,8 @@ export class WebClientService {
      * Start the webclient service.
      * Return a promise that resolves once connected.
      */
-    public start(): ng.IPromise<any> {
-        this.$log.debug('Starting WebClientService...');
+    public start(skipPush: boolean = false): ng.IPromise<any> {
+        this.$log.debug(this.logTag, 'Starting WebClientService...');
 
         // Promise to track startup state
         this.startupPromise = this.$q.defer();
@@ -603,17 +603,19 @@ export class WebClientService {
         this.salty.connect();
 
         // If push service is available, notify app
-        if (this.pushService.isAvailable()) {
+        if (skipPush === true) {
+            this.$log.debug(this.logTag, 'Skipping push notification');
+        } else if (this.pushService.isAvailable()) {
             this.pushService.sendPush(this.salty.permanentKeyBytes)
-                .catch(() => this.$log.warn('Could not notify app!'))
+                .catch(() => this.$log.warn(this.logTag, 'Could not notify app!'))
                 .then(() => {
-                    this.$log.debug('Requested app wakeup via', this.pushTokenType);
+                    this.$log.debug(this.logTag, 'Requested app wakeup via', this.pushTokenType);
                     this.$rootScope.$apply(() => {
                         this.stateService.updateConnectionBuildupState('push');
                     });
                 });
         } else if (this.trustedKeyStore.hasTrustedKey()) {
-            this.$log.debug('Push service not available');
+            this.$log.debug(this.logTag, 'Push service not available');
             this.stateService.updateConnectionBuildupState('manual_start');
         }