Browse Source

feat(TPC): append TPC ID to stream IDs

This commit will append "-" + tpc.id to every local 'MSID', 'cname',
'label' and 'mslabel', before feeding the local SDP to the Jingle layer.
It will make stream IDs unique across TraceablePeerConnection instances
and prevent from conflicts in some corner cases.

For example this will fix a problem where if the client drops
the conference without leaving the XMPP MUC gracefully and will join
the conference again without recreating the local tracks it would lead
to the MSID conflict, because the stream is still advertised by
"the ghost" participant.
dev1
paweldomas 7 years ago
parent
commit
dfccbac460
3 changed files with 93 additions and 8 deletions
  1. 82
    0
      modules/RTC/LocalSdpMunger.js
  2. 8
    8
      modules/RTC/RTC.js
  3. 3
    0
      modules/RTC/TraceablePeerConnection.js

+ 82
- 0
modules/RTC/LocalSdpMunger.js View File

@@ -161,6 +161,48 @@ export default class LocalSdpMunger {
161 161
         return modified;
162 162
     }
163 163
 
164
+    /**
165
+     * Modifies 'cname', 'msid', 'label' and 'mslabel' by appending
166
+     * the id of {@link LocalSdpMunger#tpc} at the end, preceding by a dash
167
+     * sign.
168
+     *
169
+     * @param {MLineWrap} mediaSection - The media part (audio or video) of the
170
+     * session description which will be modified in place.
171
+     * @returns {void}
172
+     * @private
173
+     */
174
+    _transformMediaIdentifiers(mediaSection) {
175
+        const pcId = this.tpc.id;
176
+
177
+        for (const ssrcLine of mediaSection.ssrcs) {
178
+            switch (ssrcLine.attribute) {
179
+            case 'cname':
180
+            case 'label':
181
+            case 'mslabel':
182
+                ssrcLine.value = ssrcLine.value && `${ssrcLine.value}-${pcId}`;
183
+                break;
184
+            case 'msid': {
185
+                if (ssrcLine.value) {
186
+                    const streamAndTrackIDs = ssrcLine.value.split(' ');
187
+
188
+                    if (streamAndTrackIDs.length === 2) {
189
+                        const streamId = streamAndTrackIDs[0];
190
+                        const trackId = streamAndTrackIDs[1];
191
+
192
+                        ssrcLine.value
193
+                            = `${streamId}-${pcId} ${trackId}-${pcId}`;
194
+                    } else {
195
+                        logger.warn(
196
+                            'Unable to munge local MSID'
197
+                                + `- weird format detected: ${ssrcLine.value}`);
198
+                    }
199
+                }
200
+                break;
201
+            }
202
+            }
203
+        }
204
+    }
205
+
164 206
     /**
165 207
      * Maybe modifies local description to fake local video tracks SDP when
166 208
      * those are muted.
@@ -185,4 +227,44 @@ export default class LocalSdpMunger {
185 227
 
186 228
         return desc;
187 229
     }
230
+
231
+    /**
232
+     * This transformation will make sure that stream identifiers are unique
233
+     * across all of the local PeerConnections even if the same stream is used
234
+     * by multiple instances at the same time.
235
+     * Each PeerConnection assigns different SSRCs to the same local
236
+     * MediaStream, but the MSID remains the same as it's used to identify
237
+     * the stream by the WebRTC backend. The transformation will append
238
+     * {@link TraceablePeerConnection#id} at the end of each stream's identifier
239
+     * ("cname", "msid", "label" and "mslabel").
240
+     *
241
+     * @param {RTCSessionDescription} sessionDesc - The local session
242
+     * description (this instance remains unchanged).
243
+     * @return {RTCSessionDescription} - Transformed local session description
244
+     * (a modified copy of the one given as the input).
245
+     */
246
+    transformStreamIdentifiers(sessionDesc) {
247
+        // FIXME similar check is probably duplicated in all other transformers
248
+        if (!sessionDesc || !sessionDesc.sdp || !sessionDesc.type) {
249
+            return sessionDesc;
250
+        }
251
+
252
+        const transformer = new SdpTransformWrap(sessionDesc.sdp);
253
+        const audioMLine = transformer.selectMedia('audio');
254
+
255
+        if (audioMLine) {
256
+            this._transformMediaIdentifiers(audioMLine);
257
+        }
258
+
259
+        const videoMLine = transformer.selectMedia('video');
260
+
261
+        if (videoMLine) {
262
+            this._transformMediaIdentifiers(videoMLine);
263
+        }
264
+
265
+        return new RTCSessionDescription({
266
+            type: sessionDesc.type,
267
+            sdp: transformer.toRawSDP()
268
+        });
269
+    }
188 270
 }

+ 8
- 8
modules/RTC/RTC.js View File

@@ -19,6 +19,12 @@ import VideoType from '../../service/RTC/VideoType';
19 19
 
20 20
 const logger = getLogger(__filename);
21 21
 
22
+/**
23
+ * The counter used to generated id numbers assigned to peer connections
24
+ * @type {number}
25
+ */
26
+let peerConnectionIdCounter = 1;
27
+
22 28
 let rtcTrackIdCounter = 0;
23 29
 
24 30
 /**
@@ -114,12 +120,6 @@ export default class RTC extends Listenable {
114 120
          */
115 121
         this.peerConnections = new Map();
116 122
 
117
-        /**
118
-         * The counter used to generated id numbers assigned to peer connections
119
-         * @type {number}
120
-         */
121
-        this.peerConnectionIdCounter = 1;
122
-
123 123
         this.localTracks = [];
124 124
 
125 125
         this.options = options;
@@ -444,13 +444,13 @@ export default class RTC extends Listenable {
444 444
         const newConnection
445 445
             = new TraceablePeerConnection(
446 446
                 this,
447
-                this.peerConnectionIdCounter,
447
+                peerConnectionIdCounter,
448 448
                 signaling,
449 449
                 iceConfig, pcConstraints,
450 450
                 isP2P, options);
451 451
 
452 452
         this.peerConnections.set(newConnection.id, newConnection);
453
-        this.peerConnectionIdCounter += 1;
453
+        peerConnectionIdCounter += 1;
454 454
 
455 455
         return newConnection;
456 456
     }

+ 3
- 0
modules/RTC/TraceablePeerConnection.js View File

@@ -1210,6 +1210,9 @@ const getters = {
1210 1210
         // happening (check setLocalDescription impl).
1211 1211
         desc = enforceSendRecv(desc);
1212 1212
 
1213
+        // See the method's doc for more info about this transformation.
1214
+        desc = this.localSdpMunger.transformStreamIdentifiers(desc);
1215
+
1213 1216
         return desc;
1214 1217
     },
1215 1218
     remoteDescription() {

Loading…
Cancel
Save