Selaa lähdekoodia

Prepare state service for iOS reconnects

Danilo Bargen 7 vuotta sitten
vanhempi
commit
8453a608cf
4 muutettua tiedostoa jossa 79 lisäystä ja 35 poistoa
  1. 10 8
      src/services/peerconnection.ts
  2. 18 18
      src/services/state.ts
  3. 43 7
      src/services/webclient.ts
  4. 8 2
      src/threema.d.ts

+ 10 - 8
src/services/peerconnection.ts

@@ -17,6 +17,8 @@
 
 import * as SDPUtils from 'sdp';
 
+import TaskConnectionState = threema.TaskConnectionState;
+
 /**
  * Wrapper around the WebRTC PeerConnection.
  *
@@ -37,8 +39,8 @@ export class PeerConnectionHelper {
     private webrtcTask: saltyrtc.tasks.webrtc.WebRTCTask;
 
     // Calculated connection state
-    public connectionState: threema.RTCConnectionState = 'new';
-    public onConnectionStateChange: (state: threema.RTCConnectionState) => void = null;
+    public connectionState: TaskConnectionState = TaskConnectionState.New;
+    public onConnectionStateChange: (state: TaskConnectionState) => void = null;
 
     // Internal callback when connection closes
     private onConnectionClosed: () => void = null;
@@ -121,19 +123,19 @@ export class PeerConnectionHelper {
             this.$rootScope.$apply(() => {
                 switch (this.pc.iceConnectionState) {
                     case 'new':
-                        this.setConnectionState('new');
+                        this.setConnectionState(TaskConnectionState.New);
                         break;
                     case 'checking':
                     case 'disconnected':
-                        this.setConnectionState('connecting');
+                        this.setConnectionState(TaskConnectionState.Connecting);
                         break;
                     case 'connected':
                     case 'completed':
-                        this.setConnectionState('connected');
+                        this.setConnectionState(TaskConnectionState.Connected);
                         break;
                     case 'failed':
                     case 'closed':
-                        this.setConnectionState('disconnected');
+                        this.setConnectionState(TaskConnectionState.Disconnected);
                         break;
                     default:
                         this.$log.warn(this.logTag, 'Ignored ICE connection state change to',
@@ -193,13 +195,13 @@ export class PeerConnectionHelper {
     /**
      * Set the connection state and update listeners.
      */
-    private setConnectionState(state: threema.RTCConnectionState) {
+    private setConnectionState(state: TaskConnectionState) {
         if (state !== this.connectionState) {
             this.connectionState = state;
             if (this.onConnectionStateChange !== null) {
                 this.$timeout(() => this.onConnectionStateChange(state), 0);
             }
-            if (this.onConnectionClosed !== null && state === 'disconnected') {
+            if (this.onConnectionClosed !== null && state === TaskConnectionState.Disconnected) {
                 this.$timeout(() => this.onConnectionClosed(), 0);
             }
         }

+ 18 - 18
src/services/state.ts

@@ -17,6 +17,7 @@
 
 import {AsyncEvent} from 'ts-events';
 
+import TaskConnectionState = threema.TaskConnectionState;
 import GlobalConnectionState = threema.GlobalConnectionState;
 import ChosenTask = threema.ChosenTask;
 
@@ -36,9 +37,9 @@ export class StateService {
     // Events
     public evtConnectionBuildupStateChange = new AsyncEvent<threema.ConnectionBuildupStateChange>();
 
-    // WebRTC states
+    // Connection states
     public signalingConnectionState: saltyrtc.SignalingState;
-    public rtcConnectionState: threema.RTCConnectionState;
+    public taskConnectionState: TaskConnectionState;
 
     // Connection buildup state
     public connectionBuildupState: threema.ConnectionBuildupState = 'connecting';
@@ -75,12 +76,12 @@ export class StateService {
                     this.state = GlobalConnectionState.Warning;
                     break;
                 case 'task':
+                    this.stage = Stage.Task;
                     if (chosenTask === ChosenTask.RelayedData) {
-                        this.state = GlobalConnectionState.Ok;
+                        this.updateTaskConnectionState(TaskConnectionState.Connected);
                     } else {
                         this.state = GlobalConnectionState.Warning;
                     }
-                    this.stage = Stage.Task;
                     break;
                 case 'closing':
                 case 'closed':
@@ -95,32 +96,31 @@ export class StateService {
     }
 
     /**
-     * RTC connection state.
-     *
-     * This is only called if the WebRTC task is active.
+     * Task connection state.
      */
-    public updateRtcConnectionState(state: threema.RTCConnectionState): void {
-        const prevState = this.rtcConnectionState;
-        this.rtcConnectionState = state;
+    public updateTaskConnectionState(state: TaskConnectionState): void {
+        const prevState = this.taskConnectionState;
+        this.taskConnectionState = state;
         if (this.stage === Stage.Task) {
-            this.$log.debug(this.logTag, 'RTC connection state:', prevState, '=>', state);
+            this.$log.debug(this.logTag, 'Task connection state:', prevState, '=>', state);
             switch (state) {
-                case 'new':
-                case 'connecting':
+                case TaskConnectionState.New:
+                case TaskConnectionState.Connecting:
+                case TaskConnectionState.Reconnecting:
                     this.state = GlobalConnectionState.Warning;
                     break;
-                case 'connected':
+                case TaskConnectionState.Connected:
                     this.state = GlobalConnectionState.Ok;
                     this.wasConnected = true;
                     break;
-                case 'disconnected':
+                case TaskConnectionState.Disconnected:
                     this.state = GlobalConnectionState.Error;
                     break;
                 default:
-                    this.$log.warn(this.logTag, 'Ignored RTC connection state change to', state);
+                    this.$log.warn(this.logTag, 'Ignored task connection state change to "' + state + '"');
             }
         } else {
-            this.$log.debug(this.logTag, 'Ignored RTC connection state change to "' + state + '"');
+            this.$log.debug(this.logTag, 'Ignored task connection state change to "' + state + '"');
         }
     }
 
@@ -216,7 +216,7 @@ export class StateService {
 
         // Reset state
         this.signalingConnectionState = 'new';
-        this.rtcConnectionState = 'new';
+        this.taskConnectionState = TaskConnectionState.New;
         this.stage = Stage.Signaling;
         this.state = GlobalConnectionState.Error;
         this.wasConnected = false;

+ 43 - 7
src/services/webclient.ts

@@ -423,8 +423,8 @@ export class WebClientService {
                     !this.config.ICE_DEBUGGING);
 
                 // On state changes in the PeerConnectionHelper class, let state service know about it
-                this.pcHelper.onConnectionStateChange = (state: threema.RTCConnectionState) => {
-                    this.stateService.updateRtcConnectionState(state);
+                this.pcHelper.onConnectionStateChange = (state: threema.TaskConnectionState) => {
+                    this.stateService.updateTaskConnectionState(state);
                 };
 
                 // Initiate handover
@@ -440,14 +440,15 @@ export class WebClientService {
         // Handle a disconnect request
         this.salty.on('application', (applicationData: any) => {
             if (applicationData.data.type === 'disconnect') {
-                this.$log.debug(this.logTag, 'Disconnecting requested');
-                const deleteStoredData = applicationData.data.forget === true;
-                const resetPush = true;
-                const redirect = true;
-                this.stop(false, deleteStoredData, resetPush, redirect);
+                this.onApplicationDisconnect(applicationData);
             }
         });
 
+        // Handle disconnecting of a peer
+        this.salty.on('peer-disconnected', (ev: saltyrtc.SaltyRTCEvent) => {
+            this.onPeerDisconnected(ev.data);
+        });
+
         // Wait for handover to be finished
         this.salty.on('handover', () => {
             this.$log.debug(this.logTag, 'Handover done');
@@ -550,6 +551,41 @@ export class WebClientService {
         }
     }
 
+    /**
+     * An 'application' message with type 'disconnect' arrived.
+     */
+    private onApplicationDisconnect(applicationData: any) {
+        this.$log.debug(this.logTag, 'Disconnecting requested');
+        const deleteStoredData = applicationData.data.forget === true;
+        const resetPush = true;
+        const redirect = true;
+        this.stop(false, deleteStoredData, resetPush, redirect);
+    }
+
+    /**
+     * A previously authenticated peer disconnected from the server.
+     */
+    private onPeerDisconnected(peerId: number) {
+        switch (this.chosenTask) {
+            case threema.ChosenTask.RelayedData:
+                if (this.stateService.taskConnectionState === threema.TaskConnectionState.Connected) {
+                    this.stateService.updateTaskConnectionState(threema.TaskConnectionState.Reconnecting);
+                } else {
+                    this.$log.debug(
+                        this.logTag,
+                        'Ignoring peer-disconnected event (state is '
+                        + this.stateService.taskConnectionState + ')',
+                    );
+                }
+                break;
+            default:
+                this.$log.debug(
+                    this.logTag,
+                    'Ignoring peer-disconnected event (chosen task is ' + this.chosenTask + ')',
+                );
+        }
+    }
+
     /**
      * Start the webclient service.
      * Return a promise that resolves once connected.

+ 8 - 2
src/threema.d.ts

@@ -353,9 +353,15 @@ declare namespace threema {
     }
 
     /**
-     * Connection state of the WebRTC peer connection.
+     * Connection state of the task peer connection.
      */
-    type RTCConnectionState = 'new' | 'connecting' | 'connected' | 'disconnected';
+    const enum TaskConnectionState {
+        New = 'new',
+        Connecting = 'connecting',
+        Connected = 'connected',
+        Reconnecting = 'reconnecting',
+        Disconnected = 'disconnected',
+    }
 
     /**
      * Connection state of the WebRTC peer connection.