浏览代码

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 年前
父节点
当前提交
dfccbac460
共有 3 个文件被更改,包括 93 次插入8 次删除
  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 查看文件

161
         return modified;
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
      * Maybe modifies local description to fake local video tracks SDP when
207
      * Maybe modifies local description to fake local video tracks SDP when
166
      * those are muted.
208
      * those are muted.
185
 
227
 
186
         return desc;
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 查看文件

19
 
19
 
20
 const logger = getLogger(__filename);
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
 let rtcTrackIdCounter = 0;
28
 let rtcTrackIdCounter = 0;
23
 
29
 
24
 /**
30
 /**
114
          */
120
          */
115
         this.peerConnections = new Map();
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
         this.localTracks = [];
123
         this.localTracks = [];
124
 
124
 
125
         this.options = options;
125
         this.options = options;
444
         const newConnection
444
         const newConnection
445
             = new TraceablePeerConnection(
445
             = new TraceablePeerConnection(
446
                 this,
446
                 this,
447
-                this.peerConnectionIdCounter,
447
+                peerConnectionIdCounter,
448
                 signaling,
448
                 signaling,
449
                 iceConfig, pcConstraints,
449
                 iceConfig, pcConstraints,
450
                 isP2P, options);
450
                 isP2P, options);
451
 
451
 
452
         this.peerConnections.set(newConnection.id, newConnection);
452
         this.peerConnections.set(newConnection.id, newConnection);
453
-        this.peerConnectionIdCounter += 1;
453
+        peerConnectionIdCounter += 1;
454
 
454
 
455
         return newConnection;
455
         return newConnection;
456
     }
456
     }

+ 3
- 0
modules/RTC/TraceablePeerConnection.js 查看文件

1210
         // happening (check setLocalDescription impl).
1210
         // happening (check setLocalDescription impl).
1211
         desc = enforceSendRecv(desc);
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
         return desc;
1216
         return desc;
1214
     },
1217
     },
1215
     remoteDescription() {
1218
     remoteDescription() {

正在加载...
取消
保存