瀏覽代碼

[eslint] newline-after-var, newline-before-return, newline-per-chained-call

tags/v0.0.2
Lyubo Marinov 8 年之前
父節點
當前提交
4581605a28
共有 61 個文件被更改,包括 1009 次插入74 次删除
  1. 3
    0
      .eslintrc.js
  2. 54
    1
      JitsiConference.js
  3. 22
    0
      JitsiConferenceEventManager.js
  4. 1
    0
      JitsiConnection.js
  5. 1
    0
      JitsiMediaDevices.js
  6. 15
    1
      JitsiMeetJS.js
  7. 31
    17
      doc/example/example.js
  8. 1
    0
      modules/DTMF/JitsiDTMFManager.js
  9. 6
    0
      modules/RTC/DataChannels.js
  10. 10
    0
      modules/RTC/JitsiLocalTrack.js
  11. 4
    0
      modules/RTC/JitsiRemoteTrack.js
  12. 7
    0
      modules/RTC/JitsiTrack.js
  13. 32
    1
      modules/RTC/RTC.js
  14. 32
    0
      modules/RTC/RTCBrowserType.js
  15. 3
    0
      modules/RTC/RTCUIHelper.js
  16. 37
    2
      modules/RTC/RTCUtils.js
  17. 25
    2
      modules/RTC/ScreenObtainer.js
  18. 47
    0
      modules/RTC/TraceablePeerConnection.js
  19. 7
    0
      modules/connectivity/ConnectionQuality.js
  20. 4
    0
      modules/connectivity/ParticipantConnectionStatus.js
  21. 9
    0
      modules/settings/Settings.js
  22. 3
    0
      modules/statistics/AnalyticsAdapter.js
  23. 6
    0
      modules/statistics/CallStats.js
  24. 5
    0
      modules/statistics/LocalStatsCollector.js
  25. 31
    0
      modules/statistics/RTPStatsCollector.js
  26. 5
    0
      modules/statistics/statistics.js
  27. 10
    0
      modules/transcription/audioRecorder.js
  28. 10
    0
      modules/transcription/transcriber.js
  29. 1
    0
      modules/transcription/transcriptionServices/AbstractTranscriptionService.js
  30. 10
    0
      modules/transcription/transcriptionServices/SphinxTranscriptionService.js
  31. 2
    0
      modules/util/AuthUtil.js
  32. 1
    0
      modules/util/EventEmitterForwarder.js
  33. 2
    0
      modules/util/GlobalOnErrorHandler.js
  34. 2
    0
      modules/util/RandomUtil.js
  35. 2
    0
      modules/util/ScriptUtil.js
  36. 6
    0
      modules/version/ComponentsVersions.js
  37. 15
    2
      modules/xmpp/Caps.js
  38. 58
    1
      modules/xmpp/ChatRoom.js
  39. 1
    0
      modules/xmpp/JingleSession.js
  40. 120
    11
      modules/xmpp/JingleSessionPC.js
  41. 17
    0
      modules/xmpp/RtxModifier.js
  42. 38
    0
      modules/xmpp/RtxModifier.spec.js
  43. 93
    17
      modules/xmpp/SDP.js
  44. 12
    0
      modules/xmpp/SDPDiffer.js
  45. 49
    2
      modules/xmpp/SDPUtil.js
  46. 2
    0
      modules/xmpp/SDPUtil.spec.js
  47. 7
    0
      modules/xmpp/SdpConsistency.js
  48. 14
    0
      modules/xmpp/SdpTransformUtil.js
  49. 37
    3
      modules/xmpp/moderator.js
  50. 26
    10
      modules/xmpp/recording.js
  51. 13
    0
      modules/xmpp/strophe.emuc.js
  52. 28
    2
      modules/xmpp/strophe.jingle.js
  53. 6
    0
      modules/xmpp/strophe.ping.js
  54. 8
    2
      modules/xmpp/strophe.rayo.js
  55. 2
    0
      modules/xmpp/strophe.util.js
  56. 11
    0
      modules/xmpp/xmpp.js
  57. 1
    0
      service/RTC/Resolutions.js
  58. 1
    0
      service/RTC/VideoType.js
  59. 1
    0
      service/authentication/AuthenticationEvents.js
  60. 1
    0
      service/statistics/constants.js
  61. 1
    0
      service/xmpp/XMPPEvents.js

+ 3
- 0
.eslintrc.js 查看文件

@@ -149,6 +149,9 @@ module.exports = {
149 149
         'multiline-ternary': 0,
150 150
         'new-cap': 2,
151 151
         'new-parens': 2,
152
+        'newline-after-var': 2,
153
+        'newline-before-return': 2,
154
+        'newline-per-chained-call': 2,
152 155
         'no-array-constructor': 2,
153 156
         'no-bitwise': 2,
154 157
         'no-continue': 2,

+ 54
- 1
JitsiConference.js 查看文件

@@ -40,6 +40,7 @@ function JitsiConference(options) {
40 40
         const errmsg
41 41
             = 'Invalid conference name (no conference name passed or it '
42 42
                 + 'contains invalid characters like capital letters)!';
43
+
43 44
         logger.error(errmsg);
44 45
         throw new Error(errmsg);
45 46
     }
@@ -184,7 +185,9 @@ JitsiConference.prototype.leave = function() {
184 185
     // leave the conference
185 186
     if (this.room) {
186 187
         const room = this.room;
188
+
187 189
         this.room = null;
190
+
188 191
         return room.leave().catch(() => {
189 192
             // remove all participants because currently the conference won't
190 193
             // be usable anyway. This is done on success automatically by the
@@ -249,6 +252,7 @@ JitsiConference.prototype.getExternalAuthUrl = function(urlForPopup) {
249 252
     return new Promise((resolve, reject) => {
250 253
         if (!this.isExternalAuthEnabled()) {
251 254
             reject();
255
+
252 256
             return;
253 257
         }
254 258
         if (urlForPopup) {
@@ -266,9 +270,11 @@ JitsiConference.prototype.getExternalAuthUrl = function(urlForPopup) {
266 270
  */
267 271
 JitsiConference.prototype.getLocalTracks = function(mediaType) {
268 272
     let tracks = [];
273
+
269 274
     if (this.rtc) {
270 275
         tracks = this.rtc.getLocalTracks(mediaType);
271 276
     }
277
+
272 278
     return tracks;
273 279
 };
274 280
 
@@ -416,15 +422,18 @@ JitsiConference.prototype.getTranscriber = function() {
416 422
         this.transcriber = new Transcriber();
417 423
         // add all existing local audio tracks to the transcriber
418 424
         const localAudioTracks = this.getLocalTracks(MediaType.AUDIO);
425
+
419 426
         for (const localAudio of localAudioTracks) {
420 427
             this.transcriber.addTrack(localAudio);
421 428
         }
422 429
         // and all remote audio tracks
423 430
         const remoteAudioTracks = this.rtc.getRemoteTracks(MediaType.AUDIO);
431
+
424 432
         for (const remoteTrack of remoteAudioTracks) {
425 433
             this.transcriber.addTrack(remoteTrack);
426 434
         }
427 435
     }
436
+
428 437
     return this.transcriber;
429 438
 };
430 439
 
@@ -439,12 +448,14 @@ JitsiConference.prototype.addTrack = function(track) {
439 448
     if (track.isVideoTrack()) {
440 449
         // Ensure there's exactly 1 local video track in the conference.
441 450
         const localVideoTrack = this.rtc.getLocalVideoTrack();
451
+
442 452
         if (localVideoTrack) {
443 453
             // Don't be excessively harsh and severe if the API client happens
444 454
             // to attempt to add the same local video track twice.
445 455
             if (track === localVideoTrack) {
446 456
                 return Promise.resolve(track);
447 457
             }
458
+
448 459
             return Promise.reject(new Error(
449 460
                     'cannot add second video track to the conference'));
450 461
 
@@ -538,6 +549,7 @@ JitsiConference.prototype.replaceTrack = function(oldTrack, newTrack) {
538 549
         // Set up the ssrcHandler for the new track before we add it at the lower levels
539 550
         newTrack.ssrcHandler = function(conference, ssrcMap) {
540 551
             const trackSSRCInfo = ssrcMap.get(this.getMSID());
552
+
541 553
             if (trackSSRCInfo) {
542 554
                 this._setSSRC(trackSSRCInfo);
543 555
                 conference.rtc.removeListener(
@@ -548,6 +560,7 @@ JitsiConference.prototype.replaceTrack = function(oldTrack, newTrack) {
548 560
         this.rtc.addListener(RTCEvents.SENDRECV_STREAMS_CHANGED,
549 561
             newTrack.ssrcHandler);
550 562
     }
563
+
551 564
     // Now replace the stream at the lower levels
552 565
     return this._doReplaceTrack(oldTrack, newTrack)
553 566
         .then(() => {
@@ -558,6 +571,7 @@ JitsiConference.prototype.replaceTrack = function(oldTrack, newTrack) {
558 571
                 // Now handle the addition of the newTrack at the JitsiConference level
559 572
                 this._setupNewTrack(newTrack);
560 573
             }
574
+
561 575
             return Promise.resolve();
562 576
         }, error => Promise.reject(new Error(error)));
563 577
 };
@@ -577,6 +591,7 @@ JitsiConference.prototype._doReplaceTrack = function(oldTrack, newTrack) {
577 591
     if (this.jingleSession) {
578 592
         return this.jingleSession.replaceTrack(oldTrack, newTrack);
579 593
     }
594
+
580 595
     return Promise.resolve();
581 596
 
582 597
 };
@@ -595,6 +610,7 @@ JitsiConference.prototype._setupNewTrack = function(newTrack) {
595 610
                 d =>
596 611
                     d.kind === `${newTrack.getTrack().kind}input`
597 612
                         && d.label === newTrack.getTrack().label);
613
+
598 614
         if (device) {
599 615
             Statistics.sendActiveDeviceListEvent(
600 616
                 RTC.getEventDataForActiveDevice(device));
@@ -693,8 +709,10 @@ JitsiConference.prototype._generateNewStreamSSRCInfo = function() {
693 709
     if (!this.jingleSession) {
694 710
         logger.warn('The call haven\'t been started. '
695 711
             + 'Cannot generate ssrc info at the moment!');
712
+
696 713
         return null;
697 714
     }
715
+
698 716
     return this.jingleSession.generateNewStreamSSRCInfo();
699 717
 };
700 718
 
@@ -726,6 +744,8 @@ JitsiConference.prototype.lock = function(password) {
726 744
     }
727 745
 
728 746
     const conference = this;
747
+
748
+
729 749
     return new Promise((resolve, reject) => {
730 750
         conference.room.lockRoom(
731 751
             password || '',
@@ -778,6 +798,7 @@ JitsiConference.prototype.setLastN = function(lastN) {
778 798
         throw new Error(`Invalid value for lastN: ${lastN}`);
779 799
     }
780 800
     const n = Number(lastN);
801
+
781 802
     if (n < -1) {
782 803
         throw new RangeError('lastN cannot be smaller than -1');
783 804
     }
@@ -804,10 +825,12 @@ JitsiConference.prototype.getParticipantCount
804 825
     = function(countHidden = false) {
805 826
 
806 827
         let participants = this.getParticipants();
828
+
807 829
         if (!countHidden) {
808 830
             participants = participants.filter(p => !p.isHidden());
809 831
         }
810
-    // Add one for the local participant.
832
+
833
+        // Add one for the local participant.
811 834
         return participants.length + 1;
812 835
     };
813 836
 
@@ -826,6 +849,7 @@ JitsiConference.prototype.getParticipantById = function(id) {
826 849
  */
827 850
 JitsiConference.prototype.kickParticipant = function(id) {
828 851
     const participant = this.getParticipantById(id);
852
+
829 853
     if (!participant) {
830 854
         return;
831 855
     }
@@ -838,6 +862,7 @@ JitsiConference.prototype.kickParticipant = function(id) {
838 862
  */
839 863
 JitsiConference.prototype.muteParticipant = function(id) {
840 864
     const participant = this.getParticipantById(id);
865
+
841 866
     if (!participant) {
842 867
         return;
843 868
     }
@@ -858,10 +883,12 @@ JitsiConference.prototype.muteParticipant = function(id) {
858 883
 JitsiConference.prototype.onMemberJoined
859 884
     = function(jid, nick, role, isHidden) {
860 885
         const id = Strophe.getResourceFromJid(jid);
886
+
861 887
         if (id === 'focus' || this.myUserId() === id) {
862 888
             return;
863 889
         }
864 890
         const participant = new JitsiParticipant(jid, this, nick, isHidden);
891
+
865 892
         participant._role = role;
866 893
         this.participants[id] = participant;
867 894
         this.eventEmitter.emit(JitsiConferenceEvents.USER_JOINED, id, participant);
@@ -873,10 +900,12 @@ JitsiConference.prototype.onMemberJoined
873 900
 
874 901
 JitsiConference.prototype.onMemberLeft = function(jid) {
875 902
     const id = Strophe.getResourceFromJid(jid);
903
+
876 904
     if (id === 'focus' || this.myUserId() === id) {
877 905
         return;
878 906
     }
879 907
     const participant = this.participants[id];
908
+
880 909
     delete this.participants[id];
881 910
 
882 911
     const removedTracks = this.rtc.removeRemoteTracks(id);
@@ -895,6 +924,7 @@ JitsiConference.prototype.onMemberLeft = function(jid) {
895 924
 JitsiConference.prototype.onUserRoleChanged = function(jid, role) {
896 925
     const id = Strophe.getResourceFromJid(jid);
897 926
     const participant = this.getParticipantById(id);
927
+
898 928
     if (!participant) {
899 929
         return;
900 930
     }
@@ -905,6 +935,7 @@ JitsiConference.prototype.onUserRoleChanged = function(jid, role) {
905 935
 JitsiConference.prototype.onDisplayNameChanged = function(jid, displayName) {
906 936
     const id = Strophe.getResourceFromJid(jid);
907 937
     const participant = this.getParticipantById(id);
938
+
908 939
     if (!participant) {
909 940
         return;
910 941
     }
@@ -927,8 +958,10 @@ JitsiConference.prototype.onDisplayNameChanged = function(jid, displayName) {
927 958
 JitsiConference.prototype.onRemoteTrackAdded = function(track) {
928 959
     const id = track.getParticipantId();
929 960
     const participant = this.getParticipantById(id);
961
+
930 962
     if (!participant) {
931 963
         logger.error(`No participant found for id: ${id}`);
964
+
932 965
         return;
933 966
     }
934 967
 
@@ -940,6 +973,7 @@ JitsiConference.prototype.onRemoteTrackAdded = function(track) {
940 973
     }
941 974
 
942 975
     const emitter = this.eventEmitter;
976
+
943 977
     track.addEventListener(
944 978
         JitsiTrackEvents.TRACK_MUTE_CHANGED,
945 979
         () => emitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track));
@@ -1006,6 +1040,7 @@ JitsiConference.prototype.onIncomingCall
1006 1040
         // Error cause this should never happen unless something is wrong!
1007 1041
         const errmsg = `Rejecting session-initiate from non-focus user: ${
1008 1042
                  jingleSession.peerjid}`;
1043
+
1009 1044
         GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
1010 1045
         logger.error(errmsg);
1011 1046
 
@@ -1032,6 +1067,7 @@ JitsiConference.prototype.onIncomingCall
1032 1067
     }
1033 1068
     // add info whether call is cross-region
1034 1069
     let crossRegion = null;
1070
+
1035 1071
     if (window.jitsiRegionInfo) {
1036 1072
         crossRegion = window.jitsiRegionInfo.CrossRegion;
1037 1073
     }
@@ -1060,6 +1096,7 @@ JitsiConference.prototype.onIncomingCall
1060 1096
          *  problems between sdp-interop and trying to keep the ssrcs
1061 1097
          *  consistent
1062 1098
          */
1099
+
1063 1100
         if (localTrack.isVideoTrack() && localTrack.isMuted() && !RTCBrowserType.isFirefox()) {
1064 1101
             /**
1065 1102
              * Handles issues when the stream is added before the peerconnection
@@ -1152,6 +1189,7 @@ JitsiConference.prototype.onCallEnded
1152 1189
     // will learn what their SSRC from the new PeerConnection which will be
1153 1190
     // created on incoming call event.
1154 1191
     const self = this;
1192
+
1155 1193
     this.getLocalTracks().forEach(localTrack => {
1156 1194
         // Reset SSRC as it will no longer be valid
1157 1195
         localTrack._setSSRC(null);
@@ -1209,18 +1247,23 @@ JitsiConference.prototype.sendTones = function(tones, duration, pause) {
1209 1247
     if (!this.dtmfManager) {
1210 1248
         if (!this.jingleSession) {
1211 1249
             logger.warn('cannot sendTones: no jingle session');
1250
+
1212 1251
             return;
1213 1252
         }
1214 1253
 
1215 1254
         const peerConnection = this.jingleSession.peerconnection;
1255
+
1216 1256
         if (!peerConnection) {
1217 1257
             logger.warn('cannot sendTones: no peer connection');
1258
+
1218 1259
             return;
1219 1260
         }
1220 1261
 
1221 1262
         const localAudio = this.getLocalAudioTrack();
1263
+
1222 1264
         if (!localAudio) {
1223 1265
             logger.warn('cannot sendTones: no local audio stream');
1266
+
1224 1267
             return;
1225 1268
         }
1226 1269
         this.dtmfManager = new JitsiDTMFManager(localAudio, peerConnection);
@@ -1236,6 +1279,7 @@ JitsiConference.prototype.isRecordingSupported = function() {
1236 1279
     if (this.room) {
1237 1280
         return this.room.isRecordingSupported();
1238 1281
     }
1282
+
1239 1283
     return false;
1240 1284
 };
1241 1285
 
@@ -1276,6 +1320,7 @@ JitsiConference.prototype.isSIPCallingSupported = function() {
1276 1320
     if (this.room) {
1277 1321
         return this.room.isSIPCallingSupported();
1278 1322
     }
1323
+
1279 1324
     return false;
1280 1325
 };
1281 1326
 
@@ -1287,6 +1332,7 @@ JitsiConference.prototype.dial = function(number) {
1287 1332
     if (this.room) {
1288 1333
         return this.room.dial(number);
1289 1334
     }
1335
+
1290 1336
     return new Promise((resolve, reject) => {
1291 1337
         reject(new Error('The conference is not created yet!'));
1292 1338
     });
@@ -1299,6 +1345,7 @@ JitsiConference.prototype.hangup = function() {
1299 1345
     if (this.room) {
1300 1346
         return this.room.hangup();
1301 1347
     }
1348
+
1302 1349
     return new Promise((resolve, reject) => {
1303 1350
         reject(new Error('The conference is not created yet!'));
1304 1351
     });
@@ -1311,6 +1358,7 @@ JitsiConference.prototype.getPhoneNumber = function() {
1311 1358
     if (this.room) {
1312 1359
         return this.room.getPhoneNumber();
1313 1360
     }
1361
+
1314 1362
     return null;
1315 1363
 };
1316 1364
 
@@ -1321,6 +1369,7 @@ JitsiConference.prototype.getPhonePin = function() {
1321 1369
     if (this.room) {
1322 1370
         return this.room.getPhonePin();
1323 1371
     }
1372
+
1324 1373
     return null;
1325 1374
 };
1326 1375
 
@@ -1332,6 +1381,7 @@ JitsiConference.prototype.getConnectionState = function() {
1332 1381
     if (this.jingleSession) {
1333 1382
         return this.jingleSession.getIceConnectionState();
1334 1383
     }
1384
+
1335 1385
     return null;
1336 1386
 };
1337 1387
 
@@ -1386,11 +1436,13 @@ JitsiConference.prototype.getLogs = function() {
1386 1436
     const data = this.xmpp.getJingleLog();
1387 1437
 
1388 1438
     const metadata = {};
1439
+
1389 1440
     metadata.time = new Date();
1390 1441
     metadata.url = window.location.href;
1391 1442
     metadata.ua = navigator.userAgent;
1392 1443
 
1393 1444
     const log = this.xmpp.getXmppLog();
1445
+
1394 1446
     if (log) {
1395 1447
         metadata.xmpp = log;
1396 1448
     }
@@ -1446,6 +1498,7 @@ JitsiConference.prototype.isCallstatsEnabled = function() {
1446 1498
  */
1447 1499
 JitsiConference.prototype._onTrackAttach = function(track, container) {
1448 1500
     const ssrc = track.getSSRC();
1501
+
1449 1502
     if (!container.id || !ssrc) {
1450 1503
         return;
1451 1504
     }

+ 22
- 0
JitsiConferenceEventManager.js 查看文件

@@ -37,6 +37,7 @@ function JitsiConferenceEventManager(conference) {
37 37
 JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
38 38
     const conference = this.conference;
39 39
     const chatRoom = conference.room;
40
+
40 41
     this.chatRoomForwarder = new EventEmitterForwarder(chatRoom,
41 42
         this.conference.eventEmitter);
42 43
 
@@ -72,10 +73,12 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
72 73
 
73 74
             Object.keys(chatRoom.connectionTimes).forEach(key => {
74 75
                 const value = chatRoom.connectionTimes[key];
76
+
75 77
                 Statistics.analytics.sendEvent(`conference.${key}`, {value});
76 78
             });
77 79
             Object.keys(chatRoom.xmpp.connectionTimes).forEach(key => {
78 80
                 const value = chatRoom.xmpp.connectionTimes[key];
81
+
79 82
                 Statistics.analytics.sendEvent(`xmpp.${key}`, {value});
80 83
             });
81 84
         });
@@ -154,6 +157,7 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
154 157
 
155 158
     const eventLogHandler
156 159
         = reason => Statistics.sendEventToAll(`conference.error.${reason}`);
160
+
157 161
     chatRoom.addListener(XMPPEvents.SESSION_ACCEPT_TIMEOUT,
158 162
         eventLogHandler.bind(null, 'sessionAcceptTimeout'));
159 163
 
@@ -185,6 +189,7 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
185 189
 
186 190
     chatRoom.setParticipantPropertyListener((node, from) => {
187 191
         const participant = conference.getParticipantById(from);
192
+
188 193
         if (!participant) {
189 194
             return;
190 195
         }
@@ -229,6 +234,7 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
229 234
                         id: 'recorder_status',
230 235
                         status
231 236
                     };
237
+
232 238
                     if (error) {
233 239
                         logObject.error = error;
234 240
                     }
@@ -252,6 +258,7 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
252 258
     chatRoom.addListener(XMPPEvents.MESSAGE_RECEIVED,
253 259
         (jid, displayName, txt, myJid, ts) => {
254 260
             const id = Strophe.getResourceFromJid(jid);
261
+
255 262
             conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED,
256 263
                 id, txt, ts);
257 264
         });
@@ -260,6 +267,7 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
260 267
         (jid, status) => {
261 268
             const id = Strophe.getResourceFromJid(jid);
262 269
             const participant = conference.getParticipantById(id);
270
+
263 271
             if (!participant || participant._status === status) {
264 272
                 return;
265 273
             }
@@ -281,10 +289,12 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
281 289
 
282 290
     chatRoom.addPresenceListener('startmuted', (data, from) => {
283 291
         let isModerator = false;
292
+
284 293
         if (conference.myUserId() === from && conference.isModerator()) {
285 294
             isModerator = true;
286 295
         } else {
287 296
             const participant = conference.getParticipantById(from);
297
+
288 298
             if (participant && participant.isModerator()) {
289 299
                 isModerator = true;
290 300
             }
@@ -334,6 +344,7 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
334 344
     chatRoom.addPresenceListener('devices', (data, from) => {
335 345
         let isAudioAvailable = false;
336 346
         let isVideoAvailable = false;
347
+
337 348
         data.children.forEach(config => {
338 349
             if (config.tagName === 'audio') {
339 350
                 isAudioAvailable = config.value === 'true';
@@ -344,10 +355,12 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
344 355
         });
345 356
 
346 357
         let availableDevices;
358
+
347 359
         if (conference.myUserId() === from) {
348 360
             availableDevices = conference.availableDevices;
349 361
         } else {
350 362
             const participant = conference.getParticipantById(from);
363
+
351 364
             if (!participant) {
352 365
                 return;
353 366
             }
@@ -420,6 +433,7 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
420 433
 
421 434
     rtc.addListener(RTCEvents.DATA_CHANNEL_OPEN, () => {
422 435
         const now = window.performance.now();
436
+
423 437
         logger.log('(TIME) data channel opened ', now);
424 438
         conference.room.connectionTimes['data.channel.opened'] = now;
425 439
         Statistics.analytics.sendEvent('conference.dataChannel.open',
@@ -439,6 +453,7 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
439 453
     rtc.addListener(RTCEvents.ENDPOINT_MESSAGE_RECEIVED,
440 454
         (from, payload) => {
441 455
             const participant = conference.getParticipantById(from);
456
+
442 457
             if (participant) {
443 458
                 conference.eventEmitter.emit(
444 459
                     JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
@@ -479,10 +494,12 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
479 494
  */
480 495
 JitsiConferenceEventManager.prototype.setupXMPPListeners = function() {
481 496
     const conference = this.conference;
497
+
482 498
     conference.xmpp.caps.addListener(XMPPEvents.PARTCIPANT_FEATURES_CHANGED,
483 499
         from => {
484 500
             const participant = conference.getParticipantId(
485 501
                 Strophe.getResourceFromJid(from));
502
+
486 503
             if(participant) {
487 504
                 conference.eventEmitter.emit(
488 505
                     JitsiConferenceEvents.PARTCIPANT_FEATURES_CHANGED,
@@ -521,12 +538,14 @@ JitsiConferenceEventManager.prototype.setupXMPPListeners = function() {
521 538
  */
522 539
 JitsiConferenceEventManager.prototype.setupStatisticsListeners = function() {
523 540
     const conference = this.conference;
541
+
524 542
     if(!conference.statistics) {
525 543
         return;
526 544
     }
527 545
 
528 546
     conference.statistics.addAudioLevelListener((ssrc, level) => {
529 547
         const resource = conference.rtc.getResourceBySSRC(ssrc);
548
+
530 549
         if (!resource) {
531 550
             return;
532 551
         }
@@ -554,12 +573,14 @@ JitsiConferenceEventManager.prototype.setupStatisticsListeners = function() {
554 573
             }
555 574
 
556 575
             const id = conference.rtc.getResourceBySSRC(ssrc);
576
+
557 577
             if (!id) {
558 578
                 return;
559 579
             }
560 580
 
561 581
             // ssrc to resolution map for user id
562 582
             const idResolutions = id2resolution[id] || {};
583
+
563 584
             idResolutions[ssrc] = resolution;
564 585
 
565 586
             id2resolution[id] = idResolutions;
@@ -574,6 +595,7 @@ JitsiConferenceEventManager.prototype.setupStatisticsListeners = function() {
574 595
     conference.statistics.addByteSentStatsListener(stats => {
575 596
         conference.getLocalTracks(MediaType.AUDIO).forEach(track => {
576 597
             const ssrc = track.getSSRC();
598
+
577 599
             if (!ssrc || !stats.hasOwnProperty(ssrc)) {
578 600
                 return;
579 601
             }

+ 1
- 0
JitsiConnection.js 查看文件

@@ -1,4 +1,5 @@
1 1
 const JitsiConference = require('./JitsiConference');
2
+
2 3
 import * as JitsiConnectionEvents from './JitsiConnectionEvents';
3 4
 import XMPP from './modules/xmpp/xmpp';
4 5
 const Statistics = require('./modules/statistics/statistics');

+ 1
- 0
JitsiMediaDevices.js 查看文件

@@ -102,6 +102,7 @@ const JitsiMediaDevices = {
102 102
     setAudioOutputDevice(deviceId) {
103 103
 
104 104
         const availableDevices = RTC.getCurrentlyAvailableMediaDevices();
105
+
105 106
         if (availableDevices && availableDevices.length > 0) {
106 107
             // if we have devices info report device to stats
107 108
             // normally this will not happen on startup as this method is called

+ 15
- 1
JitsiMeetJS.js 查看文件

@@ -37,13 +37,16 @@ function getLowerResolution(resolution) {
37 37
     const order = Resolutions[resolution].order;
38 38
     let res = null;
39 39
     let resName = null;
40
+
40 41
     Object.keys(Resolutions).forEach(resolution => {
41 42
         const value = Resolutions[resolution];
43
+
42 44
         if (!res || (res.order < value.order && value.order < order)) {
43 45
             resName = resolution;
44 46
             res = value;
45 47
         }
46 48
     });
49
+
47 50
     return resName;
48 51
 }
49 52
 
@@ -114,6 +117,7 @@ const LibJitsiMeet = {
114 117
         if (window.jitsiRegionInfo
115 118
             && Object.keys(window.jitsiRegionInfo).length > 0) {
116 119
             const logObject = {};
120
+
117 121
             for (const attr in window.jitsiRegionInfo) {
118 122
                 if (window.jitsiRegionInfo.hasOwnProperty(attr)) {
119 123
                     logObject[attr] = window.jitsiRegionInfo[attr];
@@ -130,6 +134,7 @@ const LibJitsiMeet = {
130 134
                 component: 'lib-jitsi-meet',
131 135
                 version: this.version
132 136
             };
137
+
133 138
             Statistics.sendLog(JSON.stringify(logObject));
134 139
         }
135 140
 
@@ -243,6 +248,7 @@ const LibJitsiMeet = {
243 248
                     for(let i = 0; i < tracks.length; i++) {
244 249
                         const track = tracks[i];
245 250
                         const mStream = track.getOriginalStream();
251
+
246 252
                         if(track.getType() === MediaType.AUDIO) {
247 253
                             Statistics.startLocalStats(mStream,
248 254
                                 track.setAudioLevel.bind(track));
@@ -258,16 +264,19 @@ const LibJitsiMeet = {
258 264
                 // set real device ids
259 265
                 const currentlyAvailableMediaDevices
260 266
                     = RTC.getCurrentlyAvailableMediaDevices();
267
+
261 268
                 if (currentlyAvailableMediaDevices) {
262 269
                     for(let i = 0; i < tracks.length; i++) {
263 270
                         const track = tracks[i];
271
+
264 272
                         track._setRealDeviceIdFromDeviceList(
265 273
                             currentlyAvailableMediaDevices);
266 274
                     }
267 275
                 }
268 276
 
269 277
                 return tracks;
270
-            }).catch(error => {
278
+            })
279
+            .catch(error => {
271 280
                 promiseFulfilled = true;
272 281
 
273 282
                 if(error.name === JitsiTrackErrors.UNSUPPORTED_RESOLUTION) {
@@ -296,6 +305,7 @@ const LibJitsiMeet = {
296 305
                         id: 'chrome_extension_user_canceled',
297 306
                         message: error.message
298 307
                     };
308
+
299 309
                     Statistics.sendLog(JSON.stringify(logObject));
300 310
                     Statistics.analytics.sendEvent(
301 311
                         'getUserMedia.userCancel.extensionInstall');
@@ -305,6 +315,7 @@ const LibJitsiMeet = {
305 315
                         id: 'usermedia_missing_device',
306 316
                         status: error.gum.devices
307 317
                     };
318
+
308 319
                     Statistics.sendLog(JSON.stringify(logObject));
309 320
                     Statistics.analytics.sendEvent(
310 321
                         `getUserMedia.deviceNotFound.${
@@ -316,6 +327,7 @@ const LibJitsiMeet = {
316 327
                         = addDeviceTypeToAnalyticsEvent(
317 328
                             'getUserMedia.failed',
318 329
                             options);
330
+
319 331
                     Statistics.analytics.sendEvent(
320 332
                         `${event}.${error.name}`,
321 333
                         {value: options});
@@ -337,6 +349,7 @@ const LibJitsiMeet = {
337 349
     isDeviceListAvailable() {
338 350
         logger.warn('This method is deprecated, use '
339 351
             + 'JitsiMeetJS.mediaDevices.isDeviceListAvailable instead');
352
+
340 353
         return this.mediaDevices.isDeviceListAvailable();
341 354
     },
342 355
     /**
@@ -350,6 +363,7 @@ const LibJitsiMeet = {
350 363
     isDeviceChangeAvailable(deviceType) {
351 364
         logger.warn('This method is deprecated, use '
352 365
             + 'JitsiMeetJS.mediaDevices.isDeviceChangeAvailable instead');
366
+
353 367
         return this.mediaDevices.isDeviceChangeAvailable(deviceType);
354 368
     },
355 369
     /**

+ 31
- 17
doc/example/example.js 查看文件

@@ -63,10 +63,12 @@ function onRemoteTrack(track) {
63 63
         return;
64 64
     }
65 65
     const participant = track.getParticipantId();
66
+
66 67
     if(!remoteTracks[participant]) {
67 68
         remoteTracks[participant] = [];
68 69
     }
69 70
     const idx = remoteTracks[participant].push(track);
71
+
70 72
     track.addEventListener(
71 73
         JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
72 74
         audioLevel => console.log(`Audio Level remote: ${audioLevel}`));
@@ -81,6 +83,7 @@ function onRemoteTrack(track) {
81 83
             console.log(
82 84
                 `track audio output device was changed to ${deviceId}`));
83 85
     const id = participant + track.getType() + idx;
86
+
84 87
     if(track.getType() == 'video') {
85 88
         $('body').append(`<video autoplay='1' id='${participant}video${idx}' />`);
86 89
     } else {
@@ -106,6 +109,7 @@ function onUserLeft(id) {
106 109
         return;
107 110
     }
108 111
     const tracks = remoteTracks[id];
112
+
109 113
     for(let i = 0; i < tracks.length; i++) {
110 114
         tracks[i].detach($(`#${id}${tracks[i].getType()}`));
111 115
     }
@@ -181,6 +185,7 @@ function unload() {
181 185
 }
182 186
 
183 187
 let isVideo = true;
188
+
184 189
 function switchVideo() { // eslint-disable-line no-unused-vars
185 190
     isVideo = !isVideo;
186 191
     if(localTracks[1]) {
@@ -200,9 +205,8 @@ function switchVideo() { // eslint-disable-line no-unused-vars
200 205
                 });
201 206
             localTracks[1].attach($('#localVideo1')[0]);
202 207
             room.addTrack(localTracks[1]);
203
-        }).catch(error => {
204
-            console.log(error);
205
-        });
208
+        })
209
+        .catch(error => console.log(error));
206 210
 }
207 211
 
208 212
 function changeAudioOutput(selected) { // eslint-disable-line no-unused-vars
@@ -239,23 +243,33 @@ const initOptions = {
239 243
     // The URL to the Firefox extension for desktop sharing.
240 244
     desktopSharingFirefoxExtensionURL: null
241 245
 };
242
-JitsiMeetJS.init(initOptions).then(() => {
243
-    connection = new JitsiMeetJS.JitsiConnection(null, null, options);
244 246
 
245
-    connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, onConnectionSuccess);
246
-    connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, onConnectionFailed);
247
-    connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, disconnect);
247
+JitsiMeetJS.init(initOptions)
248
+    .then(() => {
249
+        connection = new JitsiMeetJS.JitsiConnection(null, null, options);
250
+
251
+        connection.addEventListener(
252
+            JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
253
+            onConnectionSuccess);
254
+        connection.addEventListener(
255
+            JitsiMeetJS.events.connection.CONNECTION_FAILED,
256
+            onConnectionFailed);
257
+        connection.addEventListener(
258
+            JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
259
+            disconnect);
248 260
 
249
-    JitsiMeetJS.mediaDevices.addEventListener(JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED, onDeviceListChanged);
261
+        JitsiMeetJS.mediaDevices.addEventListener(
262
+            JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED,
263
+            onDeviceListChanged);
250 264
 
251
-    connection.connect();
252
-    JitsiMeetJS.createLocalTracks({devices: ['audio', 'video']})
253
-        .then(onLocalTracks).catch(error => {
254
-            throw error;
255
-        });
256
-}).catch(error => {
257
-    console.log(error);
258
-});
265
+        connection.connect();
266
+        JitsiMeetJS.createLocalTracks({devices: ['audio', 'video']})
267
+            .then(onLocalTracks)
268
+            .catch(error => {
269
+                throw error;
270
+            });
271
+    })
272
+    .catch(error => console.log(error));
259 273
 
260 274
 if (JitsiMeetJS.mediaDevices.isDeviceChangeAvailable('output')) {
261 275
     JitsiMeetJS.mediaDevices.enumerateDevices(devices => {

+ 1
- 0
modules/DTMF/JitsiDTMFManager.js 查看文件

@@ -2,6 +2,7 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
2 2
 
3 3
 function JitsiDTMFManager(localAudio, peerConnection) {
4 4
     const audioTrack = localAudio.getTrack();
5
+
5 6
     if (!audioTrack) {
6 7
         throw new Error('Failed to initialize DTMFSender: no audio track.');
7 8
     }

+ 6
- 0
modules/RTC/DataChannels.js 查看文件

@@ -139,6 +139,7 @@ DataChannels.prototype.onDataChannel = function(event) {
139 139
             } else if ('EndpointConnectivityStatusChangeEvent' === colibriClass) {
140 140
                 const endpoint = obj.endpoint;
141 141
                 const isActive = obj.active === 'true';
142
+
142 143
                 logger.info(
143 144
                     `Endpoint connection status changed: ${endpoint} active ? ${
144 145
                         isActive}`);
@@ -158,6 +159,7 @@ DataChannels.prototype.onDataChannel = function(event) {
158 159
     dataChannel.onclose = function() {
159 160
         logger.info('The Data Channel closed', dataChannel);
160 161
         const idx = self._dataChannels.indexOf(dataChannel);
162
+
161 163
         if (idx > -1) {
162 164
             self._dataChannels = self._dataChannels.splice(idx, 1);
163 165
         }
@@ -215,6 +217,7 @@ DataChannels.prototype._onXXXEndpointChanged = function(xxx, userResource) {
215 217
     const tail = xxx.substring(1);
216 218
     const lower = head.toLowerCase() + tail;
217 219
     const upper = head.toUpperCase() + tail;
220
+
218 221
     logger.log(
219 222
             `sending ${lower} endpoint changed notification to the bridge: `,
220 223
             userResource);
@@ -238,9 +241,11 @@ DataChannels.prototype._some = function(callback, thisArg) {
238 241
         if (thisArg) {
239 242
             return dataChannels.some(callback, thisArg);
240 243
         }
244
+
241 245
         return dataChannels.some(callback);
242 246
 
243 247
     }
248
+
244 249
     return false;
245 250
 
246 251
 };
@@ -256,6 +261,7 @@ DataChannels.prototype.send = function(jsonObject) {
256 261
     if(!this._some(dataChannel => {
257 262
         if (dataChannel.readyState == 'open') {
258 263
             dataChannel.send(JSON.stringify(jsonObject));
264
+
259 265
             return true;
260 266
         }
261 267
     })) {

+ 10
- 0
modules/RTC/JitsiLocalTrack.js 查看文件

@@ -146,9 +146,11 @@ JitsiLocalTrack.prototype._initNoDataFromSourceHandlers = function() {
146 146
     if(this.isVideoTrack() && this.videoType === VideoType.CAMERA) {
147 147
         const _onNoDataFromSourceError
148 148
             = this._onNoDataFromSourceError.bind(this);
149
+
149 150
         this._setHandler('track_mute', () => {
150 151
             if(this._checkForCameraIssues()) {
151 152
                 const now = window.performance.now();
153
+
152 154
                 this._noDataFromSourceTimeout
153 155
                     = setTimeout(_onNoDataFromSourceError, 3000);
154 156
                 this._setHandler('track_unmute', () => {
@@ -194,8 +196,10 @@ JitsiLocalTrack.prototype._onNoDataFromSourceError = function() {
194 196
 JitsiLocalTrack.prototype._fireNoDataFromSourceEvent = function() {
195 197
     this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
196 198
     const eventName = `${this.getType()}.no_data_from_source`;
199
+
197 200
     Statistics.analytics.sendEvent(eventName);
198 201
     const log = {name: eventName};
202
+
199 203
     if (this.isAudioTrack()) {
200 204
         log.isReceivingData = this._isReceivingData();
201 205
     }
@@ -316,6 +320,7 @@ JitsiLocalTrack.prototype._setMute = function(mute) {
316 320
             devices: [ MediaType.VIDEO ],
317 321
             facingMode: this.getCameraFacingMode()
318 322
         };
323
+
319 324
         if (this.resolution) {
320 325
             streamOptions.resolution = this.resolution;
321 326
         }
@@ -390,6 +395,7 @@ JitsiLocalTrack.prototype._removeStreamFromConferenceAsMute
390 395
 = function(successCallback, errorCallback) {
391 396
     if (!this.conference) {
392 397
         successCallback();
398
+
393 399
         return;
394 400
     }
395 401
 
@@ -474,6 +480,7 @@ JitsiLocalTrack.prototype.isMuted = function() {
474 480
     if (this.isVideoTrack() && !this.isActive()) {
475 481
         return true;
476 482
     }
483
+
477 484
     return !this.track || !this.track.enabled;
478 485
 
479 486
 };
@@ -517,6 +524,7 @@ JitsiLocalTrack.prototype.getSSRC = function() {
517 524
     } else if(this.ssrc && this.ssrc.ssrcs && this.ssrc.ssrcs.length) {
518 525
         return this.ssrc.ssrcs[0];
519 526
     }
527
+
520 528
     return null;
521 529
 
522 530
 };
@@ -549,6 +557,7 @@ JitsiLocalTrack.prototype._setByteSent = function(bytesSent) {
549 557
     // the conference(and through the XMPP chat room ???) instead
550 558
     const iceConnectionState
551 559
         = this.conference ? this.conference.getConnectionState() : null;
560
+
552 561
     if(this._testByteSent && 'connected' === iceConnectionState) {
553 562
         setTimeout(() => {
554 563
             if(this._bytesSent <= 0) {
@@ -636,6 +645,7 @@ JitsiLocalTrack.prototype._isReceivingData = function() {
636 645
     if(!this.stream) {
637 646
         return false;
638 647
     }
648
+
639 649
     // In older version of the spec there is no muted property and
640 650
     // readyState can have value muted. In the latest versions
641 651
     // readyState can have values "live" and "ended" and there is

+ 4
- 0
modules/RTC/JitsiRemoteTrack.js 查看文件

@@ -1,6 +1,7 @@
1 1
 /* global */
2 2
 
3 3
 const JitsiTrack = require('./JitsiTrack');
4
+
4 5
 import * as JitsiTrackEvents from '../../JitsiTrackEvents';
5 6
 const logger = require('jitsi-meet-logger').getLogger(__filename);
6 7
 const RTCBrowserType = require('./RTCBrowserType');
@@ -152,6 +153,7 @@ JitsiRemoteTrack.prototype._playCallback = function() {
152 153
     const type = this.isVideoTrack() ? 'video' : 'audio';
153 154
 
154 155
     const now = window.performance.now();
156
+
155 157
     console.log(`(TIME) Render ${type}:\t`, now);
156 158
     this.conference.getConnectionTimes()[`${type}.render`] = now;
157 159
 
@@ -160,9 +162,11 @@ JitsiRemoteTrack.prototype._playCallback = function() {
160 162
         - this.conference.getConnectionTimes()['muc.joined'])
161 163
         - (window.connectionTimes['obtainPermissions.end']
162 164
         - window.connectionTimes['obtainPermissions.start']);
165
+
163 166
     this.conference.getConnectionTimes()[`${type}.ttfm`] = ttfm;
164 167
     console.log(`(TIME) TTFM ${type}:\t`, ttfm);
165 168
     let eventName = `${type}.ttfm`;
169
+
166 170
     if(this.hasBeenMuted) {
167 171
         eventName += '.muted';
168 172
     }

+ 7
- 0
modules/RTC/JitsiTrack.js 查看文件

@@ -31,6 +31,7 @@ function implementOnEndedHandling(jitsiTrack) {
31 31
     }
32 32
 
33 33
     const originalStop = stream.stop;
34
+
34 35
     stream.stop = function() {
35 36
         originalStop.apply(stream);
36 37
         if (jitsiTrack.isActive()) {
@@ -211,6 +212,7 @@ JitsiTrack.prototype.getUsageLabel = function() {
211 212
     if (this.isAudioTrack()) {
212 213
         return 'mic';
213 214
     }
215
+
214 216
     return this.videoType ? this.videoType : 'default';
215 217
 
216 218
 };
@@ -267,6 +269,7 @@ JitsiTrack.prototype.attach = function(container) {
267 269
 JitsiTrack.prototype.detach = function(container) {
268 270
     for (let cs = this.containers, i = cs.length - 1; i >= 0; --i) {
269 271
         const c = cs[i];
272
+
270 273
         if (!container) {
271 274
             RTCUtils.attachMediaStream(c, null);
272 275
         }
@@ -322,6 +325,7 @@ JitsiTrack.prototype.getId = function() {
322 325
     if(this.stream) {
323 326
         return RTCUtils.getStreamID(this.stream);
324 327
     }
328
+
325 329
     return null;
326 330
 
327 331
 };
@@ -336,6 +340,7 @@ JitsiTrack.prototype.isActive = function() {
336 340
     if(typeof this.stream.active !== 'undefined') {
337 341
         return this.stream.active;
338 342
     }
343
+
339 344
     return true;
340 345
 
341 346
 };
@@ -386,6 +391,8 @@ JitsiTrack.prototype.setAudioLevel = function(audioLevel) {
386 391
 JitsiTrack.prototype.getMSID = function() {
387 392
     const streamId = this.getStreamId();
388 393
     const trackId = this.getTrackId();
394
+
395
+
389 396
     return streamId && trackId ? `${streamId} ${trackId}` : null;
390 397
 };
391 398
 

+ 32
- 1
modules/RTC/RTC.js 查看文件

@@ -18,6 +18,7 @@ const logger = getLogger(__filename);
18 18
 function createLocalTracks(tracksInfo, options) {
19 19
     const newTracks = [];
20 20
     let deviceId = null;
21
+
21 22
     tracksInfo.forEach(trackInfo => {
22 23
         if (trackInfo.mediaType === MediaType.AUDIO) {
23 24
             deviceId = options.micDeviceId;
@@ -33,8 +34,10 @@ function createLocalTracks(tracksInfo, options) {
33 34
                 trackInfo.resolution,
34 35
                 deviceId,
35 36
                 options.facingMode);
37
+
36 38
         newTracks.push(localTrack);
37 39
     });
40
+
38 41
     return newTracks;
39 42
 }
40 43
 
@@ -70,6 +73,7 @@ export default class RTC extends Listenable {
70 73
                 deviceId => {
71 74
                     const remoteAudioTracks
72 75
                         = this.getRemoteTracks(MediaType.AUDIO);
76
+
73 77
                     for (const track of remoteAudioTracks) {
74 78
                         track.setAudioOutput(deviceId);
75 79
                     }
@@ -95,6 +99,8 @@ export default class RTC extends Listenable {
95 99
         return RTCUtils.obtainAudioAndVideoPermissions(options).then(
96 100
             tracksInfo => {
97 101
                 const tracks = createLocalTracks(tracksInfo, options);
102
+
103
+
98 104
                 return tracks.some(track => !track._isReceivingData())
99 105
                     ? Promise.reject(
100 106
                         new JitsiTrackError(
@@ -201,6 +207,7 @@ export default class RTC extends Listenable {
201 207
 
202 208
     static init(options = {}) {
203 209
         this.options = options;
210
+
204 211
         return RTCUtils.init(this.options);
205 212
     }
206 213
 
@@ -232,6 +239,7 @@ export default class RTC extends Listenable {
232 239
 
233 240
         this.peerConnections.set(newConnection.id, newConnection);
234 241
         this.peerConnectionIdCounter += 1;
242
+
235 243
         return newConnection;
236 244
     }
237 245
 
@@ -244,11 +252,14 @@ export default class RTC extends Listenable {
244 252
      */
245 253
     _removePeerConnection(traceablePeerConnection) {
246 254
         const id = traceablePeerConnection.id;
255
+
247 256
         if (this.peerConnections.has(id)) {
248 257
             // NOTE Remote tracks are not removed here.
249 258
             this.peerConnections.delete(id);
259
+
250 260
             return true;
251 261
         }
262
+
252 263
         return false;
253 264
 
254 265
     }
@@ -269,6 +280,8 @@ export default class RTC extends Listenable {
269 280
      */
270 281
     getLocalVideoTrack() {
271 282
         const localVideo = this.getLocalTracks(MediaType.VIDEO);
283
+
284
+
272 285
         return localVideo.length ? localVideo[0] : undefined;
273 286
     }
274 287
 
@@ -278,6 +291,8 @@ export default class RTC extends Listenable {
278 291
      */
279 292
     getLocalAudioTrack() {
280 293
         const localAudio = this.getLocalTracks(MediaType.AUDIO);
294
+
295
+
281 296
         return localAudio.length ? localAudio[0] : undefined;
282 297
     }
283 298
 
@@ -289,10 +304,12 @@ export default class RTC extends Listenable {
289 304
      */
290 305
     getLocalTracks(mediaType) {
291 306
         let tracks = this.localTracks.slice();
307
+
292 308
         if (mediaType !== undefined) {
293 309
             tracks = tracks.filter(
294 310
                 track => track.getType() === mediaType);
295 311
         }
312
+
296 313
         return tracks;
297 314
     }
298 315
 
@@ -321,6 +338,7 @@ export default class RTC extends Listenable {
321 338
                 }
322 339
             }
323 340
         }
341
+
324 342
         return remoteTracks;
325 343
     }
326 344
 
@@ -335,6 +353,7 @@ export default class RTC extends Listenable {
335 353
         if (this.remoteTracks[resource]) {
336 354
             return this.remoteTracks[resource][type];
337 355
         }
356
+
338 357
         return null;
339 358
 
340 359
     }
@@ -366,16 +385,20 @@ export default class RTC extends Listenable {
366 385
      */
367 386
     setAudioMute(value) {
368 387
         const mutePromises = [];
388
+
369 389
         this.getLocalTracks(MediaType.AUDIO).forEach(audioTrack => {
370 390
             // this is a Promise
371 391
             mutePromises.push(value ? audioTrack.mute() : audioTrack.unmute());
372 392
         });
373
-        // we return a Promise from all Promises so we can wait for their execution
393
+
394
+        // We return a Promise from all Promises so we can wait for their
395
+        // execution.
374 396
         return Promise.all(mutePromises);
375 397
     }
376 398
 
377 399
     removeLocalTrack(track) {
378 400
         const pos = this.localTracks.indexOf(track);
401
+
379 402
         if (pos === -1) {
380 403
             return;
381 404
         }
@@ -435,6 +458,7 @@ export default class RTC extends Listenable {
435 458
 
436 459
             delete this.remoteTracks[owner];
437 460
         }
461
+
438 462
         return removedTracks;
439 463
     }
440 464
 
@@ -460,8 +484,10 @@ export default class RTC extends Listenable {
460 484
                         && mediaTrack.getStreamId() == streamId
461 485
                         && mediaTrack.getTrackId() == trackId) {
462 486
                         result = mediaTrack;
487
+
463 488
                         return true;
464 489
                     }
490
+
465 491
                     return false;
466 492
 
467 493
                 });
@@ -637,6 +663,7 @@ export default class RTC extends Listenable {
637 663
             return;
638 664
         }
639 665
         const audioTrack = this.getRemoteAudioTrack(resource);
666
+
640 667
         if(audioTrack) {
641 668
             audioTrack.setAudioLevel(audioLevel);
642 669
         }
@@ -654,6 +681,8 @@ export default class RTC extends Listenable {
654 681
         }
655 682
 
656 683
         const track = this.getRemoteTrackBySSRC(ssrc);
684
+
685
+
657 686
         return track ? track.getParticipantId() : null;
658 687
     }
659 688
 
@@ -676,6 +705,7 @@ export default class RTC extends Listenable {
676 705
      */
677 706
     handleRemoteTrackMute(type, isMuted, from) {
678 707
         const track = this.getRemoteTrackByType(type, from);
708
+
679 709
         if (track) {
680 710
             track.setMute(isMuted);
681 711
         }
@@ -688,6 +718,7 @@ export default class RTC extends Listenable {
688 718
      */
689 719
     handleRemoteTrackVideoTypeChanged(value, from) {
690 720
         const videoTrack = this.getRemoteVideoTrack(from);
721
+
691 722
         if (videoTrack) {
692 723
             videoTrack._setVideoType(value);
693 724
         }

+ 32
- 0
modules/RTC/RTCBrowserType.js 查看文件

@@ -34,11 +34,13 @@ const RTCBrowserType = {
34 34
      */
35 35
     getBrowserName() {
36 36
         let browser;
37
+
37 38
         if (RTCBrowserType.isAndroid()) {
38 39
             browser = 'android';
39 40
         } else {
40 41
             browser = currentBrowser.split('rtc_browser.')[1];
41 42
         }
43
+
42 44
         return browser;
43 45
     },
44 46
 
@@ -199,20 +201,27 @@ function detectChrome() {
199 201
         // We can assume that user agent is chrome, because it's
200 202
         // enforced when 'ext' streaming method is set
201 203
         const ver = parseInt(userAgent.match(/chrome\/(\d+)\./)[1], 10);
204
+
202 205
         logger.log(`This appears to be Chrome, ver: ${ver}`);
206
+
203 207
         return ver;
204 208
     }
209
+
205 210
     return null;
206 211
 }
207 212
 
208 213
 function detectOpera() {
209 214
     const userAgent = navigator.userAgent;
215
+
210 216
     if (userAgent.match(/Opera|OPR/)) {
211 217
         currentBrowser = RTCBrowserType.RTC_BROWSER_OPERA;
212 218
         const version = userAgent.match(/(Opera|OPR) ?\/?(\d+)\.?/)[2];
219
+
213 220
         logger.info(`This appears to be Opera, ver: ${version}`);
221
+
214 222
         return version;
215 223
     }
224
+
216 225
     return null;
217 226
 }
218 227
 
@@ -221,9 +230,12 @@ function detectFirefox() {
221 230
         currentBrowser = RTCBrowserType.RTC_BROWSER_FIREFOX;
222 231
         const version = parseInt(
223 232
             navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
233
+
224 234
         logger.log(`This appears to be Firefox, ver: ${version}`);
235
+
225 236
         return version;
226 237
     }
238
+
227 239
     return null;
228 240
 }
229 241
 
@@ -231,9 +243,11 @@ function detectSafari() {
231 243
     if (/^((?!chrome).)*safari/i.test(navigator.userAgent)) {
232 244
         currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;
233 245
         logger.info('This appears to be Safari');
246
+
234 247
         // FIXME detect Safari version when needed
235 248
         return 1;
236 249
     }
250
+
237 251
     return null;
238 252
 }
239 253
 
@@ -242,19 +256,23 @@ function detectIE() {
242 256
     const ua = window.navigator.userAgent;
243 257
 
244 258
     const msie = ua.indexOf('MSIE ');
259
+
245 260
     if (msie > 0) {
246 261
         // IE 10 or older => return version number
247 262
         version = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
248 263
     }
249 264
 
250 265
     const trident = ua.indexOf('Trident/');
266
+
251 267
     if (!version && trident > 0) {
252 268
         // IE 11 => return version number
253 269
         const rv = ua.indexOf('rv:');
270
+
254 271
         version = parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
255 272
     }
256 273
 
257 274
     const edge = ua.indexOf('Edge/');
275
+
258 276
     if (!version && edge > 0) {
259 277
         // IE 12 => return version number
260 278
         version = parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
@@ -264,6 +282,7 @@ function detectIE() {
264 282
         currentBrowser = RTCBrowserType.RTC_BROWSER_IEXPLORER;
265 283
         logger.info(`This appears to be IExplorer, ver: ${version}`);
266 284
     }
285
+
267 286
     return version;
268 287
 }
269 288
 
@@ -272,23 +291,31 @@ function detectIE() {
272 291
  */
273 292
 function detectElectron() {
274 293
     const userAgent = navigator.userAgent;
294
+
275 295
     if (userAgent.match(/Electron/)) {
276 296
         currentBrowser = RTCBrowserType.RTC_BROWSER_ELECTRON;
277 297
         const version = userAgent.match(/Electron\/([\d.]+)/)[1];
298
+
278 299
         logger.info(`This appears to be Electron, ver: ${version}`);
300
+
279 301
         return version;
280 302
     }
303
+
281 304
     return null;
282 305
 }
283 306
 
284 307
 function detectNWJS() {
285 308
     const userAgent = navigator.userAgent;
309
+
286 310
     if (userAgent.match(/JitsiMeetNW/)) {
287 311
         currentBrowser = RTCBrowserType.RTC_BROWSER_NWJS;
288 312
         const version = userAgent.match(/JitsiMeetNW\/([\d.]+)/)[1];
313
+
289 314
         logger.info(`This appears to be JitsiMeetNW, ver: ${version}`);
315
+
290 316
         return version;
291 317
     }
318
+
292 319
     return null;
293 320
 }
294 321
 
@@ -299,9 +326,11 @@ function detectReactNative() {
299 326
     // If we're remote debugging a React Native app, it may be treated as
300 327
     // Chrome. Check navigator.product as well and always return some version
301 328
     // even if we can't get the real one.
329
+
302 330
     if (match || navigator.product === 'ReactNative') {
303 331
         currentBrowser = RTCBrowserType.RTC_BROWSER_REACT_NATIVE;
304 332
         let name;
333
+
305 334
         if (match && match.length > 2) {
306 335
             name = match[1];
307 336
             version = match[2];
@@ -313,6 +342,7 @@ function detectReactNative() {
313 342
         // We're not running in a React Native environment.
314 343
         version = null;
315 344
     }
345
+
316 346
     return version;
317 347
 }
318 348
 
@@ -329,6 +359,7 @@ function detectBrowser() {
329 359
         detectSafari
330 360
     ];
331 361
     // Try all browser detectors
362
+
332 363
     for (let i = 0; i < detectors.length; i++) {
333 364
         version = detectors[i]();
334 365
         if (version) {
@@ -337,6 +368,7 @@ function detectBrowser() {
337 368
     }
338 369
     logger.warn('Browser type defaults to Safari ver 1');
339 370
     currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;
371
+
340 372
     return 1;
341 373
 }
342 374
 

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

@@ -23,17 +23,20 @@ const RTCUIHelper = {
23 23
      */
24 24
     findVideoElement(containerElement) {
25 25
         const videoElemName = RTCUIHelper.getVideoElementName();
26
+
26 27
         if (!RTCBrowserType.isTemasysPluginUsed()) {
27 28
             return $(containerElement).find(videoElemName)[0];
28 29
         }
29 30
         const matching = $(containerElement).find(
30 31
                 ` ${videoElemName}>param[value="video"]`);
32
+
31 33
         if (matching.length) {
32 34
             if (matching.length > 1) {
33 35
                 logger.warn(
34 36
                         'Container with more than one video elements: ',
35 37
                         containerElement);
36 38
             }
39
+
37 40
             return matching.parent()[0];
38 41
         }
39 42
 

+ 37
- 2
modules/RTC/RTCUtils.js 查看文件

@@ -66,6 +66,7 @@ let rawEnumerateDevicesWithCallback = undefined;
66 66
  * ready. Otherwise it is too early to assume that the devices listing is not
67 67
  * supported.
68 68
  */
69
+
69 70
 function initRawEnumerateDevicesWithCallback() {
70 71
     rawEnumerateDevicesWithCallback = navigator.mediaDevices
71 72
         && navigator.mediaDevices.enumerateDevices
@@ -265,6 +266,7 @@ function getConstraints(um, options) {
265 266
             const errmsg
266 267
                 = '\'screen\' WebRTC media source is supported only in Chrome'
267 268
                     + ' and with Temasys plugin';
269
+
268 270
             GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
269 271
             logger.error(errmsg);
270 272
         }
@@ -333,8 +335,15 @@ function compareAvailableMediaDevices(newDevices) {
333 335
         return true;
334 336
     }
335 337
 
336
-    return newDevices.map(mediaDeviceInfoToJSON).sort().join('')
337
-        !== currentlyAvailableMediaDevices.map(mediaDeviceInfoToJSON).sort().join('');
338
+    return (
339
+        newDevices
340
+                .map(mediaDeviceInfoToJSON)
341
+                .sort()
342
+                .join('')
343
+            !== currentlyAvailableMediaDevices
344
+                .map(mediaDeviceInfoToJSON)
345
+                .sort()
346
+                .join(''));
338 347
 
339 348
     function mediaDeviceInfoToJSON(info) {
340 349
         return JSON.stringify({
@@ -538,6 +547,7 @@ function obtainDevices(options) {
538 547
 
539 548
     const device = options.devices.splice(0, 1);
540 549
     const devices = [];
550
+
541 551
     devices.push(device);
542 552
     options.deviceGUM[device](
543 553
         stream => {
@@ -578,8 +588,10 @@ function handleLocalStream(streams, resolution) {
578 588
         // (with a result which meets our requirements expressed bellow) calling
579 589
         // getUserMedia once for both audio and video.
580 590
         const audioVideo = streams.audioVideo;
591
+
581 592
         if (audioVideo) {
582 593
             const audioTracks = audioVideo.getAudioTracks();
594
+
583 595
             if (audioTracks.length) {
584 596
                 // eslint-disable-next-line new-cap
585 597
                 audioStream = new webkitMediaStream();
@@ -589,6 +601,7 @@ function handleLocalStream(streams, resolution) {
589 601
             }
590 602
 
591 603
             const videoTracks = audioVideo.getVideoTracks();
604
+
592 605
             if (videoTracks.length) {
593 606
                 // eslint-disable-next-line new-cap
594 607
                 videoStream = new webkitMediaStream();
@@ -693,6 +706,7 @@ function wrapAttachMediaStream(origAttachMediaStream) {
693 706
 function defaultSetVideoSrc(element, stream) {
694 707
     // srcObject
695 708
     let srcObjectPropertyName = 'srcObject';
709
+
696 710
     if (!(srcObjectPropertyName in element)) {
697 711
         srcObjectPropertyName = 'mozSrcObject';
698 712
         if (!(srcObjectPropertyName in element)) {
@@ -701,11 +715,13 @@ function defaultSetVideoSrc(element, stream) {
701 715
     }
702 716
     if (srcObjectPropertyName) {
703 717
         element[srcObjectPropertyName] = stream;
718
+
704 719
         return;
705 720
     }
706 721
 
707 722
     // src
708 723
     let src;
724
+
709 725
     if (stream) {
710 726
         src = stream.jitsiObjectURL;
711 727
         // Save the created URL for stream so we can reuse it and not keep
@@ -738,6 +754,7 @@ class RTCUtils extends Listenable {
738 754
         return new Promise((resolve, reject) => {
739 755
             if (RTCBrowserType.isFirefox()) {
740 756
                 const FFversion = RTCBrowserType.getFirefoxVersion();
757
+
741 758
                 if (FFversion < 40) {
742 759
                     rejectWithWebRTCNotSupported(
743 760
                         `Firefox version too old: ${FFversion}.`
@@ -766,17 +783,21 @@ class RTCUtils extends Listenable {
766 783
                             element.play();
767 784
                         }
768 785
                     }
786
+
769 787
                     return element;
770 788
                 });
771 789
                 this.getStreamID = function(stream) {
772 790
                     let id = stream.id;
791
+
773 792
                     if (!id) {
774 793
                         let tracks = stream.getVideoTracks();
794
+
775 795
                         if (!tracks || tracks.length === 0) {
776 796
                             tracks = stream.getAudioTracks();
777 797
                         }
778 798
                         id = tracks[0].id;
779 799
                     }
800
+
780 801
                     return SDPUtil.filter_special_chars(id);
781 802
                 };
782 803
                 RTCSessionDescription = mozRTCSessionDescription; // eslint-disable-line
@@ -789,6 +810,7 @@ class RTCUtils extends Listenable {
789 810
 
790 811
                 this.peerconnection = webkitRTCPeerConnection;
791 812
                 const getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
813
+
792 814
                 if (navigator.mediaDevices) {
793 815
                     this.getUserMedia = wrapGetUserMedia(getUserMedia);
794 816
                     this.enumerateDevices = wrapEnumerateDevices(
@@ -800,6 +822,7 @@ class RTCUtils extends Listenable {
800 822
                 }
801 823
                 this.attachMediaStream = wrapAttachMediaStream((element, stream) => {
802 824
                     defaultSetVideoSrc(element, stream);
825
+
803 826
                     return element;
804 827
                 });
805 828
                 this.getStreamID = function(stream) {
@@ -813,6 +836,7 @@ class RTCUtils extends Listenable {
813 836
                     // XXX The return statement is affected by automatic
814 837
                     // semicolon insertion (ASI). No line terminator is allowed
815 838
                     // between the return keyword and the expression.
839
+
816 840
                     return (
817 841
                         typeof id === 'number'
818 842
                             ? id
@@ -859,11 +883,13 @@ class RTCUtils extends Listenable {
859 883
                             // The container must be visible in order to play or
860 884
                             // attach the stream when Temasys plugin is in use
861 885
                             const containerSel = $(element);
886
+
862 887
                             if (RTCBrowserType.isTemasysPluginUsed()
863 888
                                     && !containerSel.is(':visible')) {
864 889
                                 containerSel.show();
865 890
                             }
866 891
                             const video = stream.getVideoTracks().length > 0;
892
+
867 893
                             if (video && !$(element).is(':visible')) {
868 894
                                 throw new Error(
869 895
                                     'video element must be visible to attach'
@@ -982,6 +1008,8 @@ class RTCUtils extends Listenable {
982 1008
 
983 1009
         options = options || {};
984 1010
         const dsOptions = options.desktopSharingExtensionExternalInstallation;
1011
+
1012
+
985 1013
         return new Promise((resolve, reject) => {
986 1014
             const successCallback = function(stream) {
987 1015
                 resolve(handleLocalStream(stream, options.resolution));
@@ -1032,6 +1060,7 @@ class RTCUtils extends Listenable {
1032 1060
                 });
1033 1061
             } else {
1034 1062
                 const hasDesktop = options.devices.indexOf('desktop') > -1;
1063
+
1035 1064
                 if (hasDesktop) {
1036 1065
                     options.devices.splice(options.devices.indexOf('desktop'), 1);
1037 1066
                 }
@@ -1138,6 +1167,7 @@ class RTCUtils extends Listenable {
1138 1167
         if (!rtcReady) {
1139 1168
             throw new Error('WebRTC not ready yet');
1140 1169
         }
1170
+
1141 1171
         return Boolean(navigator.mediaDevices
1142 1172
             && navigator.mediaDevices.enumerateDevices
1143 1173
             && typeof MediaStreamTrack !== 'undefined'
@@ -1156,11 +1186,13 @@ class RTCUtils extends Listenable {
1156 1186
         if (rtcReady) {
1157 1187
             return Promise.resolve();
1158 1188
         }
1189
+
1159 1190
         return new Promise(resolve => {
1160 1191
             const listener = () => {
1161 1192
                 eventEmitter.removeListener(RTCEvents.RTC_READY, listener);
1162 1193
                 resolve();
1163 1194
             };
1195
+
1164 1196
             eventEmitter.addListener(RTCEvents.RTC_READY, listener);
1165 1197
                 // We have no failed event, so... it either resolves or nothing
1166 1198
                 // happens
@@ -1223,6 +1255,7 @@ class RTCUtils extends Listenable {
1223 1255
 
1224 1256
         // if we have done createObjectURL, lets clean it
1225 1257
         const url = mediaStream.jitsiObjectURL;
1258
+
1226 1259
         if (url) {
1227 1260
             delete mediaStream.jitsiObjectURL;
1228 1261
             (URL || webkitURL).revokeObjectURL(url);
@@ -1293,7 +1326,9 @@ class RTCUtils extends Listenable {
1293 1326
             'label':    device.label,
1294 1327
             'groupId':  device.groupId
1295 1328
         };
1329
+
1296 1330
         devices.push(deviceData);
1331
+
1297 1332
         return { deviceList: devices };
1298 1333
     }
1299 1334
 }

+ 25
- 2
modules/RTC/ScreenObtainer.js 查看文件

@@ -3,6 +3,7 @@
3 3
 const GlobalOnErrorHandler = require('../util/GlobalOnErrorHandler');
4 4
 const logger = require('jitsi-meet-logger').getLogger(__filename);
5 5
 const RTCBrowserType = require('./RTCBrowserType');
6
+
6 7
 import JitsiTrackError from '../../JitsiTrackError';
7 8
 import * as JitsiTrackErrors from '../../JitsiTrackErrors';
8 9
 
@@ -70,6 +71,7 @@ const ScreenObtainer = {
70 71
      */
71 72
     init(options, gum) {
72 73
         let obtainDesktopStream = null;
74
+
73 75
         this.options = options = options || {};
74 76
         gumFunction = gum;
75 77
 
@@ -98,6 +100,7 @@ const ScreenObtainer = {
98 100
                         // I cannot find documentation about "InvalidStateError"
99 101
                         // but this is what we are receiving from GUM when the
100 102
                         // streamId for the desktop sharing is "".
103
+
101 104
                         if (error && error.name == 'InvalidStateError') {
102 105
                             jitsiError = new JitsiTrackError(
103 106
                                 JitsiTrackErrors.CHROME_EXTENSION_USER_CANCELED
@@ -187,6 +190,7 @@ const ScreenObtainer = {
187 190
     obtainScreenOnFirefox(options, callback, errorCallback) {
188 191
         let extensionRequired = false;
189 192
         const { desktopSharingFirefoxMaxVersionExtRequired } = this.options;
193
+
190 194
         if (desktopSharingFirefoxMaxVersionExtRequired === -1
191 195
             || (desktopSharingFirefoxMaxVersionExtRequired >= 0
192 196
                 && RTCBrowserType.getFirefoxVersion()
@@ -199,6 +203,7 @@ const ScreenObtainer = {
199 203
 
200 204
         if (!extensionRequired || firefoxExtInstalled === true) {
201 205
             obtainWebRTCScreen(options, callback, errorCallback);
206
+
202 207
             return;
203 208
         }
204 209
 
@@ -220,6 +225,7 @@ const ScreenObtainer = {
220 225
                 300);
221 226
             logger.log(
222 227
                 'Waiting for detection of jidesha on firefox to finish.');
228
+
223 229
             return;
224 230
         }
225 231
 
@@ -264,7 +270,8 @@ const ScreenObtainer = {
264 270
                             .then(() => {
265 271
                                 doGetStreamFromExtension(this.options,
266 272
                                     streamCallback, failCallback);
267
-                            }).catch(() => {
273
+                            })
274
+                            .catch(() => {
268 275
                                 this.handleExtensionInstallationError(options,
269 276
                                     streamCallback, failCallback);
270 277
                             });
@@ -290,6 +297,7 @@ const ScreenObtainer = {
290 297
             options.listener('waitingForExtension', webStoreInstallUrl);
291 298
             this.checkForChromeExtensionOnInterval(options, streamCallback,
292 299
                 failCallback, e);
300
+
293 301
             return;
294 302
         }
295 303
 
@@ -306,6 +314,7 @@ const ScreenObtainer = {
306 314
         if (options.checkAgain() === false) {
307 315
             failCallback(new JitsiTrackError(
308 316
                 JitsiTrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR));
317
+
309 318
             return;
310 319
         }
311 320
         waitForExtensionAfterInstall(this.options, options.interval, 1)
@@ -314,7 +323,8 @@ const ScreenObtainer = {
314 323
                 options.listener('extensionFound');
315 324
                 this.obtainScreenFromExtension(options,
316 325
                     streamCallback, failCallback);
317
-            }).catch(() => {
326
+            })
327
+            .catch(() => {
318 328
                 this.checkForChromeExtensionOnInterval(options,
319 329
                     streamCallback, failCallback);
320 330
             });
@@ -358,6 +368,7 @@ function isUpdateRequired(minVersion, extVersion) {
358 368
         const s2 = extVersion.split('.');
359 369
 
360 370
         const len = Math.max(s1.length, s2.length);
371
+
361 372
         for (let i = 0; i < len; i++) {
362 373
             let n1 = 0,
363 374
                 n2 = 0;
@@ -382,6 +393,7 @@ function isUpdateRequired(minVersion, extVersion) {
382 393
     } catch (e) {
383 394
         GlobalOnErrorHandler.callErrorHandler(e);
384 395
         logger.error('Failed to parse extension version', e);
396
+
385 397
         return true;
386 398
     }
387 399
 }
@@ -390,6 +402,7 @@ function checkChromeExtInstalled(callback, options) {
390 402
     if (typeof chrome === 'undefined' || !chrome || !chrome.runtime) {
391 403
         // No API, so no extension for sure
392 404
         callback(false, false);
405
+
393 406
         return;
394 407
     }
395 408
     chrome.runtime.sendMessage(
@@ -401,15 +414,18 @@ function checkChromeExtInstalled(callback, options) {
401 414
                 logger.warn(
402 415
                     'Extension not installed?: ', chrome.runtime.lastError);
403 416
                 callback(false, false);
417
+
404 418
                 return;
405 419
             }
406 420
             // Check installed extension version
407 421
             const extVersion = response.version;
422
+
408 423
             logger.log(`Extension version is: ${extVersion}`);
409 424
             const updateRequired
410 425
                 = isUpdateRequired(
411 426
                     options.desktopSharingChromeMinExtVersion,
412 427
                     extVersion);
428
+
413 429
             callback(!updateRequired, updateRequired);
414 430
         }
415 431
     );
@@ -428,11 +444,13 @@ function doGetStreamFromExtension(options, streamCallback, failCallback) {
428 444
             if (!response) {
429 445
                 // possibly re-wraping error message to make code consistent
430 446
                 const lastError = chrome.runtime.lastError;
447
+
431 448
                 failCallback(lastError instanceof Error
432 449
                     ? lastError
433 450
                     : new JitsiTrackError(
434 451
                         JitsiTrackErrors.CHROME_EXTENSION_GENERIC_ERROR,
435 452
                         lastError));
453
+
436 454
                 return;
437 455
             }
438 456
             logger.log('Response from extension: ', response);
@@ -481,6 +499,7 @@ function waitForExtensionAfterInstall(options, waitInterval, retries) {
481 499
     if(retries === 0) {
482 500
         return Promise.reject();
483 501
     }
502
+
484 503
     return new Promise((resolve, reject) => {
485 504
         let currentRetries = retries;
486 505
         const interval = window.setInterval(() => {
@@ -523,6 +542,7 @@ function onGetStreamResponse(response, onSuccess, onFailure) {
523 542
         if(response.streamId === '') {
524 543
             onFailure(new JitsiTrackError(
525 544
                 JitsiTrackErrors.CHROME_EXTENSION_USER_CANCELED));
545
+
526 546
             return;
527 547
         }
528 548
 
@@ -546,10 +566,12 @@ function initFirefoxExtensionDetection(options) {
546 566
     }
547 567
     if (!options.desktopSharingFirefoxExtId) {
548 568
         firefoxExtInstalled = false;
569
+
549 570
         return;
550 571
     }
551 572
 
552 573
     const img = document.createElement('img');
574
+
553 575
     img.onload = () => {
554 576
         logger.log('Detected firefox screen sharing extension.');
555 577
         firefoxExtInstalled = true;
@@ -566,6 +588,7 @@ function initFirefoxExtensionDetection(options) {
566 588
     const src
567 589
         = `chrome://${options.desktopSharingFirefoxExtId.replace('@', '.')
568 590
             }/content/${document.location.hostname}.png`;
591
+
569 592
     img.setAttribute('src', src);
570 593
 }
571 594
 

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

@@ -46,6 +46,7 @@ function TraceablePeerConnection(rtc, id, signalingLayer, ice_config,
46 46
      * <tt>TracablePeerConnection</tt>.
47 47
      * @type {RTC}
48 48
      */
49
+
49 50
     this.rtc = rtc;
50 51
     /**
51 52
      * The peer connection identifier assigned by the RTC module.
@@ -59,6 +60,7 @@ function TraceablePeerConnection(rtc, id, signalingLayer, ice_config,
59 60
     this.signalingLayer = signalingLayer;
60 61
     this.options = options;
61 62
     let RTCPeerConnectionType = null;
63
+
62 64
     if (RTCBrowserType.isFirefox()) {
63 65
         RTCPeerConnectionType = mozRTCPeerConnection;
64 66
     } else if (RTCBrowserType.isTemasysPluginUsed()) {
@@ -75,8 +77,10 @@ function TraceablePeerConnection(rtc, id, signalingLayer, ice_config,
75 77
      */
76 78
     this.maxstats = 0;
77 79
     const Interop = require('sdp-interop').Interop;
80
+
78 81
     this.interop = new Interop();
79 82
     const Simulcast = require('sdp-simulcast');
83
+
80 84
     this.simulcast = new Simulcast({numOfLayers: SIMULCAST_LAYERS,
81 85
         explodeRemoteSimulcast: false});
82 86
     this.sdpConsistency = new SdpConsistency();
@@ -171,9 +175,11 @@ function TraceablePeerConnection(rtc, id, signalingLayer, ice_config,
171 175
             self.peerconnection.getStats(stats => {
172 176
                 const results = stats.result();
173 177
                 const now = new Date();
178
+
174 179
                 for (let i = 0; i < results.length; ++i) {
175 180
                     results[i].names().forEach(name => {
176 181
                         const id = `${results[i].id}-${name}`;
182
+
177 183
                         if (!self.stats[id]) {
178 184
                             self.stats[id] = {
179 185
                                 startTime: now,
@@ -216,6 +222,7 @@ TraceablePeerConnection.prototype._remoteStreamAdded = function(stream) {
216 222
     if (!RTC.isUserStream(stream)) {
217 223
         logger.info(
218 224
             'Ignored remote \'stream added\' event for non-user stream', stream);
225
+
219 226
         return;
220 227
     }
221 228
     // Bind 'addtrack'/'removetrack' event handlers
@@ -230,10 +237,12 @@ TraceablePeerConnection.prototype._remoteStreamAdded = function(stream) {
230 237
     }
231 238
     // Call remoteTrackAdded for each track in the stream
232 239
     const streamAudioTracks = stream.getAudioTracks();
240
+
233 241
     for (const audioTrack of streamAudioTracks) {
234 242
         this._remoteTrackAdded(stream, audioTrack);
235 243
     }
236 244
     const streamVideoTracks = stream.getVideoTracks();
245
+
237 246
     for (const videoTrack of streamVideoTracks) {
238 247
         this._remoteTrackAdded(stream, videoTrack);
239 248
     }
@@ -261,6 +270,7 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
261 270
             new Error(
262 271
                 `MediaType undefined for remote track, stream id: ${streamId}`
263 272
             ));
273
+
264 274
         // Abort
265 275
         return;
266 276
     }
@@ -269,11 +279,13 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
269 279
     const mediaLines
270 280
         = remoteSDP.media.filter(
271 281
             mediaLines => mediaLines.startsWith(`m=${mediaType}`));
282
+
272 283
     if (!mediaLines.length) {
273 284
         GlobalOnErrorHandler.callErrorHandler(
274 285
             new Error(
275 286
                 `No media lines for type ${mediaType
276 287
                      } found in remote SDP for remote track: ${streamId}`));
288
+
277 289
         // Abort
278 290
         return;
279 291
     }
@@ -284,6 +296,8 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
284 296
         line => {
285 297
             const msid
286 298
                 = RTCBrowserType.isTemasysPluginUsed() ? 'mslabel' : 'msid';
299
+
300
+
287 301
             return line.indexOf(`${msid}:${streamId}`) !== -1;
288 302
         });
289 303
     if (!ssrcLines.length) {
@@ -291,6 +305,7 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
291 305
             new Error(
292 306
                 `No SSRC lines for streamId ${streamId
293 307
                      } for remote track, media type: ${mediaType}`));
308
+
294 309
         // Abort
295 310
         return;
296 311
     }
@@ -306,6 +321,7 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
306 321
                 `No SSRC owner known for: ${trackSsrc
307 322
                      } for remote track, msid: ${streamId
308 323
                      } media type: ${mediaType}`));
324
+
309 325
         // Abort
310 326
         return;
311 327
     }
@@ -318,6 +334,7 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
318 334
     if (!peerMediaInfo) {
319 335
         GlobalOnErrorHandler.callErrorHandler(
320 336
             new Error(`No peer media info available for: ${ownerEndpointId}`));
337
+
321 338
         // Abort
322 339
         return;
323 340
     }
@@ -337,16 +354,20 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
337 354
 TraceablePeerConnection.prototype._remoteStreamRemoved = function(stream) {
338 355
     if (!RTC.isUserStream(stream)) {
339 356
         const id = RTC.getStreamID(stream);
357
+
340 358
         logger.info(
341 359
             `Ignored remote 'stream removed' event for non-user stream ${id}`);
360
+
342 361
         return;
343 362
     }
344 363
     // Call remoteTrackRemoved for each track in the stream
345 364
     const streamVideoTracks = stream.getVideoTracks();
365
+
346 366
     for (const videoTrack of streamVideoTracks) {
347 367
         this._remoteTrackRemoved(stream, videoTrack);
348 368
     }
349 369
     const streamAudioTracks = stream.getAudioTracks();
370
+
350 371
     for (const audioTrack of streamAudioTracks) {
351 372
         this._remoteTrackRemoved(stream, audioTrack);
352 373
     }
@@ -369,6 +390,7 @@ TraceablePeerConnection.prototype._remoteTrackRemoved
369 390
     if (!streamId) {
370 391
         GlobalOnErrorHandler.callErrorHandler(
371 392
             new Error('Remote track removal failed - no stream ID'));
393
+
372 394
         // Abort
373 395
         return;
374 396
     }
@@ -376,6 +398,7 @@ TraceablePeerConnection.prototype._remoteTrackRemoved
376 398
     if (!trackId) {
377 399
         GlobalOnErrorHandler.callErrorHandler(
378 400
             new Error('Remote track removal failed - no track ID'));
401
+
379 402
         // Abort
380 403
         return;
381 404
     }
@@ -427,6 +450,7 @@ function extractSSRCMap(desc) {
427 450
     if (typeof desc !== 'object' || desc === null
428 451
         || typeof desc.sdp !== 'string') {
429 452
         logger.warn('An empty description was passed as an argument.');
453
+
430 454
         return ssrcMap;
431 455
     }
432 456
 
@@ -451,6 +475,7 @@ function extractSSRCMap(desc) {
451 475
                                      .map(ssrcStr => parseInt(ssrcStr));
452 476
                     const primarySSRC = groupSSRCs[0];
453 477
                     // Note that group.semantics is already present
478
+
454 479
                     group.ssrcs = groupSSRCs;
455 480
                     if (!groupsMap.has(primarySSRC)) {
456 481
                         groupsMap.set(primarySSRC, []);
@@ -500,6 +525,7 @@ const normalizePlanB = function(desc) {
500 525
     if (typeof desc !== 'object' || desc === null
501 526
         || typeof desc.sdp !== 'string') {
502 527
         logger.warn('An empty description was passed as an argument.');
528
+
503 529
         return desc;
504 530
     }
505 531
 
@@ -534,6 +560,7 @@ const normalizePlanB = function(desc) {
534 560
 
535 561
             if (Array.isArray(mLine.ssrcs)) {
536 562
                 let i;
563
+
537 564
                 for (i = 0; i < mLine.ssrcs.length; i++) {
538 565
                     if (typeof mLine.ssrcs[i] === 'object'
539 566
                         && typeof mLine.ssrcs[i].id !== 'undefined'
@@ -555,6 +582,8 @@ const normalizePlanB = function(desc) {
555 582
     }
556 583
 
557 584
     const resStr = transform.write(session);
585
+
586
+
558 587
     return new RTCSessionDescription({
559 588
         type: desc.type,
560 589
         sdp: resStr
@@ -579,10 +608,12 @@ const getters = {
579 608
             this.trace('getLocalDescription::postTransform (Plan B)',
580 609
                 dumpSDP(desc));
581 610
         }
611
+
582 612
         return desc;
583 613
     },
584 614
     remoteDescription() {
585 615
         let desc = this.peerconnection.remoteDescription;
616
+
586 617
         this.trace('getRemoteDescription::preTransform', dumpSDP(desc));
587 618
 
588 619
         // if we're running on FF, transform to Plan B first.
@@ -591,9 +622,11 @@ const getters = {
591 622
             this.trace(
592 623
                 'getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));
593 624
         }
625
+
594 626
         return desc;
595 627
     }
596 628
 };
629
+
597 630
 Object.keys(getters).forEach(prop => {
598 631
     Object.defineProperty(
599 632
         TraceablePeerConnection.prototype,
@@ -612,17 +645,21 @@ TraceablePeerConnection.prototype.addStream = function(stream, ssrcInfo) {
612 645
         this.sdpConsistency.setPrimarySsrc(ssrcInfo.ssrcs[0]);
613 646
         const simGroup
614 647
             = ssrcInfo.groups.find(groupInfo => groupInfo.semantics === 'SIM');
648
+
615 649
         if (simGroup) {
616 650
             this.simulcast.setSsrcCache(simGroup.ssrcs);
617 651
         }
618 652
         const fidGroups
619 653
             = ssrcInfo.groups.filter(
620 654
                 groupInfo => groupInfo.semantics === 'FID');
655
+
621 656
         if (fidGroups) {
622 657
             const rtxSsrcMapping = new Map();
658
+
623 659
             fidGroups.forEach(fidGroup => {
624 660
                 const primarySsrc = fidGroup.ssrcs[0];
625 661
                 const rtxSsrc = fidGroup.ssrcs[1];
662
+
626 663
                 rtxSsrcMapping.set(primarySsrc, rtxSsrc);
627 664
             });
628 665
             this.rtxModifier.setSsrcCache(rtxSsrcMapping);
@@ -640,6 +677,7 @@ TraceablePeerConnection.prototype.removeStream = function(stream) {
640 677
 
641 678
 TraceablePeerConnection.prototype.createDataChannel = function(label, opts) {
642 679
     this.trace('createDataChannel', label, opts);
680
+
643 681
     return this.peerconnection.createDataChannel(label, opts);
644 682
 };
645 683
 
@@ -654,6 +692,7 @@ TraceablePeerConnection.prototype.setLocalDescription
654 692
             }
655 693
 
656 694
             const self = this;
695
+
657 696
             this.peerconnection.setLocalDescription(description,
658 697
         () => {
659 698
             self.trace('setLocalDescriptionOnSuccess');
@@ -681,6 +720,7 @@ TraceablePeerConnection.prototype.setRemoteDescription
681 720
             if (this.options.preferH264) {
682 721
                 const parsedSdp = transform.parse(description.sdp);
683 722
                 const videoMLine = parsedSdp.media.find(m => m.type === 'video');
723
+
684 724
                 SDPUtil.preferVideoCodec(videoMLine, 'h264');
685 725
                 description.sdp = transform.write(parsedSdp);
686 726
             }
@@ -700,6 +740,7 @@ TraceablePeerConnection.prototype.setRemoteDescription
700 740
             }
701 741
 
702 742
             const self = this;
743
+
703 744
             this.peerconnection.setRemoteDescription(description,
704 745
         () => {
705 746
             self.trace('setRemoteDescriptionOnSuccess');
@@ -727,6 +768,7 @@ TraceablePeerConnection.prototype.setRemoteDescription
727 768
 TraceablePeerConnection.prototype.generateRecvonlySsrc = function() {
728 769
     // FIXME replace with SDPUtil.generateSsrc (when it's added)
729 770
     const newSSRC = this.generateNewStreamSSRCInfo().ssrcs[0];
771
+
730 772
     logger.info(`Generated new recvonly SSRC: ${newSSRC}`);
731 773
     this.sdpConsistency.setPrimarySsrc(newSSRC);
732 774
 };
@@ -865,6 +907,7 @@ TraceablePeerConnection.prototype.createAnswer
865 907
                 //  details)
866 908
                 const remoteDescription = new SDP(this.remoteDescription.sdp);
867 909
                 const localDescription = new SDP(answer.sdp);
910
+
868 911
                 _fixAnswerRFC4145Setup(remoteDescription, localDescription);
869 912
                 answer.sdp = localDescription.raw;
870 913
 
@@ -933,6 +976,7 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) {
933 976
  */
934 977
 TraceablePeerConnection.prototype.generateNewStreamSSRCInfo = function() {
935 978
     let ssrcInfo = {ssrcs: [], groups: []};
979
+
936 980
     if (!this.options.disableSimulcast
937 981
         && this.simulcast.isSupported()) {
938 982
         for (let i = 0; i < SIMULCAST_LAYERS; i++) {
@@ -954,9 +998,11 @@ TraceablePeerConnection.prototype.generateNewStreamSSRCInfo = function() {
954 998
         //  only want to iterate through the items originally
955 999
         //  on the list
956 1000
         const currNumSsrcs = ssrcInfo.ssrcs.length;
1001
+
957 1002
         for (let i = 0; i < currNumSsrcs; ++i) {
958 1003
             const primarySsrc = ssrcInfo.ssrcs[i];
959 1004
             const rtxSsrc = SDPUtil.generateSsrc();
1005
+
960 1006
             ssrcInfo.ssrcs.push(rtxSsrc);
961 1007
             ssrcInfo.groups.push({
962 1008
                 ssrcs: [primarySsrc, rtxSsrc],
@@ -964,6 +1010,7 @@ TraceablePeerConnection.prototype.generateNewStreamSSRCInfo = function() {
964 1010
             });
965 1011
         }
966 1012
     }
1013
+
967 1014
     return ssrcInfo;
968 1015
 };
969 1016
 

+ 7
- 0
modules/connectivity/ConnectionQuality.js 查看文件

@@ -54,6 +54,7 @@ function getTarget(simulcast, resolution, millisSinceStart) {
54 54
     if (simulcast) {
55 55
         // Find the first format with height no bigger than ours.
56 56
         let simulcastFormat = kSimulcastFormats.find(f => f.height <= height);
57
+
57 58
         if (simulcastFormat) {
58 59
             // Sum the target fields from all simulcast layers for the given
59 60
             // resolution (e.g. 720p + 360p + 180p).
@@ -71,6 +72,7 @@ function getTarget(simulcast, resolution, millisSinceStart) {
71 72
         // See GetMaxDefaultVideoBitrateKbps in
72 73
         // media/engine/webrtcvideoengine2.cc from webrtc.org
73 74
         const pixels = resolution.width * resolution.height;
75
+
74 76
         if (pixels <= 320 * 240) {
75 77
             target = 600;
76 78
         } else if (pixels <= 640 * 480) {
@@ -97,6 +99,7 @@ function rampUp(millisSinceStart) {
97 99
     if (millisSinceStart > 60000) {
98 100
         return Number.MAX_SAFE_INTEGER;
99 101
     }
102
+
100 103
     // According to GCC the send side bandwidth estimation grows with at most
101 104
     // 8% per second.
102 105
     // https://tools.ietf.org/html/draft-ietf-rmcat-gcc-02#section-5.5
@@ -252,6 +255,7 @@ export default class ConnectionQuality {
252 255
         let quality = 100;
253 256
         let packetLoss;
254 257
         // TODO: take into account packet loss for received streams
258
+
255 259
         if (this._localStats.packetLoss) {
256 260
             packetLoss = this._localStats.packetLoss.upload;
257 261
 
@@ -306,6 +310,7 @@ export default class ConnectionQuality {
306 310
             // expected sending bitrate in perfect conditions
307 311
             let target
308 312
                 = getTarget(this._simulcast, resolution, millisSinceStart);
313
+
309 314
             target = 0.9 * target;
310 315
 
311 316
             quality = 100 * this._localStats.bitrate.upload / target;
@@ -323,6 +328,7 @@ export default class ConnectionQuality {
323 328
             const diffSeconds
324 329
                 = (window.performance.now() - this._lastConnectionQualityUpdate)
325 330
                     / 1000;
331
+
326 332
             quality
327 333
                 = Math.min(
328 334
                     quality,
@@ -359,6 +365,7 @@ export default class ConnectionQuality {
359 365
         // resolution instead. Consider removing this.
360 366
         const localVideoTrack
361 367
             = this._conference.getLocalVideoTrack();
368
+
362 369
         if (localVideoTrack && localVideoTrack.resolution) {
363 370
             data.resolution = localVideoTrack.resolution;
364 371
         }

+ 4
- 0
modules/connectivity/ParticipantConnectionStatus.js 查看文件

@@ -321,6 +321,7 @@ export default class ParticipantConnectionStatus {
321 321
      */
322 322
     figureOutConnectionStatus(id) {
323 323
         const participant = this.conference.getParticipantById(id);
324
+
324 325
         if (!participant) {
325 326
             // Probably the participant is no longer in the conference
326 327
             // (at the time of writing this code, participant is
@@ -329,6 +330,7 @@ export default class ParticipantConnectionStatus {
329 330
             // so we don't care, but let's print the warning for
330 331
             // debugging purpose
331 332
             logger.warn(`figure out conn status - no participant for: ${id}`);
333
+
332 334
             return;
333 335
         }
334 336
 
@@ -364,9 +366,11 @@ export default class ParticipantConnectionStatus {
364 366
     onTrackRtcMuted(track) {
365 367
         const participantId = track.getParticipantId();
366 368
         const participant = this.conference.getParticipantById(participantId);
369
+
367 370
         logger.debug(`Detector track RTC muted: ${participantId}`);
368 371
         if (!participant) {
369 372
             logger.error(`No participant for id: ${participantId}`);
373
+
370 374
             return;
371 375
         }
372 376
         this.rtcMutedTimestamp[participantId] = Date.now();

+ 9
- 0
modules/settings/Settings.js 查看文件

@@ -11,6 +11,8 @@ import UsernameGenerator from '../util/UsernameGenerator';
11 11
  */
12 12
 function getLocalStorage() {
13 13
     const global = typeof window == 'undefined' ? this : window;
14
+
15
+
14 16
     return global.localStorage;
15 17
 }
16 18
 
@@ -28,6 +30,7 @@ function generateUniqueId() {
28 30
  */
29 31
 function generateJitsiMeetId() {
30 32
     const jitsiMeetId = generateUniqueId();
33
+
31 34
     logger.log('generated id', jitsiMeetId);
32 35
 
33 36
     return jitsiMeetId;
@@ -39,6 +42,7 @@ function generateJitsiMeetId() {
39 42
  */
40 43
 function generateCallStatsUsername() {
41 44
     const username = UsernameGenerator.generateUsername();
45
+
42 46
     logger.log('generated callstats uid', username);
43 47
 
44 48
     return username;
@@ -50,6 +54,7 @@ class Settings {
50 54
         this.callStatsUserName;
51 55
 
52 56
         const localStorage = getLocalStorage();
57
+
53 58
         if (localStorage) {
54 59
             this.userId
55 60
                 = localStorage.getItem('jitsiMeetId') || generateJitsiMeetId();
@@ -70,6 +75,7 @@ class Settings {
70 75
      */
71 76
     save() {
72 77
         const localStorage = getLocalStorage();
78
+
73 79
         if (localStorage) {
74 80
             localStorage.setItem('jitsiMeetId', this.userId);
75 81
             localStorage.setItem('callStatsUserName', this.callStatsUserName);
@@ -98,6 +104,7 @@ class Settings {
98 104
      */
99 105
     setSessionId(sessionId) {
100 106
         const localStorage = getLocalStorage();
107
+
101 108
         if (localStorage) {
102 109
             if (sessionId) {
103 110
                 localStorage.setItem('sessionId', sessionId);
@@ -122,6 +129,8 @@ class Settings {
122 129
         // We may update sessionId in localStorage from another JitsiConference
123 130
         // instance and that's why we should always re-read it.
124 131
         const localStorage = getLocalStorage();
132
+
133
+
125 134
         return localStorage ? localStorage.getItem('sessionId') : undefined;
126 135
     }
127 136
 }

+ 3
- 0
modules/statistics/AnalyticsAdapter.js 查看文件

@@ -35,7 +35,9 @@ class CacheAnalytics extends AnalyticsAbstract {
35 35
      */
36 36
     drainCachedEvents() {
37 37
         const eventCacheCopy = this.eventCache.slice();
38
+
38 39
         this.eventCache = [];
40
+
39 41
         return eventCacheCopy;
40 42
     }
41 43
 
@@ -74,6 +76,7 @@ class AnalyticsAdapter {
74 76
     sendEvent(action, data = {}) {
75 77
         const modifiedData = Object.assign(
76 78
             {browserName: this.browserName}, this.permanentProperties, data);
79
+
77 80
         this.analyticsHandlers.forEach(
78 81
             analytics => analytics.sendEvent(action, modifiedData));
79 82
     }

+ 6
- 0
modules/statistics/CallStats.js 查看文件

@@ -1,6 +1,7 @@
1 1
 /* global $, Strophe, callstats */
2 2
 const logger = require('jitsi-meet-logger').getLogger(__filename);
3 3
 const GlobalOnErrorHandler = require('../util/GlobalOnErrorHandler');
4
+
4 5
 import Settings from '../settings/Settings';
5 6
 
6 7
 const jsSHA = require('jssha');
@@ -62,6 +63,7 @@ function initCallback(err, msg) {
62 63
     // there is no lib, nothing to report to
63 64
     if (err !== 'success') {
64 65
         CallStats.initializeFailed = true;
66
+
65 67
         return;
66 68
     }
67 69
 
@@ -76,6 +78,7 @@ function initCallback(err, msg) {
76 78
     if(!fabricInitialized) {
77 79
         CallStats.initializeFailed = true;
78 80
         logger.log('callstats fabric not initilized', ret.message);
81
+
79 82
         return;
80 83
     }
81 84
 
@@ -88,6 +91,7 @@ function initCallback(err, msg) {
88 91
         CallStats.reportsQueue.forEach(function(report) {
89 92
             if (report.type === reportType.ERROR) {
90 93
                 const error = report.data;
94
+
91 95
                 CallStats._reportError.call(this, error.type, error.error,
92 96
                     error.pc);
93 97
             } else if (report.type === reportType.EVENT
@@ -95,6 +99,7 @@ function initCallback(err, msg) {
95 99
                 // if we have and event to report and we failed to add fabric
96 100
                 // this event will not be reported anyway, returning an error
97 101
                 const eventData = report.data;
102
+
98 103
                 callStats.sendFabricEvent(
99 104
                     this.peerconnection,
100 105
                     eventData.event,
@@ -102,6 +107,7 @@ function initCallback(err, msg) {
102 107
                     eventData.eventData);
103 108
             } else if (report.type === reportType.MST_WITH_USERID) {
104 109
                 const data = report.data;
110
+
105 111
                 callStats.associateMstWithUserID(
106 112
                     this.peerconnection,
107 113
                     data.callStatsId,

+ 5
- 0
modules/statistics/LocalStatsCollector.js 查看文件

@@ -63,6 +63,7 @@ function timeDomainDataToAudioLevel(samples) {
63 63
 function animateLevel(newLevel, lastLevel) {
64 64
     let value = 0;
65 65
     const diff = lastLevel - newLevel;
66
+
66 67
     if(diff > 0.2) {
67 68
         value = lastLevel - 0.2;
68 69
     } else if(diff < -0.4) {
@@ -101,10 +102,12 @@ LocalStatsCollector.prototype.start = function() {
101 102
     }
102 103
     context.resume();
103 104
     const analyser = context.createAnalyser();
105
+
104 106
     analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;
105 107
     analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;
106 108
 
107 109
     const source = context.createMediaStreamSource(this.stream);
110
+
108 111
     source.connect(analyser);
109 112
 
110 113
 
@@ -113,8 +116,10 @@ LocalStatsCollector.prototype.start = function() {
113 116
     this.intervalId = setInterval(
114 117
         () => {
115 118
             const array = new Uint8Array(analyser.frequencyBinCount);
119
+
116 120
             analyser.getByteTimeDomainData(array);
117 121
             const audioLevel = timeDomainDataToAudioLevel(array);
122
+
118 123
             if (audioLevel != self.audioLevel) {
119 124
                 self.audioLevel = animateLevel(audioLevel, self.audioLevel);
120 125
                 self.callback(self.audioLevel);

+ 31
- 0
modules/statistics/RTPStatsCollector.js 查看文件

@@ -3,6 +3,7 @@
3 3
 const GlobalOnErrorHandler = require('../util/GlobalOnErrorHandler');
4 4
 const logger = require('jitsi-meet-logger').getLogger(__filename);
5 5
 const RTCBrowserType = require('../RTC/RTCBrowserType');
6
+
6 7
 import * as StatisticsEvents from '../../service/statistics/Events';
7 8
 
8 9
 /* Whether we support the browser we are running into for logging statistics */
@@ -15,6 +16,7 @@ const browserSupported = RTCBrowserType.isChrome()
15 16
  * by RTCPeerConnection#getStats mapped by RTCBrowserType.
16 17
  */
17 18
 const KEYS_BY_BROWSER_TYPE = {};
19
+
18 20
 KEYS_BY_BROWSER_TYPE[RTCBrowserType.RTC_BROWSER_FIREFOX] = {
19 21
     'ssrc': 'ssrc',
20 22
     'packetsReceived': 'packetsReceived',
@@ -67,6 +69,7 @@ function calculatePacketLoss(lostPackets, totalPackets) {
67 69
     if(!totalPackets || totalPackets <= 0 || !lostPackets || lostPackets <= 0) {
68 70
         return 0;
69 71
     }
72
+
70 73
     return Math.round((lostPackets / totalPackets) * 100);
71 74
 }
72 75
 
@@ -180,6 +183,7 @@ function StatsCollector(
180 183
      */
181 184
     this._browserType = RTCBrowserType.getBrowserType();
182 185
     const keys = KEYS_BY_BROWSER_TYPE[this._browserType];
186
+
183 187
     if (!keys) {
184 188
         throw `The browser type '${this._browserType}' isn't supported!`;
185 189
     }
@@ -242,6 +246,7 @@ StatsCollector.prototype.errorCallback = function(error) {
242 246
  */
243 247
 StatsCollector.prototype.start = function(startAudioLevelStats) {
244 248
     const self = this;
249
+
245 250
     if(startAudioLevelStats) {
246 251
         this.audioLevelsIntervalId = setInterval(
247 252
             () => {
@@ -249,6 +254,7 @@ StatsCollector.prototype.start = function(startAudioLevelStats) {
249 254
                 self.peerconnection.getStats(
250 255
                     report => {
251 256
                         let results = null;
257
+
252 258
                         if (!report || !report.result
253 259
                             || typeof report.result != 'function') {
254 260
                             results = report;
@@ -274,6 +280,7 @@ StatsCollector.prototype.start = function(startAudioLevelStats) {
274 280
                 self.peerconnection.getStats(
275 281
                     report => {
276 282
                         let results = null;
283
+
277 284
                         if (!report || !report.result
278 285
                             || typeof report.result != 'function') {
279 286
                             // firefox
@@ -314,6 +321,7 @@ StatsCollector.prototype._defineGetStatValueMethod = function(keys) {
314 321
     // RTCPeerConnection#getStats.
315 322
     const keyFromName = function(name) {
316 323
         const key = keys[name];
324
+
317 325
         if (key) {
318 326
             return key;
319 327
         }
@@ -325,6 +333,7 @@ StatsCollector.prototype._defineGetStatValueMethod = function(keys) {
325 333
     // returned by RTCPeerConnection#getStats associated with a given
326 334
     // browser-specific key.
327 335
     let itemStatByKey;
336
+
328 337
     switch (this._browserType) {
329 338
     case RTCBrowserType.RTC_BROWSER_CHROME:
330 339
     case RTCBrowserType.RTC_BROWSER_OPERA:
@@ -345,14 +354,18 @@ StatsCollector.prototype._defineGetStatValueMethod = function(keys) {
345 354
         // Array in which each element is a key-value pair.
346 355
         itemStatByKey = function(item, key) {
347 356
             let value;
357
+
348 358
             item.values.some(pair => {
349 359
                 if (pair.hasOwnProperty(key)) {
350 360
                     value = pair[key];
361
+
351 362
                     return true;
352 363
                 }
364
+
353 365
                 return false;
354 366
 
355 367
             });
368
+
356 369
             return value;
357 370
         };
358 371
         break;
@@ -379,8 +392,10 @@ StatsCollector.prototype.processStatsReport = function() {
379 392
     }
380 393
 
381 394
     const getStatValue = this._getStatValue;
395
+
382 396
     function getNonNegativeStat(report, name) {
383 397
         let value = getStatValue(report, name);
398
+
384 399
         if (typeof value !== 'number') {
385 400
             value = Number(value);
386 401
         }
@@ -398,9 +413,11 @@ StatsCollector.prototype.processStatsReport = function() {
398 413
             continue;
399 414
         }
400 415
         const now = this.currentStatsReport[idx];
416
+
401 417
         try {
402 418
             const receiveBandwidth = getStatValue(now, 'receiveBandwidth');
403 419
             const sendBandwidth = getStatValue(now, 'sendBandwidth');
420
+
404 421
             if (receiveBandwidth || sendBandwidth) {
405 422
                 this.conferenceStats.bandwidth = {
406 423
                     'download': Math.round(receiveBandwidth / 1000),
@@ -411,6 +428,7 @@ StatsCollector.prototype.processStatsReport = function() {
411 428
 
412 429
         if(now.type == 'googCandidatePair') {
413 430
             let active, ip, localip, type;
431
+
414 432
             try {
415 433
                 ip = getStatValue(now, 'remoteAddress');
416 434
                 type = getStatValue(now, 'transportType');
@@ -422,6 +440,7 @@ StatsCollector.prototype.processStatsReport = function() {
422 440
             }
423 441
             // Save the address unless it has been saved already.
424 442
             const conferenceStatsTransport = this.conferenceStats.transport;
443
+
425 444
             if(!conferenceStatsTransport.some(
426 445
                     t =>
427 446
                         t.ip == ip && t.type == type && t.localip == localip)) {
@@ -437,6 +456,7 @@ StatsCollector.prototype.processStatsReport = function() {
437 456
 
438 457
             const local = this.currentStatsReport[now.localCandidateId];
439 458
             const remote = this.currentStatsReport[now.remoteCandidateId];
459
+
440 460
             this.conferenceStats.transport.push({
441 461
                 ip: `${remote.ipAddress}:${remote.portNumber}`,
442 462
                 type: local.transport,
@@ -451,6 +471,7 @@ StatsCollector.prototype.processStatsReport = function() {
451 471
 
452 472
         const before = this.previousStatsReport[idx];
453 473
         const ssrc = getStatValue(now, 'ssrc');
474
+
454 475
         if (!before || !ssrc) {
455 476
             continue;
456 477
         }
@@ -461,6 +482,7 @@ StatsCollector.prototype.processStatsReport = function() {
461 482
         let isDownloadStream = true;
462 483
         let key = 'packetsReceived';
463 484
         let packetsNow = getStatValue(now, key);
485
+
464 486
         if (typeof packetsNow === 'undefined'
465 487
             || packetsNow === null || packetsNow === '') {
466 488
             isDownloadStream = false;
@@ -496,6 +518,7 @@ StatsCollector.prototype.processStatsReport = function() {
496 518
 
497 519
         // TODO: clean this mess up!
498 520
         let nowBytesTransmitted = getStatValue(now, 'bytesSent');
521
+
499 522
         if(typeof nowBytesTransmitted === 'number'
500 523
             || typeof nowBytesTransmitted === 'string') {
501 524
             nowBytesTransmitted = Number(nowBytesTransmitted);
@@ -511,6 +534,7 @@ StatsCollector.prototype.processStatsReport = function() {
511 534
 
512 535
         const timeMs = now.timestamp - before.timestamp;
513 536
         let bitrateReceivedKbps = 0, bitrateSentKbps = 0;
537
+
514 538
         if (timeMs > 0) {
515 539
             // TODO is there any reason to round here?
516 540
             bitrateReceivedKbps = Math.round((bytesReceived * 8) / timeMs);
@@ -523,8 +547,10 @@ StatsCollector.prototype.processStatsReport = function() {
523 547
         });
524 548
 
525 549
         const resolution = {height: null, width: null};
550
+
526 551
         try {
527 552
             let height, width;
553
+
528 554
             if ((height = getStatValue(now, 'googFrameHeightReceived'))
529 555
                 && (width = getStatValue(now, 'googFrameWidthReceived'))) {
530 556
                 resolution.height = height;
@@ -555,12 +581,14 @@ StatsCollector.prototype.processStatsReport = function() {
555 581
     let bitrateDownload = 0;
556 582
     let bitrateUpload = 0;
557 583
     const resolutions = {};
584
+
558 585
     Object.keys(this.ssrc2stats).forEach(
559 586
         function(ssrc) {
560 587
             const ssrcStats = this.ssrc2stats[ssrc];
561 588
             // process packet loss stats
562 589
             const loss = ssrcStats.loss;
563 590
             const type = loss.isDownloadStream ? 'download' : 'upload';
591
+
564 592
             totalPackets[type] += loss.packetsTotal;
565 593
             lostPackets[type] += loss.packetsLost;
566 594
 
@@ -616,12 +644,14 @@ StatsCollector.prototype.processAudioLevelReport = function() {
616 644
         }
617 645
 
618 646
         const now = this.currentAudioLevelsReport[idx];
647
+
619 648
         if (now.type != 'ssrc') {
620 649
             continue;
621 650
         }
622 651
 
623 652
         const before = this.baselineAudioLevelsReport[idx];
624 653
         const ssrc = getStatValue(now, 'ssrc');
654
+
625 655
         if (!before) {
626 656
             logger.warn(`${ssrc} not enough data`);
627 657
             continue;
@@ -644,6 +674,7 @@ StatsCollector.prototype.processAudioLevelReport = function() {
644 674
         } catch(e) {/* not supported*/
645 675
             logger.warn('Audio Levels are not available in the statistics.');
646 676
             clearInterval(this.audioLevelsIntervalId);
677
+
647 678
             return;
648 679
         }
649 680
 

+ 5
- 0
modules/statistics/statistics.js 查看文件

@@ -2,11 +2,13 @@
2 2
 import analytics from './AnalyticsAdapter';
3 3
 const CallStats = require('./CallStats');
4 4
 const EventEmitter = require('events');
5
+
5 6
 import JitsiTrackError from '../../JitsiTrackError';
6 7
 const logger = require('jitsi-meet-logger').getLogger(__filename);
7 8
 const LocalStats = require('./LocalStatsCollector.js');
8 9
 const RTPStats = require('./RTPStatsCollector.js');
9 10
 const ScriptUtil = require('../util/ScriptUtil');
11
+
10 12
 import * as StatisticsEvents from '../../service/statistics/Events';
11 13
 
12 14
 /**
@@ -130,6 +132,7 @@ Statistics.startLocalStats = function(stream, callback) {
130 132
     }
131 133
     const localStats = new LocalStats(stream, Statistics.audioLevelsInterval,
132 134
         callback);
135
+
133 136
     this.localStats.push(localStats);
134 137
     localStats.start();
135 138
 };
@@ -193,6 +196,7 @@ Statistics.stopLocalStats = function(stream) {
193 196
     for(let i = 0; i < Statistics.localStats.length; i++) {
194 197
         if(Statistics.localStats[i].stream === stream) {
195 198
             const localStats = Statistics.localStats.splice(i, 1);
199
+
196 200
             localStats[0].stop();
197 201
             break;
198 202
         }
@@ -230,6 +234,7 @@ Statistics.prototype.startCallStats = function(session) {
230 234
 Statistics.prototype.stopCallStats = function() {
231 235
     if(this.callStatsStarted) {
232 236
         const index = Statistics.callsStatsInstances.indexOf(this.callstats);
237
+
233 238
         if(index > -1) {
234 239
             Statistics.callsStatsInstances.splice(index, 1);
235 240
         }

+ 10
- 0
modules/transcription/audioRecorder.js 查看文件

@@ -65,6 +65,7 @@ function instantiateTrackRecorder(track) {
65 65
     // Create a new stream which only holds the audio track
66 66
     const originalStream = trackRecorder.track.getOriginalStream();
67 67
     const stream = createEmptyStream();
68
+
68 69
     originalStream.getAudioTracks().forEach(track => stream.addTrack(track));
69 70
     // Create the MediaRecorder
70 71
     trackRecorder.recorder = new MediaRecorder(stream,
@@ -133,6 +134,7 @@ audioRecorder.prototype.addTrack = function(track) {
133 134
         // create the track recorder
134 135
         const trackRecorder = instantiateTrackRecorder(track);
135 136
         // push it to the local array of all recorders
137
+
136 138
         this.recorders.push(trackRecorder);
137 139
         // update the name of the trackRecorders
138 140
         this.updateNames();
@@ -161,9 +163,11 @@ audioRecorder.prototype.removeTrack = function(track) {
161 163
 
162 164
     const array = this.recorders;
163 165
     let i;
166
+
164 167
     for(i = 0; i < array.length; i++) {
165 168
         if(array[i].track.getParticipantId() === track.getParticipantId()) {
166 169
             const recorderToRemove = array[i];
170
+
167 171
             if(this.isRecording) {
168 172
                 stopRecorder(recorderToRemove);
169 173
             } else {
@@ -184,6 +188,7 @@ audioRecorder.prototype.removeTrack = function(track) {
184 188
  */
185 189
 audioRecorder.prototype.updateNames = function() {
186 190
     const conference = this.jitsiConference;
191
+
187 192
     this.recorders.forEach(trackRecorder => {
188 193
         if(trackRecorder.track.isLocal()) {
189 194
             trackRecorder.name = 'the transcriber';
@@ -191,6 +196,7 @@ audioRecorder.prototype.updateNames = function() {
191 196
             const id = trackRecorder.track.getParticipantId();
192 197
             const participant = conference.getParticipantById(id);
193 198
             const newName = participant.getDisplayName();
199
+
194 200
             if(newName !== 'undefined') {
195 201
                 trackRecorder.name = newName;
196 202
             }
@@ -232,10 +238,12 @@ audioRecorder.prototype.stop = function() {
232 238
  */
233 239
 audioRecorder.prototype.download = function() {
234 240
     const t = this;
241
+
235 242
     this.recorders.forEach(trackRecorder => {
236 243
         const blob = new Blob(trackRecorder.data, {type: t.fileType});
237 244
         const url = URL.createObjectURL(blob);
238 245
         const a = document.createElement('a');
246
+
239 247
         document.body.appendChild(a);
240 248
         a.style = 'display: none';
241 249
         a.href = url;
@@ -260,6 +268,7 @@ audioRecorder.prototype.getRecordingResults = function() {
260 268
 
261 269
     const array = [];
262 270
     const t = this;
271
+
263 272
     this.recorders.forEach(
264 273
           recorder =>
265 274
               array.push(
@@ -267,6 +276,7 @@ audioRecorder.prototype.getRecordingResults = function() {
267 276
                       new Blob(recorder.data, {type: t.fileType}),
268 277
                       recorder.name,
269 278
                       recorder.startTime)));
279
+
270 280
     return array;
271 281
 };
272 282
 

+ 10
- 0
modules/transcription/transcriber.js 查看文件

@@ -79,6 +79,7 @@ transcriber.prototype.stop = function stop(callback) {
79 79
     const t = this;
80 80
 
81 81
     const callBack = blobCallBack.bind(this);
82
+
82 83
     this.audioRecorder.getRecordingResults().forEach(recordingResult => {
83 84
         t.transcriptionService.send(recordingResult, callBack);
84 85
         t.counter++;
@@ -109,11 +110,13 @@ const blobCallBack = function(answer) {
109 110
         let offset = answer.startTime.getUTCMilliseconds()
110 111
             - this.startTime.getUTCMilliseconds();
111 112
         // transcriber time will always be earlier
113
+
112 114
         if (offset < 0) {
113 115
             offset = 0; // presume 0 if it somehow not earlier
114 116
         }
115 117
 
116 118
         let array = '[';
119
+
117 120
         answer.wordArray.forEach(wordObject => {
118 121
             wordObject.begin += offset;
119 122
             wordObject.end += offset;
@@ -164,6 +167,7 @@ transcriber.prototype.merge = function() {
164 167
     // arrays of Word objects
165 168
     const potentialWords = []; // array of the first Word objects
166 169
     // check if any arrays are already empty and remove them
170
+
167 171
     hasPopulatedArrays(arrays);
168 172
 
169 173
     // populate all the potential Words for a first time
@@ -173,6 +177,7 @@ transcriber.prototype.merge = function() {
173 177
     let lowestWordArray;
174 178
     let wordToAdd;
175 179
     let foundSmaller;
180
+
176 181
     while(hasPopulatedArrays(arrays)) {
177 182
         // first select the lowest array;
178 183
         lowestWordArray = arrays[0];
@@ -242,6 +247,7 @@ const hasPopulatedArrays = function(twoDimensionalArray) {
242 247
             twoDimensionalArray.splice(i, 1);
243 248
         }
244 249
     }
250
+
245 251
     return twoDimensionalArray.length > 0;
246 252
 };
247 253
 
@@ -259,12 +265,15 @@ const pushWordToSortedArray = function(array, word) {
259 265
     } else{
260 266
         if(array[array.length - 1].begin <= word.begin) {
261 267
             array.push(word);
268
+
262 269
             return;
263 270
         }
264 271
         let i;
272
+
265 273
         for(i = 0; i < array.length; i++) {
266 274
             if(word.begin < array[i].begin) {
267 275
                 array.splice(i, 0, word);
276
+
268 277
                 return;
269 278
             }
270 279
         }
@@ -302,6 +311,7 @@ transcriber.prototype.getTranscription = function() {
302 311
                  FINISHED_STATE}" state. It's currently in the "${
303 312
                  this.state}" state`);
304 313
     }
314
+
305 315
     return this.transcription;
306 316
 };
307 317
 

+ 1
- 0
modules/transcription/transcriptionServices/AbstractTranscriptionService.js 查看文件

@@ -18,6 +18,7 @@ const TranscriptionService = function() {
18 18
  */
19 19
 TranscriptionService.prototype.send = function send(recordingResult, callback) {
20 20
     const t = this;
21
+
21 22
     this.sendRequest(recordingResult.blob, response => {
22 23
         if(t.verify(response)) {
23 24
             recordingResult.wordArray = t.formatResponse(response);

+ 10
- 0
modules/transcription/transcriptionServices/SphinxTranscriptionService.js 查看文件

@@ -33,6 +33,7 @@ SphinxService.prototype.sendRequest = function(audioFileBlob, callback) {
33 33
     console.log(`sending an audio file  to ${this.url}`);
34 34
     console.log(`the audio file being sent: ${audioFileBlob}`);
35 35
     const request = new XMLHttpRequest();
36
+
36 37
     request.onreadystatechange = function() {
37 38
         if(request.readyState === XMLHttpRequest.DONE
38 39
             && request.status === 200) {
@@ -61,12 +62,15 @@ SphinxService.prototype.formatResponse = function(response) {
61 62
     const result = JSON.parse(response).objects;
62 63
     // make sure to delete the session id object, which is always
63 64
     // the first value in the JSON array
65
+
64 66
     result.shift();
65 67
     const array = [];
68
+
66 69
     result.forEach(
67 70
         word =>
68 71
             word.filler
69 72
                 || array.push(new Word(word.word, word.start, word.end)));
73
+
70 74
     return array;
71 75
 };
72 76
 
@@ -83,10 +87,12 @@ SphinxService.prototype.verify = function(response) {
83 87
     }
84 88
     // test if the string can be parsed into valid JSON
85 89
     let json;
90
+
86 91
     try{
87 92
         json = JSON.parse(response);
88 93
     } catch (error) {
89 94
         console.log(error);
95
+
90 96
         return false;
91 97
     }
92 98
     // check if the JSON has a "objects" value
@@ -95,9 +101,11 @@ SphinxService.prototype.verify = function(response) {
95 101
     }
96 102
     // get the "objects" value and check for a session ID
97 103
     const array = json.objects;
104
+
98 105
     if(!(array[0] && array[0]['session-id'])) {
99 106
         return false;
100 107
     }
108
+
101 109
     // everything seems to be in order
102 110
     return true;
103 111
 };
@@ -110,10 +118,12 @@ SphinxService.prototype.verify = function(response) {
110 118
  */
111 119
 function getURL() {
112 120
     const message = 'config does not contain an url to a Sphinx4 https server';
121
+
113 122
     if(config.sphinxURL === undefined) {
114 123
         console.log(message);
115 124
     } else {
116 125
         const toReturn = config.sphinxURL;
126
+
117 127
         if(toReturn.includes !== undefined && toReturn.includes('https://')) {
118 128
             return toReturn;
119 129
         }

+ 2
- 0
modules/util/AuthUtil.js 查看文件

@@ -22,9 +22,11 @@ const AuthUtil = {
22 22
      */
23 23
     getTokenAuthUrl(urlPattern, roomName, roleUpgrade) {
24 24
         const url = urlPattern;
25
+
25 26
         if (typeof url !== 'string') {
26 27
             return null;
27 28
         }
29
+
28 30
         return url.replace('{room}', roomName)
29 31
             .replace('{roleUpgrade}', roleUpgrade === true);
30 32
     }

+ 1
- 0
modules/util/EventEmitterForwarder.js 查看文件

@@ -25,6 +25,7 @@ function EventEmitterForwarder(src, dest) {
25 25
 EventEmitterForwarder.prototype.forward = function(...args) {
26 26
     const srcEvent = args[0];
27 27
     // This will be the "this" value for emit function.
28
+
28 29
     args[0] = this.dest;
29 30
     // Using bind.apply to pass the arguments as Array-like object ("arguments")
30 31
     this.src.addListener(

+ 2
- 0
modules/util/GlobalOnErrorHandler.js 查看文件

@@ -57,6 +57,7 @@ const GlobalOnErrorHandler = {
57 57
      */
58 58
     callErrorHandler(error) {
59 59
         const errHandler = window.onerror;
60
+
60 61
         if(!errHandler) {
61 62
             return;
62 63
         }
@@ -68,6 +69,7 @@ const GlobalOnErrorHandler = {
68 69
      */
69 70
     callUnhandledRejectionHandler(error) {
70 71
         const errHandler = window.onunhandledrejection;
72
+
71 73
         if(!errHandler) {
72 74
             return;
73 75
         }

+ 2
- 0
modules/util/RandomUtil.js 查看文件

@@ -61,9 +61,11 @@ const RandomUtil = {
61 61
      */
62 62
     randomHexString(len) {
63 63
         let ret = '';
64
+
64 65
         while (len--) {
65 66
             ret += this.randomHexDigit();
66 67
         }
68
+
67 69
         return ret;
68 70
     },
69 71
     randomElement,

+ 2
- 0
modules/util/ScriptUtil.js 查看文件

@@ -34,10 +34,12 @@ const ScriptUtil = {
34 34
             // finds the src url of the current loaded script
35 35
             // and use it as base of the src supplied argument
36 36
             const scriptEl = currentExecutingScript();
37
+
37 38
             if(scriptEl) {
38 39
                 const scriptSrc = scriptEl.src;
39 40
                 const baseScriptSrc
40 41
                     = scriptSrc.substring(0, scriptSrc.lastIndexOf('/') + 1);
42
+
41 43
                 if (scriptSrc && baseScriptSrc) {
42 44
                     src = baseScriptSrc + src;
43 45
                 }

+ 6
- 0
modules/version/ComponentsVersions.js 查看文件

@@ -38,6 +38,7 @@ ComponentsVersions.prototype.processPresence
38 38
     = function(node, mucResource, mucJid) {
39 39
         if (node.attributes.xmlns !== 'http://jitsi.org/jitmeet') {
40 40
             logger.warn('Ignored presence versions node - invalid xmlns', node);
41
+
41 42
             return;
42 43
         }
43 44
 
@@ -45,23 +46,28 @@ ComponentsVersions.prototype.processPresence
45 46
             logger.warn(
46 47
                 `Received versions not from the focus user: ${node}`,
47 48
                 mucJid);
49
+
48 50
             return;
49 51
         }
50 52
 
51 53
         const log = [];
54
+
52 55
         node.children.forEach(item => {
53 56
 
54 57
             const componentName = item.attributes.name;
58
+
55 59
             if (componentName !== ComponentsVersions.FOCUS_COMPONENT
56 60
             && componentName !== ComponentsVersions.XMPP_SERVER_COMPONENT
57 61
             && componentName !== ComponentsVersions.VIDEOBRIDGE_COMPONENT) {
58 62
                 logger.warn(
59 63
                     `Received version for not supported component name: ${
60 64
                         componentName}`);
65
+
61 66
                 return;
62 67
             }
63 68
 
64 69
             const version = item.value;
70
+
65 71
             if (this.versions[componentName] !== version) {
66 72
                 this.versions[componentName] = version;
67 73
                 logger.info(`Got ${componentName} version: ${version}`);

+ 15
- 2
modules/xmpp/Caps.js 查看文件

@@ -11,9 +11,11 @@ const HASH = 'sha-1';
11 11
 
12 12
 function compareIdentities(a, b) {
13 13
     let res = 0;
14
+
14 15
     IDENTITY_PROPERTIES_FOR_COMPARE.some(key =>
15 16
         (res = ((a[key] > b[key]) && 1) || ((a[key] < b[key]) && -1)) !== 0
16 17
     );
18
+
17 19
     return res;
18 20
 }
19 21
 
@@ -43,6 +45,7 @@ export default class Caps extends Listenable {
43 45
         this.rooms = new Set();
44 46
 
45 47
         const emuc = connection.emuc;
48
+
46 49
         emuc.addListener(XMPPEvents.EMUC_ROOM_ADDED,
47 50
             room => this._addChatRoom(room));
48 51
         emuc.addListener(XMPPEvents.EMUC_ROOM_REMOVED,
@@ -104,13 +107,19 @@ export default class Caps extends Listenable {
104 107
     getFeatures(jid, timeout = 5000) {
105 108
         const user
106 109
             = jid in this.jidToVersion ? this.jidToVersion[jid] : null;
110
+
107 111
         if(!user || !(user.version in this.versionToCapabilities)) {
108 112
             const node = user ? `${user.node}#${user.version}` : null;
113
+
114
+
109 115
             return new Promise((resolve, reject) =>
110 116
                 this.disco.info(jid, node, response => {
111 117
                     const features = new Set();
112
-                    $(response).find('>query>feature').each((idx, el) =>
113
-                            features.add(el.getAttribute('var')));
118
+
119
+                    $(response)
120
+                        .find('>query>feature')
121
+                        .each(
122
+                            (idx, el) => features.add(el.getAttribute('var')));
114 123
                     if(user) {
115 124
                             // TODO: Maybe use the version + node + hash
116 125
                             // as keys?
@@ -121,6 +130,7 @@ export default class Caps extends Listenable {
121 130
                 }, reject , timeout)
122 131
             );
123 132
         }
133
+
124 134
         return Promise.resolve(this.versionToCapabilities[user.version]);
125 135
     }
126 136
 
@@ -175,6 +185,7 @@ export default class Caps extends Listenable {
175 185
     _generateVersion() {
176 186
         const identities = this.disco._identities.sort(compareIdentities);
177 187
         const features = this.disco._features.sort();
188
+
178 189
         this.version = b64_sha1(
179 190
             identities.reduce(
180 191
                     (accumulatedValue, identity) =>
@@ -200,11 +211,13 @@ export default class Caps extends Listenable {
200 211
         const version = caps.getAttribute('ver');
201 212
         const node = caps.getAttribute('node');
202 213
         const oldVersion = this.jidToVersion[from];
214
+
203 215
         this.jidToVersion[from] = {version, node};
204 216
         if(oldVersion && oldVersion.version !== version) {
205 217
             this.eventEmitter.emit(XMPPEvents.PARTCIPANT_FEATURES_CHANGED,
206 218
                 from);
207 219
         }
220
+
208 221
         // return true to not remove the handler from Strophe
209 222
         return true;
210 223
     }

+ 58
- 1
modules/xmpp/ChatRoom.js 查看文件

@@ -12,16 +12,20 @@ const logger = getLogger(__filename);
12 12
 const parser = {
13 13
     packet2JSON(packet, nodes) {
14 14
         const self = this;
15
+
16
+        // eslint-disable-next-line newline-per-chained-call
15 17
         $(packet).children().each(function() {
16 18
             const tagName = $(this).prop('tagName');
17 19
             const node = {
18 20
                 tagName
19 21
             };
22
+
20 23
             node.attributes = {};
21 24
             $($(this)[0].attributes).each((index, attr) => {
22 25
                 node.attributes[ attr.name ] = attr.value;
23 26
             });
24 27
             const text = Strophe.getText($(this)[0]);
28
+
25 29
             if (text) {
26 30
                 node.value = text;
27 31
             }
@@ -33,6 +37,7 @@ const parser = {
33 37
     json2packet(nodes, packet) {
34 38
         for(let i = 0; i < nodes.length; i++) {
35 39
             const node = nodes[i];
40
+
36 41
             if(node) {
37 42
                 packet.c(node.tagName, node.attributes);
38 43
                 if(node.value) {
@@ -56,6 +61,7 @@ const parser = {
56 61
  */
57 62
 function filterNodeFromPresenceJSON(pres, nodeName) {
58 63
     const res = [];
64
+
59 65
     for(let i = 0; i < pres.length; i++) {
60 66
         if(pres[i].tagName === nodeName) {
61 67
             res.push(pres[i]);
@@ -65,6 +71,10 @@ function filterNodeFromPresenceJSON(pres, nodeName) {
65 71
     return res;
66 72
 }
67 73
 
74
+// XXX As ChatRoom constructs XMPP stanzas and Strophe is build around the idea
75
+// of chaining function calls, allow long function call chains.
76
+/* eslint-disable newline-per-chained-call */
77
+
68 78
 export default class ChatRoom extends Listenable {
69 79
     constructor(connection, jid, password, XMPP, options) {
70 80
         super();
@@ -131,6 +141,7 @@ export default class ChatRoom extends Listenable {
131 141
 
132 142
     sendPresence(fromJoin) {
133 143
         const to = this.presMap.to;
144
+
134 145
         if (!to || (!this.joined && !fromJoin)) {
135 146
             // Too early to send presence - not initialized
136 147
             return;
@@ -170,6 +181,7 @@ export default class ChatRoom extends Listenable {
170 181
     doLeave() {
171 182
         logger.log('do leave', this.myroomjid);
172 183
         const pres = $pres({to: this.myroomjid, type: 'unavailable' });
184
+
173 185
         this.presMap.length = 0;
174 186
 
175 187
         // XXX Strophe is asynchronously sending by default. Unfortunately, that
@@ -199,6 +211,7 @@ export default class ChatRoom extends Listenable {
199 211
                 = $(result).find('>query>feature[var="muc_passwordprotected"]')
200 212
                         .length
201 213
                     === 1;
214
+
202 215
             if (locked != this.locked) {
203 216
                 this.eventEmitter.emit(XMPPEvents.MUC_LOCK_CHANGED, locked);
204 217
                 this.locked = locked;
@@ -224,8 +237,10 @@ export default class ChatRoom extends Listenable {
224 237
                     '>query>x[xmlns="jabber:x:data"]'
225 238
                     + '>field[var="muc#roomconfig_whois"]').length) {
226 239
                 const errmsg = 'non-anonymous rooms not supported';
240
+
227 241
                 GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
228 242
                 logger.error(errmsg);
243
+
229 244
                 return;
230 245
             }
231 246
 
@@ -253,15 +268,19 @@ export default class ChatRoom extends Listenable {
253 268
         const from = pres.getAttribute('from');
254 269
         // Parse roles.
255 270
         const member = {};
271
+
256 272
         member.show = $(pres).find('>show').text();
257 273
         member.status = $(pres).find('>status').text();
258 274
         const mucUserItem
259
-            = $(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>item');
275
+            = $(pres).find(
276
+                '>x[xmlns="http://jabber.org/protocol/muc#user"]>item');
277
+
260 278
         member.affiliation = mucUserItem.attr('affiliation');
261 279
         member.role = mucUserItem.attr('role');
262 280
 
263 281
         // Focus recognition
264 282
         const jid = mucUserItem.attr('jid');
283
+
265 284
         member.jid = jid;
266 285
         member.isFocus
267 286
             = jid && jid.indexOf(`${this.moderator.getFocusUserJid()}/`) === 0;
@@ -272,13 +291,16 @@ export default class ChatRoom extends Listenable {
272 291
 
273 292
         $(pres).find('>x').remove();
274 293
         const nodes = [];
294
+
275 295
         parser.packet2JSON(pres, nodes);
276 296
         this.lastPresences[from] = nodes;
277 297
         let jibri = null;
278 298
         // process nodes to extract data needed for MUC_JOINED and
279 299
         // MUC_MEMBER_JOINED events
300
+
280 301
         for(let i = 0; i < nodes.length; i++) {
281 302
             const node = nodes[i];
303
+
282 304
             switch(node.tagName) {
283 305
             case 'nick':
284 306
                 member.nick = node.value;
@@ -291,6 +313,7 @@ export default class ChatRoom extends Listenable {
291 313
 
292 314
         if (from == this.myroomjid) {
293 315
             const newRole = member.affiliation == 'owner' ? member.role : 'none';
316
+
294 317
             if (this.role !== newRole) {
295 318
                 this.role = newRole;
296 319
                 this.eventEmitter.emit(XMPPEvents.LOCAL_ROLE_CHANGED, this.role);
@@ -299,6 +322,7 @@ export default class ChatRoom extends Listenable {
299 322
                 this.joined = true;
300 323
                 const now = this.connectionTimes['muc.joined']
301 324
                     = window.performance.now();
325
+
302 326
                 logger.log('(TIME) MUC joined:\t', now);
303 327
 
304 328
                 // set correct initial state of locked
@@ -323,6 +347,7 @@ export default class ChatRoom extends Listenable {
323 347
             // Presence update for existing participant
324 348
             // Watch role change:
325 349
             const memberOfThis = this.members[from];
350
+
326 351
             if (memberOfThis.role != member.role) {
327 352
                 memberOfThis.role = member.role;
328 353
                 this.eventEmitter.emit(
@@ -352,6 +377,7 @@ export default class ChatRoom extends Listenable {
352 377
         // for the rest info we got in presence
353 378
         for(let i = 0; i < nodes.length; i++) {
354 379
             const node = nodes[i];
380
+
355 381
             switch(node.tagName) {
356 382
             case 'nick':
357 383
                 if(!member.isFocus) {
@@ -375,6 +401,7 @@ export default class ChatRoom extends Listenable {
375 401
                 break;
376 402
             case 'call-control': {
377 403
                 const att = node.attributes;
404
+
378 405
                 if(!att) {
379 406
                     break;
380 407
                 }
@@ -435,6 +462,7 @@ export default class ChatRoom extends Listenable {
435 462
         // otherwise we can remove the presence handler from strophe
436 463
         try {
437 464
             let tagHandler = this.presHandlers[node.tagName];
465
+
438 466
             if (node.tagName.startsWith('jitsi_participant_')) {
439 467
                 tagHandler = this.participantPropertyListener;
440 468
             }
@@ -450,6 +478,7 @@ export default class ChatRoom extends Listenable {
450 478
 
451 479
     sendMessage(body, nickname) {
452 480
         const msg = $msg({to: this.roomjid, type: 'groupchat'});
481
+
453 482
         msg.c('body', body).up();
454 483
         if (nickname) {
455 484
             msg.c('nick', {xmlns: 'http://jabber.org/protocol/nick'}).t(nickname).up().up();
@@ -460,6 +489,7 @@ export default class ChatRoom extends Listenable {
460 489
 
461 490
     setSubject(subject) {
462 491
         const msg = $msg({to: this.roomjid, type: 'groupchat'});
492
+
463 493
         msg.c('subject', subject);
464 494
         this.connection.send(msg);
465 495
     }
@@ -491,6 +521,7 @@ export default class ChatRoom extends Listenable {
491 521
             const reasonSelect = $(pres).find(
492 522
                     '>x[xmlns="http://jabber.org/protocol/muc#user"]'
493 523
                     + '>destroy>reason');
524
+
494 525
             if (reasonSelect.length) {
495 526
                 reason = reasonSelect.text();
496 527
             }
@@ -499,6 +530,7 @@ export default class ChatRoom extends Listenable {
499 530
 
500 531
             this.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason);
501 532
             this.connection.emuc.doLeave(this.roomjid);
533
+
502 534
             return true;
503 535
         }
504 536
 
@@ -510,6 +542,7 @@ export default class ChatRoom extends Listenable {
510 542
                 '>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="307"]'
511 543
             ).length !== 0;
512 544
         const membersKeys = Object.keys(this.members);
545
+
513 546
         if (!isSelfPresence) {
514 547
             delete this.members[from];
515 548
             this.onParticipantLeft(from, false);
@@ -519,6 +552,7 @@ export default class ChatRoom extends Listenable {
519 552
             // event.
520 553
             membersKeys.forEach(jid => {
521 554
                 const member = this.members[jid];
555
+
522 556
                 delete this.members[jid];
523 557
                 this.onParticipantLeft(jid, member.isFocus);
524 558
             });
@@ -545,15 +579,19 @@ export default class ChatRoom extends Listenable {
545 579
 
546 580
         const txt = $(msg).find('>body').text();
547 581
         const type = msg.getAttribute('type');
582
+
548 583
         if (type == 'error') {
549 584
             this.eventEmitter.emit(XMPPEvents.CHAT_ERROR_RECEIVED,
550 585
                 $(msg).find('>text').text(), txt);
586
+
551 587
             return true;
552 588
         }
553 589
 
554 590
         const subject = $(msg).find('>subject');
591
+
555 592
         if (subject.length) {
556 593
             const subjectText = subject.text();
594
+
557 595
             if (subjectText || subjectText === '') {
558 596
                 this.eventEmitter.emit(XMPPEvents.SUBJECT_CHANGED, subjectText);
559 597
                 logger.log(`Subject is changed to ${subjectText}`);
@@ -570,6 +608,7 @@ export default class ChatRoom extends Listenable {
570 608
             if (stamp) {
571 609
                 // the format is CCYYMMDDThh:mm:ss
572 610
                 const dateParts = stamp.match(/(\d{4})(\d{2})(\d{2}T\d{2}:\d{2}:\d{2})/);
611
+
573 612
                 stamp = `${dateParts[1]}-${dateParts[2]}-${dateParts[3]}Z`;
574 613
             }
575 614
         }
@@ -592,6 +631,7 @@ export default class ChatRoom extends Listenable {
592 631
         } else if ($(pres).find(
593 632
             '>error[type="cancel"]>not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) {
594 633
             const toDomain = Strophe.getDomainFromJid(pres.getAttribute('to'));
634
+
595 635
             if (toDomain === this.xmpp.options.hosts.anonymousdomain) {
596 636
                 // enter the room by replying with 'not-authorized'. This would
597 637
                 // result in reconnection from authorized domain.
@@ -634,6 +674,7 @@ export default class ChatRoom extends Listenable {
634 674
                     const formsubmit
635 675
                         = $iq({to: this.roomjid, type: 'set'})
636 676
                             .c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'});
677
+
637 678
                     formsubmit.c('x', {xmlns: 'jabber:x:data', type: 'submit'});
638 679
                     formsubmit.c('field', {'var': 'FORM_TYPE'}).c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up();
639 680
                     formsubmit.c('field', {'var': 'muc#roomconfig_roomsecret'}).c('value').t(key).up().up();
@@ -656,6 +697,7 @@ export default class ChatRoom extends Listenable {
656 697
 
657 698
     removeFromPresence(key) {
658 699
         const nodes = this.presMap.nodes.filter(node => key !== node.tagName);
700
+
659 701
         this.presMap.nodes = nodes;
660 702
     }
661 703
 
@@ -677,9 +719,11 @@ export default class ChatRoom extends Listenable {
677 719
      */
678 720
     isFocus(mucJid) {
679 721
         const member = this.members[mucJid];
722
+
680 723
         if (member) {
681 724
             return member.isFocus;
682 725
         }
726
+
683 727
         return null;
684 728
     }
685 729
 
@@ -691,6 +735,7 @@ export default class ChatRoom extends Listenable {
691 735
         if (this.members[peerJid]) {
692 736
             return this.members[peerJid].role;
693 737
         }
738
+
694 739
         return null;
695 740
     }
696 741
 
@@ -753,6 +798,7 @@ export default class ChatRoom extends Listenable {
753 798
     getMediaPresenceInfo(endpointId, mediaType) {
754 799
         // Will figure out current muted status by looking up owner's presence
755 800
         const pres = this.lastPresences[`${this.roomjid}/${endpointId}`];
801
+
756 802
         if (!pres) {
757 803
             // No presence available
758 804
             return null;
@@ -774,6 +820,7 @@ export default class ChatRoom extends Listenable {
774 820
             }
775 821
         } else {
776 822
             logger.error(`Unsupported media type: ${mediaType}`);
823
+
777 824
             return null;
778 825
         }
779 826
 
@@ -789,6 +836,7 @@ export default class ChatRoom extends Listenable {
789 836
         if(this.recording) {
790 837
             return this.recording.isSupported();
791 838
         }
839
+
792 840
         return false;
793 841
     }
794 842
 
@@ -828,6 +876,7 @@ export default class ChatRoom extends Listenable {
828 876
         if(this.moderator) {
829 877
             return this.moderator.isSipGatewayEnabled();
830 878
         }
879
+
831 880
         return false;
832 881
     }
833 882
 
@@ -886,15 +935,20 @@ export default class ChatRoom extends Listenable {
886 935
 
887 936
     onMute(iq) {
888 937
         const from = iq.getAttribute('from');
938
+
889 939
         if (from !== this.focusMucJid) {
890 940
             logger.warn('Ignored mute from non focus peer');
941
+
891 942
             return false;
892 943
         }
893 944
         const mute = $(iq).find('mute');
945
+
894 946
         if (mute.length) {
895 947
             const doMuteAudio = mute.text() === 'true';
948
+
896 949
             this.eventEmitter.emit(XMPPEvents.AUDIO_MUTED_BY_FOCUS, doMuteAudio);
897 950
         }
951
+
898 952
         return true;
899 953
     }
900 954
 
@@ -908,6 +962,7 @@ export default class ChatRoom extends Listenable {
908 962
         return new Promise((resolve, reject) => {
909 963
             const timeout = setTimeout(() => onMucLeft(true), 5000);
910 964
             const eventEmitter = this.eventEmitter;
965
+
911 966
             function onMucLeft(doReject = false) {
912 967
                 eventEmitter.removeListener(XMPPEvents.MUC_LEFT, onMucLeft);
913 968
                 clearTimeout(timeout);
@@ -924,3 +979,5 @@ export default class ChatRoom extends Listenable {
924 979
         });
925 980
     }
926 981
 }
982
+
983
+/* eslint-enable newline-per-chained-call */

+ 1
- 0
modules/xmpp/JingleSession.js 查看文件

@@ -73,6 +73,7 @@ export default class JingleSession {
73 73
             const errmsg
74 74
                 = `attempt to initiate on session ${this.sid}
75 75
                    in state ${this.state}`;
76
+
76 77
             logger.error(errmsg);
77 78
             throw new Error(errmsg);
78 79
         }

+ 120
- 11
modules/xmpp/JingleSessionPC.js 查看文件

@@ -2,6 +2,7 @@
2 2
 
3 3
 import {getLogger} from 'jitsi-meet-logger';
4 4
 const logger = getLogger(__filename);
5
+
5 6
 import JingleSession from './JingleSession';
6 7
 const SDPDiffer = require('./SDPDiffer');
7 8
 const SDPUtil = require('./SDPUtil');
@@ -124,9 +125,11 @@ export default class JingleSessionPC extends JingleSession {
124 125
             }
125 126
             // XXX this is broken, candidate is not parsed.
126 127
             const candidate = ev.candidate;
128
+
127 129
             if (candidate) {
128 130
                 // Discard candidates of disabled protocols.
129 131
                 let protocol = candidate.protocol;
132
+
130 133
                 if (typeof protocol === 'string') {
131 134
                     protocol = protocol.toLowerCase();
132 135
                     if (protocol === 'tcp' || protocol === 'ssltcp') {
@@ -173,6 +176,7 @@ export default class JingleSessionPC extends JingleSession {
173 176
                 return;
174 177
             }
175 178
             const now = window.performance.now();
179
+
176 180
             this.room.connectionTimes[
177 181
                     `ice.state.${this.peerconnection.iceConnectionState}`]
178 182
                 = now;
@@ -222,15 +226,19 @@ export default class JingleSessionPC extends JingleSession {
222 226
 
223 227
     sendIceCandidate(candidate) {
224 228
         const localSDP = new SDP(this.peerconnection.localDescription.sdp);
229
+
225 230
         if (candidate && !this.lasticecandidate) {
226 231
             const ice
227 232
                 = SDPUtil.iceparams(
228 233
                     localSDP.media[candidate.sdpMLineIndex], localSDP.session);
229 234
             const jcand = SDPUtil.candidateToJingle(candidate.candidate);
235
+
230 236
             if (!(ice && jcand)) {
231 237
                 const errorMesssage = 'failed to get ice && jcand';
238
+
232 239
                 GlobalOnErrorHandler.callErrorHandler(new Error(errorMesssage));
233 240
                 logger.error(errorMesssage);
241
+
234 242
                 return;
235 243
             }
236 244
             ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
@@ -266,13 +274,16 @@ export default class JingleSessionPC extends JingleSession {
266 274
                 sid: this.sid});
267 275
 
268 276
         const localSDP = new SDP(this.peerconnection.localDescription.sdp);
277
+
269 278
         for (let mid = 0; mid < localSDP.media.length; mid++) {
270 279
             const cands = candidates.filter(el => el.sdpMLineIndex == mid);
271 280
             const mline
272 281
                 = SDPUtil.parse_mline(localSDP.media[mid].split('\r\n')[0]);
282
+
273 283
             if (cands.length > 0) {
274 284
                 const ice
275 285
                     = SDPUtil.iceparams(localSDP.media[mid], localSDP.session);
286
+
276 287
                 ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
277 288
                 cand.c('content', {
278 289
                     creator: this.initiator == this.localJid
@@ -283,6 +294,7 @@ export default class JingleSessionPC extends JingleSession {
283 294
                     const candidate
284 295
                         = SDPUtil.candidateToJingle(cands[i].candidate);
285 296
                     // Mangle ICE candidate if 'failICE' test option is enabled
297
+
286 298
                     if (this.failICE) {
287 299
                         candidate.ip = '1.1.1.1';
288 300
                     }
@@ -296,6 +308,7 @@ export default class JingleSessionPC extends JingleSession {
296 308
 
297 309
                 if (fingerprint_line) {
298 310
                     const tmp = SDPUtil.parse_fingerprint(fingerprint_line);
311
+
299 312
                     tmp.required = true;
300 313
                     cand.c(
301 314
                         'fingerprint',
@@ -325,12 +338,15 @@ export default class JingleSessionPC extends JingleSession {
325 338
                 = $(content).find(
326 339
                     'description>'
327 340
                         + 'source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
341
+
328 342
             ssrcs.each((idx, ssrcElement) => {
329 343
                 const ssrc = ssrcElement.getAttribute('ssrc');
344
+
330 345
                 $(ssrcElement)
331 346
                     .find('>ssrc-info[xmlns="http://jitsi.org/jitmeet"]')
332 347
                     .each((idx, ssrcInfoElement) => {
333 348
                         const owner = ssrcInfoElement.getAttribute('owner');
349
+
334 350
                         if (owner && owner.length) {
335 351
                             this.ssrcOwners[ssrc]
336 352
                                 = Strophe.getResourceFromJid(owner);
@@ -392,6 +408,7 @@ export default class JingleSessionPC extends JingleSession {
392 408
     setOfferCycle(jingleOfferIq, success, failure) {
393 409
         const workFunction = finishedCallback => {
394 410
             const newRemoteSdp = this._processNewJingleOfferIq(jingleOfferIq);
411
+
395 412
             this._renegotiate(newRemoteSdp)
396 413
                 .then(() => {
397 414
                     finishedCallback();
@@ -403,6 +420,7 @@ export default class JingleSessionPC extends JingleSession {
403 420
                     finishedCallback(error);
404 421
                 });
405 422
         };
423
+
406 424
         this.modificationQueue.push(
407 425
             workFunction,
408 426
             error => {
@@ -425,6 +443,7 @@ export default class JingleSessionPC extends JingleSession {
425 443
         // the SCTP connection established with the new bridge.
426 444
         this.room.eventEmitter.emit(XMPPEvents.ICE_RESTARTING);
427 445
         const originalOffer = jingleOfferElem.clone();
446
+
428 447
         jingleOfferElem.find('>content[name=\'data\']').remove();
429 448
 
430 449
         // First set an offer without the 'data' section
@@ -437,6 +456,7 @@ export default class JingleSessionPC extends JingleSession {
437 456
                     () => {
438 457
                         const localSDP
439 458
                             = new SDP(this.peerconnection.localDescription.sdp);
459
+
440 460
                         this.sendTransportAccept(localSDP, success, failure);
441 461
                     },
442 462
                     failure);
@@ -463,6 +483,7 @@ export default class JingleSessionPC extends JingleSession {
463 483
                 initiator: this.initiator,
464 484
                 responder: this.responder,
465 485
                 sid: this.sid });
486
+
466 487
         if (this.webrtcIceTcpDisable) {
467 488
             localSDP.removeTcpCandidates = true;
468 489
         }
@@ -531,6 +552,7 @@ export default class JingleSessionPC extends JingleSession {
531 552
 
532 553
         localSDP.media.forEach((medialines, idx) => {
533 554
             const mline = SDPUtil.parse_mline(medialines.split('\r\n')[0]);
555
+
534 556
             transportAccept.c('content',
535 557
                 {
536 558
                     creator:
@@ -599,6 +621,7 @@ export default class JingleSessionPC extends JingleSession {
599 621
             .c(reason || 'success');
600 622
 
601 623
         if (text) {
624
+            // eslint-disable-next-line newline-per-chained-call
602 625
             sessionTerminate.up().c('text').t(text);
603 626
         }
604 627
 
@@ -638,16 +661,22 @@ export default class JingleSessionPC extends JingleSession {
638 661
      */
639 662
     _parseSsrcInfoFromSourceAdd(sourceAddElem, currentRemoteSdp) {
640 663
         const addSsrcInfo = [];
664
+
641 665
         $(sourceAddElem).each((idx, content) => {
642 666
             const name = $(content).attr('name');
643 667
             let lines = '';
668
+
644 669
             $(content)
645 670
                 .find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]')
646 671
                 .each(function() {
647 672
                     const semantics = this.getAttribute('semantics');
648
-                    const ssrcs = $(this).find('>source').map(function() {
649
-                        return this.getAttribute('ssrc');
650
-                    }).get();
673
+                    const ssrcs
674
+                        = $(this)
675
+                            .find('>source')
676
+                            .map(function() {
677
+                                return this.getAttribute('ssrc');
678
+                            })
679
+                            .get();
651 680
 
652 681
                     if (ssrcs.length) {
653 682
                         lines
@@ -659,13 +688,18 @@ export default class JingleSessionPC extends JingleSession {
659 688
             const tmp
660 689
                 = $(content).find(
661 690
                     'source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
691
+
662 692
             tmp.each(function() {
663 693
                 const ssrc = $(this).attr('ssrc');
694
+
664 695
                 if (currentRemoteSdp.containsSSRC(ssrc)) {
665 696
                     logger.warn(
666 697
                         `Source-add request for existing SSRC: ${ssrc}`);
698
+
667 699
                     return;
668 700
                 }
701
+
702
+                // eslint-disable-next-line newline-per-chained-call
669 703
                 $(this).find('>parameter').each(function() {
670 704
                     lines += `a=ssrc:${ssrc} ${$(this).attr('name')}`;
671 705
                     if ($(this).attr('value') && $(this).attr('value').length) {
@@ -684,6 +718,7 @@ export default class JingleSessionPC extends JingleSession {
684 718
                 addSsrcInfo[idx] += lines;
685 719
             });
686 720
         });
721
+
687 722
         return addSsrcInfo;
688 723
     }
689 724
 
@@ -696,6 +731,7 @@ export default class JingleSessionPC extends JingleSession {
696 731
         if (!this.peerconnection.localDescription) {
697 732
             logger.warn('addSource - localDescription not ready yet');
698 733
             setTimeout(() => this.addRemoteStream(elem), 200);
734
+
699 735
             return;
700 736
         }
701 737
         logger.log('Processing add remote stream');
@@ -710,11 +746,13 @@ export default class JingleSessionPC extends JingleSession {
710 746
             const addSsrcInfo = this._parseSsrcInfoFromSourceAdd(elem, sdp);
711 747
 
712 748
             const newRemoteSdp = this._processRemoteAddSource(addSsrcInfo);
749
+
713 750
             this._renegotiate(newRemoteSdp)
714 751
                 .then(() => {
715 752
                     logger.info('Remote source-add processed');
716 753
                     const newSdp
717 754
                         = new SDP(this.peerconnection.localDescription.sdp);
755
+
718 756
                     logger.log('SDPs', mySdp, newSdp);
719 757
                     this.notifyMySSRCUpdate(mySdp, newSdp);
720 758
                     finishedCallback();
@@ -724,6 +762,7 @@ export default class JingleSessionPC extends JingleSession {
724 762
                     finishedCallback(error);
725 763
                 });
726 764
         };
765
+
727 766
         this.modificationQueue.push(workFunction);
728 767
     }
729 768
 
@@ -736,6 +775,7 @@ export default class JingleSessionPC extends JingleSession {
736 775
         if (!this.peerconnection.localDescription) {
737 776
             logger.warn('removeSource - localDescription not ready yet');
738 777
             setTimeout(() => this.removeRemoteStream(elem), 200);
778
+
739 779
             return;
740 780
         }
741 781
 
@@ -750,11 +790,13 @@ export default class JingleSessionPC extends JingleSession {
750 790
 
751 791
             const newRemoteSdp
752 792
                 = this._processRemoteRemoveSource(removeSsrcInfo);
793
+
753 794
             this._renegotiate(newRemoteSdp)
754 795
                 .then(() => {
755 796
                     logger.info('Remote source-remove processed');
756 797
                     const newSdp
757 798
                         = new SDP(this.peerconnection.localDescription.sdp);
799
+
758 800
                     logger.log('SDPs', mySdp, newSdp);
759 801
                     this.notifyMySSRCUpdate(mySdp, newSdp);
760 802
                     finishedCallback();
@@ -764,6 +806,7 @@ export default class JingleSessionPC extends JingleSession {
764 806
                     finishedCallback(error);
765 807
                 });
766 808
         };
809
+
767 810
         this.modificationQueue.push(workFunction);
768 811
     }
769 812
 
@@ -792,6 +835,7 @@ export default class JingleSessionPC extends JingleSession {
792 835
      */
793 836
     _processNewJingleOfferIq(offerIq) {
794 837
         const remoteSdp = new SDP('');
838
+
795 839
         if (this.webrtcIceTcpDisable) {
796 840
             remoteSdp.removeTcpCandidates = true;
797 841
         }
@@ -804,6 +848,7 @@ export default class JingleSessionPC extends JingleSession {
804 848
 
805 849
         remoteSdp.fromJingle(offerIq);
806 850
         this.readSsrcInfo($(offerIq).find('>content'));
851
+
807 852
         return remoteSdp;
808 853
     }
809 854
 
@@ -816,6 +861,7 @@ export default class JingleSessionPC extends JingleSession {
816 861
      */
817 862
     _processRemoteRemoveSource(removeSsrcInfo) {
818 863
         const remoteSdp = new SDP(this.peerconnection.remoteDescription.sdp);
864
+
819 865
         removeSsrcInfo.forEach((lines, idx) => {
820 866
             lines = lines.split('\r\n');
821 867
             lines.pop(); // remove empty last element;
@@ -838,6 +884,7 @@ export default class JingleSessionPC extends JingleSession {
838 884
      */
839 885
     _processRemoteAddSource(addSsrcInfo) {
840 886
         const remoteSdp = new SDP(this.peerconnection.remoteDescription.sdp);
887
+
841 888
         addSsrcInfo.forEach((lines, idx) => {
842 889
             remoteSdp.media[idx] += lines;
843 890
         });
@@ -874,6 +921,7 @@ export default class JingleSessionPC extends JingleSession {
874 921
         //  core flows like this.
875 922
         return new Promise((resolve, reject) => {
876 923
             const remoteUfrag = JingleSessionPC.getUfrag(remoteDescription.sdp);
924
+
877 925
             if (remoteUfrag != this.remoteUfrag) {
878 926
                 this.remoteUfrag = remoteUfrag;
879 927
                 this.room.eventEmitter.emit(
@@ -886,6 +934,7 @@ export default class JingleSessionPC extends JingleSession {
886 934
                 () => {
887 935
                     if (this.signalingState === 'closed') {
888 936
                         reject('Attempted to setRemoteDescription in state closed');
937
+
889 938
                         return;
890 939
                     }
891 940
                     logger.debug('Renegotiate: creating answer');
@@ -893,6 +942,7 @@ export default class JingleSessionPC extends JingleSession {
893 942
                         answer => {
894 943
                             const localUfrag
895 944
                                 = JingleSessionPC.getUfrag(answer.sdp);
945
+
896 946
                             if (localUfrag != this.localUfrag) {
897 947
                                 this.localUfrag = localUfrag;
898 948
                                 this.room.eventEmitter.emit(
@@ -942,6 +992,7 @@ export default class JingleSessionPC extends JingleSession {
942 992
                 // NOTE the code below assumes that no more than 1 video track
943 993
                 // can be added to the peer connection.
944 994
                 // Transition from no video to video (possibly screen sharing)
995
+
945 996
                 if (!oldTrack && newTrack && newTrack.isVideoTrack()) {
946 997
                     // Clearing current primary SSRC will make
947 998
                     // the SdpConsistency generate a new one which will result
@@ -964,6 +1015,7 @@ export default class JingleSessionPC extends JingleSession {
964 1015
                     .then(() => {
965 1016
                         const newSdp
966 1017
                             = new SDP(this.peerconnection.localDescription.sdp);
1018
+
967 1019
                         this.notifyMySSRCUpdate(oldSdp, newSdp);
968 1020
                         finishedCallback();
969 1021
                     }, error => {
@@ -972,6 +1024,7 @@ export default class JingleSessionPC extends JingleSession {
972 1024
                         finishedCallback(error);
973 1025
                     });
974 1026
             };
1027
+
975 1028
             this.modificationQueue.push(
976 1029
                 workFunction,
977 1030
                 error => {
@@ -991,6 +1044,7 @@ export default class JingleSessionPC extends JingleSession {
991 1044
         const actualStream
992 1045
             = stream && stream.getOriginalStream
993 1046
                 ? stream.getOriginalStream() : stream;
1047
+
994 1048
         if (this.peerconnection) {
995 1049
             this.peerconnection.addStream(actualStream, ssrcInfo);
996 1050
         }
@@ -1008,16 +1062,22 @@ export default class JingleSessionPC extends JingleSession {
1008 1062
      */
1009 1063
     _parseSsrcInfoFromSourceRemove(sourceRemoveElem, currentRemoteSdp) {
1010 1064
         const removeSsrcInfo = [];
1065
+
1011 1066
         $(sourceRemoveElem).each((idx, content) => {
1012 1067
             const name = $(content).attr('name');
1013 1068
             let lines = '';
1069
+
1014 1070
             $(content)
1015 1071
                 .find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]')
1016 1072
                 .each(function() {
1017 1073
                     const semantics = this.getAttribute('semantics');
1018
-                    const ssrcs = $(this).find('>source').map(function() {
1019
-                        return this.getAttribute('ssrc');
1020
-                    }).get();
1074
+                    const ssrcs
1075
+                        = $(this)
1076
+                            .find('>source')
1077
+                            .map(function() {
1078
+                                return this.getAttribute('ssrc');
1079
+                            })
1080
+                            .get();
1021 1081
 
1022 1082
                     if (ssrcs.length) {
1023 1083
                         lines
@@ -1030,8 +1090,10 @@ export default class JingleSessionPC extends JingleSession {
1030 1090
             const tmp
1031 1091
                 = $(content).find(
1032 1092
                     'source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
1093
+
1033 1094
             tmp.each(function() {
1034 1095
                 const ssrc = $(this).attr('ssrc');
1096
+
1035 1097
                 ssrcs.push(ssrc);
1036 1098
             });
1037 1099
             currentRemoteSdp.media.forEach((media, idx) => {
@@ -1044,6 +1106,7 @@ export default class JingleSessionPC extends JingleSession {
1044 1106
                 ssrcs.forEach(ssrc => {
1045 1107
                     const ssrcLines
1046 1108
                         = SDPUtil.find_lines(media, `a=ssrc:${ssrc}`);
1109
+
1047 1110
                     if (ssrcLines.length) {
1048 1111
                         removeSsrcInfo[idx] += `${ssrcLines.join('\r\n')}\r\n`;
1049 1112
                     }
@@ -1051,6 +1114,7 @@ export default class JingleSessionPC extends JingleSession {
1051 1114
                 removeSsrcInfo[idx] += lines;
1052 1115
             });
1053 1116
         });
1117
+
1054 1118
         return removeSsrcInfo;
1055 1119
     }
1056 1120
 
@@ -1078,6 +1142,7 @@ export default class JingleSessionPC extends JingleSession {
1078 1142
             if (!this.peerconnection) {
1079 1143
                 finishedCallback(
1080 1144
                     'Error: tried adding stream with no active peer connection');
1145
+
1081 1146
                 return;
1082 1147
             }
1083 1148
             this.addStreamToPeerConnection(stream, ssrcInfo);
@@ -1090,14 +1155,17 @@ export default class JingleSessionPC extends JingleSession {
1090 1155
             }
1091 1156
             if (dontModifySources) {
1092 1157
                 finishedCallback();
1158
+
1093 1159
                 return;
1094 1160
             }
1095 1161
             const oldSdp = new SDP(this.peerconnection.localDescription.sdp);
1162
+
1096 1163
             this._renegotiate()
1097 1164
                 .then(() => {
1098 1165
                     const newSdp
1099 1166
                         = new SDP(this.peerconnection.localDescription.sdp);
1100 1167
                     // FIXME objects should not be logged
1168
+
1101 1169
                     logger.log('SDPs', oldSdp, newSdp);
1102 1170
                     this.notifyMySSRCUpdate(oldSdp, newSdp);
1103 1171
                     finishedCallback();
@@ -1105,6 +1173,7 @@ export default class JingleSessionPC extends JingleSession {
1105 1173
                     finishedCallback(error);
1106 1174
                 });
1107 1175
         };
1176
+
1108 1177
         this.modificationQueue.push(
1109 1178
             workFunction,
1110 1179
             error => {
@@ -1135,6 +1204,7 @@ export default class JingleSessionPC extends JingleSession {
1135 1204
         // of complications. Instead, we use the RTPSender and remove just
1136 1205
         // the track.
1137 1206
         let track = null;
1207
+
1138 1208
         if (stream.getAudioTracks() && stream.getAudioTracks().length) {
1139 1209
             track = stream.getAudioTracks()[0];
1140 1210
         } else if (stream.getVideoTracks() && stream.getVideoTracks().length) {
@@ -1143,7 +1213,9 @@ export default class JingleSessionPC extends JingleSession {
1143 1213
 
1144 1214
         if (!track) {
1145 1215
             const msg = 'Cannot remove tracks: no tracks.';
1216
+
1146 1217
             logger.log(msg);
1218
+
1147 1219
             return;
1148 1220
         }
1149 1221
 
@@ -1151,8 +1223,10 @@ export default class JingleSessionPC extends JingleSession {
1151 1223
         this.peerconnection.peerconnection.getSenders().some(s => {
1152 1224
             if (s.track === track) {
1153 1225
                 sender = s;
1226
+
1154 1227
                 return true;
1155 1228
             }
1229
+
1156 1230
             return false;
1157 1231
         });
1158 1232
 
@@ -1173,6 +1247,7 @@ export default class JingleSessionPC extends JingleSession {
1173 1247
         const actualStream
1174 1248
             = stream && stream.getOriginalStream
1175 1249
                 ? stream.getOriginalStream() : stream;
1250
+
1176 1251
         if (!this.peerconnection) {
1177 1252
             return;
1178 1253
         }
@@ -1196,6 +1271,7 @@ export default class JingleSessionPC extends JingleSession {
1196 1271
         const workFunction = finishedCallback => {
1197 1272
             if (!this.peerconnection) {
1198 1273
                 finishedCallback();
1274
+
1199 1275
                 return;
1200 1276
             }
1201 1277
             if (RTCBrowserType.getBrowserType()
@@ -1205,10 +1281,12 @@ export default class JingleSessionPC extends JingleSession {
1205 1281
                 this.removeStreamFromPeerConnection(stream);
1206 1282
             }
1207 1283
             const oldSdp = new SDP(this.peerconnection.localDescription.sdp);
1284
+
1208 1285
             this._renegotiate()
1209 1286
                 .then(() => {
1210 1287
                     const newSdp
1211 1288
                         = new SDP(this.peerconnection.localDescription.sdp);
1289
+
1212 1290
                     if (ssrcInfo) {
1213 1291
                         this.modifiedSSRCs[ssrcInfo.type]
1214 1292
                             = this.modifiedSSRCs[ssrcInfo.type] || [];
@@ -1221,6 +1299,7 @@ export default class JingleSessionPC extends JingleSession {
1221 1299
                     finishedCallback(error);
1222 1300
                 });
1223 1301
         };
1302
+
1224 1303
         this.modificationQueue.push(
1225 1304
             workFunction,
1226 1305
             error => {
@@ -1237,6 +1316,7 @@ export default class JingleSessionPC extends JingleSession {
1237 1316
 
1238 1317
         if (this.state !== JingleSessionState.ACTIVE) {
1239 1318
             logger.warn(`Skipping SSRC update in '${this.state} ' state.`);
1319
+
1240 1320
             return;
1241 1321
         }
1242 1322
 
@@ -1250,6 +1330,7 @@ export default class JingleSessionPC extends JingleSession {
1250 1330
                 sid: this.sid
1251 1331
             }
1252 1332
             );
1333
+
1253 1334
         sdpDiffer.toJingle(remove);
1254 1335
         const removed = this.fixJingle(remove);
1255 1336
 
@@ -1316,9 +1397,11 @@ export default class JingleSessionPC extends JingleSession {
1316 1397
 
1317 1398
             // Get XMPP error code and condition(reason)
1318 1399
             const errorElSel = $(errResponse).find('error');
1400
+
1319 1401
             if (errorElSel.length) {
1320 1402
                 error.code = errorElSel.attr('code');
1321 1403
                 const errorReasonSel = $(errResponse).find('error :first');
1404
+
1322 1405
                 if (errorReasonSel.length) {
1323 1406
                     error.reason = errorReasonSel[0].tagName;
1324 1407
                 }
@@ -1398,8 +1481,9 @@ export default class JingleSessionPC extends JingleSession {
1398 1481
      * @returns {boolean} true if the jingle has to be sent and false otherwise.
1399 1482
      */
1400 1483
     fixJingle(jingle) {
1401
-        /* eslint-disable no-case-declarations */
1484
+        // eslint-disable-next-line newline-per-chained-call
1402 1485
         const action = $(jingle.nodeTree).find('jingle').attr('action');
1486
+
1403 1487
         switch (action) {
1404 1488
         case 'source-add':
1405 1489
         case 'session-accept':
@@ -1408,15 +1492,20 @@ export default class JingleSessionPC extends JingleSession {
1408 1492
         case 'source-remove':
1409 1493
             this.fixSourceRemoveJingle(jingle);
1410 1494
             break;
1411
-        default:
1495
+        default: {
1412 1496
             const errmsg = 'Unknown jingle action!';
1497
+
1413 1498
             GlobalOnErrorHandler.callErrorHandler(errmsg);
1414 1499
             logger.error(errmsg);
1500
+
1415 1501
             return false;
1416
-        }/* eslint-enable no-case-declarations */
1502
+        }
1503
+        }
1417 1504
 
1418 1505
         const sources
1419 1506
             = $(jingle.tree()).find('>jingle>content>description>source');
1507
+
1508
+
1420 1509
         return sources && sources.length > 0;
1421 1510
     }
1422 1511
 
@@ -1428,23 +1517,27 @@ export default class JingleSessionPC extends JingleSession {
1428 1517
      */
1429 1518
     fixSourceAddJingle(jingle) {
1430 1519
         let ssrcs = this.modifiedSSRCs.unmute;
1520
+
1431 1521
         this.modifiedSSRCs.unmute = [];
1432 1522
         if (ssrcs && ssrcs.length) {
1433 1523
             ssrcs.forEach(ssrcObj => {
1434 1524
                 const desc
1435 1525
                     = $(jingle.tree()).find(
1436 1526
                         `>jingle>content[name="${ssrcObj.mtype}"]>description`);
1527
+
1437 1528
                 if (!desc || !desc.length) {
1438 1529
                     return;
1439 1530
                 }
1440 1531
                 ssrcObj.ssrcs.forEach(ssrc => {
1441 1532
                     const sourceNode = desc.find(`>source[ssrc="${ssrc}"]`);
1533
+
1442 1534
                     sourceNode.remove();
1443 1535
                 });
1444 1536
                 ssrcObj.groups.forEach(group => {
1445 1537
                     const groupNode = desc.find(`>ssrc-group[semantics="${
1446 1538
                          group.semantics}"]:has(source[ssrc="${
1447 1539
                          group.ssrcs[0]}"])`);
1540
+
1448 1541
                     groupNode.remove();
1449 1542
                 });
1450 1543
             });
@@ -1457,10 +1550,14 @@ export default class JingleSessionPC extends JingleSession {
1457 1550
                 const desc
1458 1551
                     = JingleSessionPC.createDescriptionNode(
1459 1552
                         jingle, ssrcObj.mtype);
1553
+
1554
+                // eslint-disable-next-line newline-per-chained-call
1460 1555
                 const cname = Math.random().toString(36).substring(2);
1556
+
1461 1557
                 ssrcObj.ssrcs.forEach(ssrc => {
1462 1558
                     const sourceNode
1463 1559
                         = desc.find(`>source[ssrc="${ssrc}"]`);
1560
+
1464 1561
                     sourceNode.remove();
1465 1562
                     const sourceXML
1466 1563
                         = '<source xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"'
@@ -1470,6 +1567,7 @@ export default class JingleSessionPC extends JingleSession {
1470 1567
                         + '<parameter xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"'
1471 1568
                         + ` value="${cname}" name="cname" />`
1472 1569
                         + '</source>';
1570
+
1473 1571
                     desc.append(sourceXML);
1474 1572
                 });
1475 1573
                 ssrcObj.groups.forEach(group => {
@@ -1477,6 +1575,7 @@ export default class JingleSessionPC extends JingleSession {
1477 1575
                         = desc.find(
1478 1576
                             `>ssrc-group[semantics="${group.semantics
1479 1577
                                 }"]:has(source[ssrc="${group.ssrcs[0]}"])`);
1578
+
1480 1579
                     groupNode.remove();
1481 1580
                     desc.append(
1482 1581
                         `<ssrc-group semantics="${group.semantics
@@ -1496,6 +1595,7 @@ export default class JingleSessionPC extends JingleSession {
1496 1595
      */
1497 1596
     fixSourceRemoveJingle(jingle) {
1498 1597
         let ssrcs = this.modifiedSSRCs.mute;
1598
+
1499 1599
         this.modifiedSSRCs.mute = [];
1500 1600
         if (ssrcs && ssrcs.length) {
1501 1601
             ssrcs.forEach(ssrcObj => {
@@ -1504,6 +1604,7 @@ export default class JingleSessionPC extends JingleSession {
1504 1604
                         = $(jingle.tree()).find(
1505 1605
                             `>jingle>content[name="${ssrcObj.mtype
1506 1606
                                 }"]>description>source[ssrc="${ssrc}"]`);
1607
+
1507 1608
                     sourceNode.remove();
1508 1609
                 });
1509 1610
                 ssrcObj.groups.forEach(group => {
@@ -1513,6 +1614,7 @@ export default class JingleSessionPC extends JingleSession {
1513 1614
                                 }"]>description>ssrc-group[semantics="${
1514 1615
                                 group.semantics}"]:has(source[ssrc="${
1515 1616
                                 group.ssrcs[0]}"])`);
1617
+
1516 1618
                     groupNode.remove();
1517 1619
                 });
1518 1620
             });
@@ -1525,9 +1627,11 @@ export default class JingleSessionPC extends JingleSession {
1525 1627
                 const desc
1526 1628
                     = JingleSessionPC.createDescriptionNode(
1527 1629
                         jingle, ssrcObj.mtype);
1630
+
1528 1631
                 ssrcObj.ssrcs.forEach(ssrc => {
1529 1632
                     const sourceNode
1530 1633
                         = desc.find(`>source[ssrc="${ssrc}"]`);
1634
+
1531 1635
                     if (!sourceNode || !sourceNode.length) {
1532 1636
                         // Maybe we have to include cname, msid, etc here?
1533 1637
                         desc.append(
@@ -1540,6 +1644,7 @@ export default class JingleSessionPC extends JingleSession {
1540 1644
                         = desc.find(`>ssrc-group[semantics="${
1541 1645
                              group.semantics}"]:has(source[ssrc="${
1542 1646
                              group.ssrcs[0]}"])`);
1647
+
1543 1648
                     if (!groupNode || !groupNode.length) {
1544 1649
                         desc.append(
1545 1650
                             `<ssrc-group semantics="${group.semantics
@@ -1563,18 +1668,21 @@ export default class JingleSessionPC extends JingleSession {
1563 1668
         let content = $(jingle.tree()).find(`>jingle>content[name="${mtype}"]`);
1564 1669
 
1565 1670
         if (!content || !content.length) {
1566
-            $(jingle.tree()).find('>jingle').append(
1567
-                `<content name="${mtype}"></content>`);
1671
+            $(jingle.tree())
1672
+                .find('>jingle')
1673
+                .append(`<content name="${mtype}"></content>`);
1568 1674
             content = $(jingle.tree()).find(`>jingle>content[name="${mtype}"]`);
1569 1675
         }
1570 1676
 
1571 1677
         let desc = content.find('>description');
1678
+
1572 1679
         if (!desc || !desc.length) {
1573 1680
             content.append(
1574 1681
                 `<description xmlns="urn:xmpp:jingle:apps:rtp:1" media="${
1575 1682
                     mtype}"></description>`);
1576 1683
             desc = content.find('>description');
1577 1684
         }
1685
+
1578 1686
         return desc;
1579 1687
     }
1580 1688
 
@@ -1584,6 +1692,7 @@ export default class JingleSessionPC extends JingleSession {
1584 1692
     static getUfrag(sdp) {
1585 1693
         const ufragLines
1586 1694
             = sdp.split('\n').filter(line => line.startsWith('a=ice-ufrag:'));
1695
+
1587 1696
         if (ufragLines.length > 0) {
1588 1697
             return ufragLines[0].substr('a=ice-ufrag:'.length);
1589 1698
         }

+ 17
- 0
modules/xmpp/RtxModifier.js 查看文件

@@ -28,8 +28,10 @@ function updateAssociatedRtxStream(mLine, primarySsrcInfo, rtxSsrc) {
28 28
     const primarySsrcCname = primarySsrcInfo.cname;
29 29
 
30 30
     const previousRtxSSRC = mLine.getRtxSSRC(primarySsrc);
31
+
31 32
     if (previousRtxSSRC === rtxSsrc) {
32 33
         logger.debug(`${rtxSsrc} was already associated with ${primarySsrc}`);
34
+
33 35
         return;
34 36
     }
35 37
     if (previousRtxSSRC) {
@@ -111,28 +113,34 @@ export default class RtxModifier {
111 113
     modifyRtxSsrcs(sdpStr) {
112 114
         const sdpTransformer = new SdpTransformWrap(sdpStr);
113 115
         const videoMLine = sdpTransformer.selectMedia('video');
116
+
114 117
         if (!videoMLine) {
115 118
             logger.error(`No 'video' media found in the sdp: ${sdpStr}`);
119
+
116 120
             return sdpStr;
117 121
         }
118 122
         if (videoMLine.direction === 'inactive'
119 123
                 || videoMLine.direction === 'recvonly') {
120 124
             logger.debug('RtxModifier doing nothing, video '
121 125
                 + 'm line is inactive or recvonly');
126
+
122 127
             return sdpStr;
123 128
         }
124 129
         if (videoMLine.getSSRCCount() < 1) {
125 130
             logger.debug('RtxModifier doing nothing, no video ssrcs present');
131
+
126 132
             return sdpStr;
127 133
         }
128 134
         logger.debug('Current ssrc mapping: ', this.correspondingRtxSsrcs);
129 135
         const primaryVideoSsrcs = videoMLine.getPrimaryVideoSSRCs();
136
+
130 137
         logger.debug('Parsed primary video ssrcs ', primaryVideoSsrcs,
131 138
             ' making sure all have rtx streams');
132 139
         for (const ssrc of primaryVideoSsrcs) {
133 140
             const msid = videoMLine.getSSRCAttrValue(ssrc, 'msid');
134 141
             const cname = videoMLine.getSSRCAttrValue(ssrc, 'cname');
135 142
             let correspondingRtxSsrc = this.correspondingRtxSsrcs.get(ssrc);
143
+
136 144
             if (correspondingRtxSsrc) {
137 145
                 logger.debug(
138 146
                     'Already have an associated rtx ssrc for'
@@ -143,6 +151,7 @@ export default class RtxModifier {
143 151
                 // If there's one in the sdp already for it, we'll just set
144 152
                 //  that as the corresponding one
145 153
                 const previousAssociatedRtxStream = videoMLine.getRtxSSRC(ssrc);
154
+
146 155
                 if (previousAssociatedRtxStream) {
147 156
                     logger.debug(
148 157
                         `Rtx stream ${previousAssociatedRtxStream} `
@@ -167,6 +176,7 @@ export default class RtxModifier {
167 176
                 },
168 177
                 correspondingRtxSsrc);
169 178
         }
179
+
170 180
         return sdpTransformer.toRawSDP();
171 181
     }
172 182
 
@@ -178,31 +188,38 @@ export default class RtxModifier {
178 188
     stripRtx(sdpStr) {
179 189
         const sdpTransformer = new SdpTransformWrap(sdpStr);
180 190
         const videoMLine = sdpTransformer.selectMedia('video');
191
+
181 192
         if (!videoMLine) {
182 193
             logger.error(`No 'video' media found in the sdp: ${sdpStr}`);
194
+
183 195
             return sdpStr;
184 196
         }
185 197
         if (videoMLine.direction === 'inactive'
186 198
                 || videoMLine.direction === 'recvonly') {
187 199
             logger.debug('RtxModifier doing nothing, video '
188 200
                 + 'm line is inactive or recvonly');
201
+
189 202
             return sdpStr;
190 203
         }
191 204
         if (videoMLine.getSSRCCount() < 1) {
192 205
             logger.debug('RtxModifier doing nothing, no video ssrcs present');
206
+
193 207
             return sdpStr;
194 208
         }
195 209
         if (!videoMLine.containsAnySSRCGroups()) {
196 210
             logger.debug('RtxModifier doing nothing, '
197 211
               + 'no video ssrcGroups present');
212
+
198 213
             return sdpStr;
199 214
         }
200 215
         const fidGroups = videoMLine.findGroups('FID');
201 216
         // Remove the fid groups from the mline
217
+
202 218
         videoMLine.removeGroupsBySemantics('FID');
203 219
         // Get the rtx ssrcs and remove them from the mline
204 220
         for (const fidGroup of fidGroups) {
205 221
             const rtxSsrc = parseSecondarySSRC(fidGroup);
222
+
206 223
             videoMLine.removeSSRC(rtxSsrc);
207 224
         }
208 225
 

+ 38
- 0
modules/xmpp/RtxModifier.spec.js 查看文件

@@ -12,6 +12,8 @@ import * as SDPUtil from './SDPUtil';
12 12
  */
13 13
 function numVideoSsrcs(parsedSdp) {
14 14
     const videoMLine = parsedSdp.media.find(m => m.type === 'video');
15
+
16
+
15 17
     return videoMLine.ssrcs
16 18
     .map(ssrcInfo => ssrcInfo.id)
17 19
     .filter((ssrc, index, array) => array.indexOf(ssrc) === index)
@@ -25,6 +27,8 @@ function numVideoSsrcs(parsedSdp) {
25 27
  */
26 28
 function getPrimaryVideoSsrc(parsedSdp) {
27 29
     const videoMLine = parsedSdp.media.find(m => m.type === 'video');
30
+
31
+
28 32
     return parseInt(SDPUtil.parsePrimaryVideoSsrc(videoMLine));
29 33
 }
30 34
 
@@ -38,14 +42,18 @@ function getPrimaryVideoSsrc(parsedSdp) {
38 42
  */
39 43
 function getPrimaryVideoSsrcs(parsedSdp) {
40 44
     const videoMLine = parsedSdp.media.find(m => m.type === 'video');
45
+
41 46
     if (numVideoSsrcs(parsedSdp) === 1) {
42 47
         return [videoMLine.ssrcs[0].id];
43 48
     }
44 49
     const simGroups = getVideoGroups(parsedSdp, 'SIM');
50
+
45 51
     if (simGroups.length > 1) {
46 52
         return;
47 53
     }
48 54
     const simGroup = simGroups[0];
55
+
56
+
49 57
     return SDPUtil.parseGroupSsrcs(simGroup);
50 58
 
51 59
 }
@@ -61,7 +69,9 @@ function getPrimaryVideoSsrcs(parsedSdp) {
61 69
  */
62 70
 function getVideoGroups(parsedSdp, groupSemantics) {
63 71
     const videoMLine = parsedSdp.media.find(m => m.type === 'video');
72
+
64 73
     videoMLine.ssrcGroups = videoMLine.ssrcGroups || [];
74
+
65 75
     return videoMLine.ssrcGroups
66 76
     .filter(g => g.semantics === groupSemantics);
67 77
 }
@@ -85,15 +95,18 @@ describe('RtxModifier', () => {
85 95
                 const newSdpStr = this.rtxModifier.modifyRtxSsrcs(this.transform.write(this.singleVideoSdp));
86 96
                 const newSdp = transform.parse(newSdpStr);
87 97
                 const newPrimaryVideoSsrc = getPrimaryVideoSsrc(newSdp);
98
+
88 99
                 expect(newPrimaryVideoSsrc).toEqual(this.primaryVideoSsrc);
89 100
           // Should now have an rtx ssrc as well
90 101
                 expect(numVideoSsrcs(newSdp)).toEqual(2);
91 102
           // Should now have an FID group
92 103
                 const fidGroups = getVideoGroups(newSdp, 'FID');
104
+
93 105
                 expect(fidGroups.length).toEqual(1);
94 106
 
95 107
                 const fidGroup = fidGroups[0];
96 108
                 const fidGroupPrimarySsrc = SDPUtil.parseGroupSsrcs(fidGroup)[0];
109
+
97 110
                 expect(fidGroupPrimarySsrc).toEqual(this.primaryVideoSsrc);
98 111
             });
99 112
 
@@ -112,6 +125,7 @@ describe('RtxModifier', () => {
112 125
                 newSdp = transform.parse(newSdpStr);
113 126
                 fidGroup = getVideoGroups(newSdp, 'FID')[0];
114 127
                 const newFidGroupRtxSsrc = SDPUtil.parseGroupSsrcs(fidGroup)[1];
128
+
115 129
                 expect(newFidGroupRtxSsrc).toEqual(fidGroupRtxSsrc);
116 130
             });
117 131
 
@@ -125,6 +139,7 @@ describe('RtxModifier', () => {
125 139
 
126 140
                 let fidGroup = getVideoGroups(newSdp, 'FID')[0];
127 141
                 const fidGroupRtxSsrc = SDPUtil.parseGroupSsrcs(fidGroup)[1];
142
+
128 143
                 this.rtxModifier.clearSsrcCache();
129 144
 
130 145
           // Now pass the original sdp through again
@@ -132,6 +147,7 @@ describe('RtxModifier', () => {
132 147
                 newSdp = transform.parse(newSdpStr);
133 148
                 fidGroup = getVideoGroups(newSdp, 'FID')[0];
134 149
                 const newFidGroupRtxSsrc = SDPUtil.parseGroupSsrcs(fidGroup)[1];
150
+
135 151
                 expect(newFidGroupRtxSsrc).not.toEqual(fidGroupRtxSsrc);
136 152
             });
137 153
 
@@ -141,6 +157,7 @@ describe('RtxModifier', () => {
141 157
           // -->The rtx ssrc used should be the one we set
142 158
                 const forcedRtxSsrc = 123456;
143 159
                 const ssrcCache = new Map();
160
+
144 161
                 ssrcCache.set(this.primaryVideoSsrc, forcedRtxSsrc);
145 162
                 this.rtxModifier.setSsrcCache(ssrcCache);
146 163
                 const newSdpStr = this.rtxModifier.modifyRtxSsrcs(this.transform.write(this.singleVideoSdp));
@@ -148,6 +165,7 @@ describe('RtxModifier', () => {
148 165
 
149 166
                 const fidGroup = getVideoGroups(newSdp, 'FID')[0];
150 167
                 const fidGroupRtxSsrc = SDPUtil.parseGroupSsrcs(fidGroup)[1];
168
+
151 169
                 expect(fidGroupRtxSsrc).toEqual(forcedRtxSsrc);
152 170
             });
153 171
         });
@@ -164,14 +182,17 @@ describe('RtxModifier', () => {
164 182
                 const newSdpStr = this.rtxModifier.modifyRtxSsrcs(this.transform.write(this.multipleVideoSdp));
165 183
                 const newSdp = transform.parse(newSdpStr);
166 184
                 const newPrimaryVideoSsrcs = getPrimaryVideoSsrcs(newSdp);
185
+
167 186
                 expect(newPrimaryVideoSsrcs).toEqual(this.primaryVideoSsrcs);
168 187
           // Should now have rtx ssrcs as well
169 188
                 expect(numVideoSsrcs(newSdp)).toEqual(this.primaryVideoSsrcs.length * 2);
170 189
           // Should now have FID groups
171 190
                 const fidGroups = getVideoGroups(newSdp, 'FID');
191
+
172 192
                 expect(fidGroups.length).toEqual(this.primaryVideoSsrcs.length);
173 193
                 fidGroups.forEach(fidGroup => {
174 194
                     const fidGroupPrimarySsrc = SDPUtil.parseGroupSsrcs(fidGroup)[0];
195
+
175 196
                     expect(this.primaryVideoSsrcs.indexOf(fidGroupPrimarySsrc)).not.toEqual(-1);
176 197
                 });
177 198
             });
@@ -186,10 +207,12 @@ describe('RtxModifier', () => {
186 207
                 const rtxMapping = new Map();
187 208
                 let fidGroups = getVideoGroups(newSdp, 'FID');
188 209
           // Save the first mapping that is made
210
+
189 211
                 fidGroups.forEach(fidGroup => {
190 212
                     const fidSsrcs = SDPUtil.parseGroupSsrcs(fidGroup);
191 213
                     const fidGroupPrimarySsrc = fidSsrcs[0];
192 214
                     const fidGroupRtxSsrc = fidSsrcs[1];
215
+
193 216
                     rtxMapping.set(fidGroupPrimarySsrc, fidGroupRtxSsrc);
194 217
                 });
195 218
           // Now pass the original sdp through again and make sure we get the same mapping
@@ -200,6 +223,7 @@ describe('RtxModifier', () => {
200 223
                     const fidSsrcs = SDPUtil.parseGroupSsrcs(fidGroup);
201 224
                     const fidGroupPrimarySsrc = fidSsrcs[0];
202 225
                     const fidGroupRtxSsrc = fidSsrcs[1];
226
+
203 227
                     expect(rtxMapping.has(fidGroupPrimarySsrc)).toBe(true);
204 228
                     expect(rtxMapping.get(fidGroupPrimarySsrc)).toEqual(fidGroupRtxSsrc);
205 229
                 });
@@ -216,10 +240,12 @@ describe('RtxModifier', () => {
216 240
                 const rtxMapping = new Map();
217 241
                 let fidGroups = getVideoGroups(newSdp, 'FID');
218 242
           // Save the first mapping that is made
243
+
219 244
                 fidGroups.forEach(fidGroup => {
220 245
                     const fidSsrcs = SDPUtil.parseGroupSsrcs(fidGroup);
221 246
                     const fidGroupPrimarySsrc = fidSsrcs[0];
222 247
                     const fidGroupRtxSsrc = fidSsrcs[1];
248
+
223 249
                     rtxMapping.set(fidGroupPrimarySsrc, fidGroupRtxSsrc);
224 250
                 });
225 251
 
@@ -232,6 +258,7 @@ describe('RtxModifier', () => {
232 258
                     const fidSsrcs = SDPUtil.parseGroupSsrcs(fidGroup);
233 259
                     const fidGroupPrimarySsrc = fidSsrcs[0];
234 260
                     const fidGroupRtxSsrc = fidSsrcs[1];
261
+
235 262
                     expect(rtxMapping.has(fidGroupPrimarySsrc)).toBe(true);
236 263
                     expect(rtxMapping.get(fidGroupPrimarySsrc)).not.toEqual(fidGroupRtxSsrc);
237 264
                 });
@@ -242,6 +269,7 @@ describe('RtxModifier', () => {
242 269
           // Call modifyRtxSsrcs
243 270
           // -->The rtx ssrc used should be the one we set
244 271
                 const rtxMapping = new Map();
272
+
245 273
                 this.primaryVideoSsrcs.forEach(ssrc => {
246 274
                     rtxMapping.set(ssrc, SDPUtil.generateSsrc());
247 275
                 });
@@ -251,10 +279,12 @@ describe('RtxModifier', () => {
251 279
                 const newSdp = transform.parse(newSdpStr);
252 280
 
253 281
                 const fidGroups = getVideoGroups(newSdp, 'FID');
282
+
254 283
                 fidGroups.forEach(fidGroup => {
255 284
                     const fidSsrcs = SDPUtil.parseGroupSsrcs(fidGroup);
256 285
                     const fidGroupPrimarySsrc = fidSsrcs[0];
257 286
                     const fidGroupRtxSsrc = fidSsrcs[1];
287
+
258 288
                     expect(rtxMapping.has(fidGroupPrimarySsrc)).toBe(true);
259 289
                     expect(rtxMapping.get(fidGroupPrimarySsrc)).toEqual(fidGroupRtxSsrc);
260 290
                 });
@@ -265,24 +295,30 @@ describe('RtxModifier', () => {
265 295
             it('should handle a recvonly video mline', function() {
266 296
                 const sdp = SampleSdpStrings.plainVideoSdp;
267 297
                 const videoMLine = sdp.media.find(m => m.type === 'video');
298
+
268 299
                 videoMLine.direction = 'recvonly';
269 300
                 const newSdpStr = this.rtxModifier.modifyRtxSsrcs(this.transform.write(sdp));
301
+
270 302
                 expect(newSdpStr).toEqual(this.transform.write(sdp));
271 303
             });
272 304
 
273 305
             it('should handle an inactive video mline', function() {
274 306
                 const sdp = SampleSdpStrings.plainVideoSdp;
275 307
                 const videoMLine = sdp.media.find(m => m.type === 'video');
308
+
276 309
                 videoMLine.direction = 'inactive';
277 310
                 const newSdpStr = this.rtxModifier.modifyRtxSsrcs(this.transform.write(sdp));
311
+
278 312
                 expect(newSdpStr).toEqual(this.transform.write(sdp));
279 313
             });
280 314
 
281 315
             it('should handle a video mline with no video ssrcs', function() {
282 316
                 const sdp = SampleSdpStrings.plainVideoSdp;
283 317
                 const videoMLine = sdp.media.find(m => m.type === 'video');
318
+
284 319
                 videoMLine.ssrcs = [];
285 320
                 const newSdpStr = this.rtxModifier.modifyRtxSsrcs(this.transform.write(sdp));
321
+
286 322
                 expect(newSdpStr).toEqual(this.transform.write(sdp));
287 323
             });
288 324
         });
@@ -295,12 +331,14 @@ describe('RtxModifier', () => {
295 331
             const newSdpStr = this.rtxModifier.stripRtx(sdpStr);
296 332
             const newSdp = transform.parse(newSdpStr);
297 333
             const fidGroups = getVideoGroups(newSdp, 'FID');
334
+
298 335
             expect(fidGroups.length).toEqual(0);
299 336
             expect(numVideoSsrcs(newSdp)).toEqual(1);
300 337
         });
301 338
         it('should do nothing to an sdp with no rtx', function() {
302 339
             const sdpStr = transform.write(SampleSdpStrings.plainVideoSdp);
303 340
             const newSdpStr = this.rtxModifier.stripRtx(sdpStr);
341
+
304 342
             expect(newSdpStr).toEqual(sdpStr);
305 343
         });
306 344
     });

+ 93
- 17
modules/xmpp/SDP.js 查看文件

@@ -5,8 +5,10 @@ const SDPUtil = require('./SDPUtil');
5 5
 // SDP STUFF
6 6
 function SDP(sdp) {
7 7
     const media = sdp.split('\r\nm=');
8
+
8 9
     for (let i = 1, length = media.length; i < length; i++) {
9 10
         let media_i = `m=${media[i]}`;
11
+
10 12
         if (i != length - 1) {
11 13
             media_i += '\r\n';
12 14
         }
@@ -46,6 +48,7 @@ SDP.prototype.getMediaSsrcMap = function() {
46 48
     const self = this;
47 49
     const media_ssrcs = {};
48 50
     let tmp;
51
+
49 52
     for (let mediaindex = 0; mediaindex < self.media.length; mediaindex++) {
50 53
         tmp = SDPUtil.find_lines(self.media[mediaindex], 'a=ssrc:');
51 54
         const mid = SDPUtil.parse_mid(SDPUtil.find_line(self.media[mediaindex], 'a=mid:'));
@@ -55,10 +58,12 @@ SDP.prototype.getMediaSsrcMap = function() {
55 58
             ssrcs: {},
56 59
             ssrcGroups: []
57 60
         };
61
+
58 62
         media_ssrcs[mediaindex] = media;
59 63
         tmp.forEach(line => {
60 64
             const linessrc = line.substring(7).split(' ')[0];
61 65
             // allocate new ChannelSsrc
66
+
62 67
             if(!media.ssrcs[linessrc]) {
63 68
                 media.ssrcs[linessrc] = {
64 69
                     ssrc: linessrc,
@@ -72,6 +77,7 @@ SDP.prototype.getMediaSsrcMap = function() {
72 77
             const idx = line.indexOf(' ');
73 78
             const semantics = line.substr(0, idx).substr(13);
74 79
             const ssrcs = line.substr(14 + semantics.length).split(' ');
80
+
75 81
             if (ssrcs.length) {
76 82
                 media.ssrcGroups.push({
77 83
                     semantics,
@@ -80,6 +86,7 @@ SDP.prototype.getMediaSsrcMap = function() {
80 86
             }
81 87
         });
82 88
     }
89
+
83 90
     return media_ssrcs;
84 91
 };
85 92
 /**
@@ -91,6 +98,7 @@ SDP.prototype.containsSSRC = function(ssrc) {
91 98
     // FIXME this code is really strange - improve it if you can
92 99
     const medias = this.getMediaSsrcMap();
93 100
     let result = false;
101
+
94 102
     Object.keys(medias).forEach(mediaindex => {
95 103
         if (result) {
96 104
             return;
@@ -99,12 +107,14 @@ SDP.prototype.containsSSRC = function(ssrc) {
99 107
             result = true;
100 108
         }
101 109
     });
110
+
102 111
     return result;
103 112
 };
104 113
 
105 114
 // remove iSAC and CN from SDP
106 115
 SDP.prototype.mangle = function() {
107 116
     let i, j, lines, mline, newdesc, rtpmap;
117
+
108 118
     for (i = 0; i < this.media.length; i++) {
109 119
         lines = this.media[i].split('\r\n');
110 120
         lines.pop(); // remove empty last element
@@ -133,10 +143,12 @@ SDP.prototype.mangle = function() {
133 143
 SDP.prototype.removeSessionLines = function(prefix) {
134 144
     const self = this;
135 145
     const lines = SDPUtil.find_lines(this.session, prefix);
146
+
136 147
     lines.forEach(line => {
137 148
         self.session = self.session.replace(`${line}\r\n`, '');
138 149
     });
139 150
     this.raw = this.session + this.media.join('');
151
+
140 152
     return lines;
141 153
 };
142 154
 // remove lines matching prefix from a media section specified by mediaindex
@@ -144,11 +156,13 @@ SDP.prototype.removeSessionLines = function(prefix) {
144 156
 SDP.prototype.removeMediaLines = function(mediaindex, prefix) {
145 157
     const self = this;
146 158
     const lines = SDPUtil.find_lines(this.media[mediaindex], prefix);
159
+
147 160
     lines.forEach(line => {
148 161
         self.media[mediaindex]
149 162
             = self.media[mediaindex].replace(`${line}\r\n`, '');
150 163
     });
151 164
     this.raw = this.session + this.media.join('');
165
+
152 166
     return lines;
153 167
 };
154 168
 
@@ -156,11 +170,13 @@ SDP.prototype.removeMediaLines = function(mediaindex, prefix) {
156 170
 SDP.prototype.toJingle = function(elem, thecreator) {
157 171
     let i, j, k, lines, mline, rtpmap, ssrc, tmp;
158 172
     // new bundle plan
173
+
159 174
     lines = SDPUtil.find_lines(this.session, 'a=group:');
160 175
     if (lines.length) {
161 176
         for (i = 0; i < lines.length; i++) {
162 177
             tmp = lines[i].split(' ');
163 178
             const semantics = tmp.shift().substr(8);
179
+
164 180
             elem.c('group', {xmlns: 'urn:xmpp:jingle:apps:grouping:0', semantics});
165 181
             for (j = 0; j < tmp.length; j++) {
166 182
                 elem.c('content', {name: tmp[j]}).up();
@@ -176,6 +192,7 @@ SDP.prototype.toJingle = function(elem, thecreator) {
176 192
             continue; // eslint-disable-line no-continue
177 193
         }
178 194
         const assrcline = SDPUtil.find_line(this.media[i], 'a=ssrc:');
195
+
179 196
         if (assrcline) {
180 197
             ssrc = assrcline.substring(7).split(' ')[0]; // take the first
181 198
         } else {
@@ -184,9 +201,11 @@ SDP.prototype.toJingle = function(elem, thecreator) {
184 201
 
185 202
         elem.c('content', {creator: thecreator, name: mline.media});
186 203
         const amidline = SDPUtil.find_line(this.media[i], 'a=mid:');
204
+
187 205
         if (amidline) {
188 206
             // prefer identifier from a=mid if present
189 207
             const mid = SDPUtil.parse_mid(amidline);
208
+
190 209
             elem.attrs({ name: mid });
191 210
         }
192 211
 
@@ -202,6 +221,7 @@ SDP.prototype.toJingle = function(elem, thecreator) {
202 221
                 elem.c('payload-type', SDPUtil.parse_rtpmap(rtpmap));
203 222
                 // put any 'a=fmtp:' + mline.fmt[j] lines into <param name=foo value=bar/>
204 223
                 const afmtpline = SDPUtil.find_line(this.media[i], `a=fmtp:${mline.fmt[j]}`);
224
+
205 225
                 if (afmtpline) {
206 226
                     tmp = SDPUtil.parse_fmtp(afmtpline);
207 227
                     for (k = 0; k < tmp.length; k++) {
@@ -213,6 +233,7 @@ SDP.prototype.toJingle = function(elem, thecreator) {
213 233
                 elem.up();
214 234
             }
215 235
             const crypto = SDPUtil.find_lines(this.media[i], 'a=crypto:', this.session);
236
+
216 237
             if (crypto.length) {
217 238
                 elem.c('encryption', {required: 1});
218 239
                 crypto.forEach(
@@ -225,24 +246,29 @@ SDP.prototype.toJingle = function(elem, thecreator) {
225 246
                 elem.c('source', { ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
226 247
                 // FIXME: group by ssrc and support multiple different ssrcs
227 248
                 const ssrclines = SDPUtil.find_lines(this.media[i], 'a=ssrc:');
249
+
228 250
                 if(ssrclines.length > 0) {
229 251
                     ssrclines.forEach(line => {
230 252
                         const idx = line.indexOf(' ');
231 253
                         const linessrc = line.substr(0, idx).substr(7);
254
+
232 255
                         if (linessrc != ssrc) {
233 256
                             elem.up();
234 257
                             ssrc = linessrc;
235 258
                             elem.c('source', { ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
236 259
                         }
237 260
                         const kv = line.substr(idx + 1);
261
+
238 262
                         elem.c('parameter');
239 263
                         if (kv.indexOf(':') == -1) {
240 264
                             elem.attrs({ name: kv });
241 265
                         } else {
242 266
                             const k = kv.split(':', 2)[0];
267
+
243 268
                             elem.attrs({ name: k });
244 269
 
245 270
                             let v = kv.split(':', 2)[1];
271
+
246 272
                             v = SDPUtil.filter_special_chars(v);
247 273
                             elem.attrs({ value: v });
248 274
                         }
@@ -252,12 +278,18 @@ SDP.prototype.toJingle = function(elem, thecreator) {
252 278
                     elem.up();
253 279
                     elem.c('source', { ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
254 280
                     elem.c('parameter');
255
-                    elem.attrs({name: 'cname', value:Math.random().toString(36).substring(7)});
281
+                    elem.attrs({
282
+                        name: 'cname',
283
+
284
+                        // eslint-disable-next-line newline-per-chained-call
285
+                        value: Math.random().toString(36).substring(7)
286
+                    });
256 287
                     elem.up();
257 288
                     // FIXME what case does this code handle ? remove ???
258 289
                     let msid = null;
259 290
                     // FIXME what is this ? global APP.RTC in SDP ?
260 291
                     const localTrack = APP.RTC.getLocalTracks(mline.media);
292
+
261 293
                     if (localTrack) {
262 294
                         // FIXME before this changes the track id was accessed,
263 295
                         // but msid stands for the stream id, makes no sense ?
@@ -280,10 +312,12 @@ SDP.prototype.toJingle = function(elem, thecreator) {
280 312
 
281 313
                 // XEP-0339 handle ssrc-group attributes
282 314
                 const ssrc_group_lines = SDPUtil.find_lines(this.media[i], 'a=ssrc-group:');
315
+
283 316
                 ssrc_group_lines.forEach(line => {
284 317
                     const idx = line.indexOf(' ');
285 318
                     const semantics = line.substr(0, idx).substr(13);
286 319
                     const ssrcs = line.substr(14 + semantics.length).split(' ');
320
+
287 321
                     if (ssrcs.length) {
288 322
                         elem.c('ssrc-group', { semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
289 323
                         ssrcs.forEach(ssrc => elem.c('source', { ssrc }).up());
@@ -349,19 +383,23 @@ SDP.prototype.toJingle = function(elem, thecreator) {
349 383
         elem.up(); // end of content
350 384
     }
351 385
     elem.up();
386
+
352 387
     return elem;
353 388
 };
354 389
 
355 390
 SDP.prototype.transportToJingle = function(mediaindex, elem) {
356 391
     let tmp;
357 392
     const self = this;
393
+
358 394
     elem.c('transport');
359 395
 
360 396
     // XEP-0343 DTLS/SCTP
361 397
     const sctpmap
362 398
         = SDPUtil.find_line(this.media[mediaindex], 'a=sctpmap:', self.session);
399
+
363 400
     if (sctpmap) {
364 401
         const sctpAttrs = SDPUtil.parse_sctpmap(sctpmap);
402
+
365 403
         elem.c('sctpmap', {
366 404
             xmlns: 'urn:xmpp:jingle:transports:dtls-sctp:1',
367 405
             number: sctpAttrs[0], /* SCTP port */
@@ -376,6 +414,7 @@ SDP.prototype.transportToJingle = function(mediaindex, elem) {
376 414
     // XEP-0320
377 415
     const fingerprints
378 416
         = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
417
+
379 418
     fingerprints.forEach(line => {
380 419
         tmp = SDPUtil.parse_fingerprint(line);
381 420
         tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0';
@@ -395,14 +434,17 @@ SDP.prototype.transportToJingle = function(mediaindex, elem) {
395 434
         // XEP-0176
396 435
         if (SDPUtil.find_line(this.media[mediaindex], 'a=candidate:', this.session)) { // add any a=candidate lines
397 436
             const lines = SDPUtil.find_lines(this.media[mediaindex], 'a=candidate:', this.session);
437
+
398 438
             lines.forEach(line => {
399 439
                 const candidate = SDPUtil.candidateToJingle(line);
440
+
400 441
                 if (self.failICE) {
401 442
                     candidate.ip = '1.1.1.1';
402 443
                 }
403 444
                 const protocol = candidate
404 445
                         && typeof candidate.protocol === 'string'
405 446
                     ? candidate.protocol.toLowerCase() : '';
447
+
406 448
                 if ((self.removeTcpCandidates
407 449
                         && (protocol === 'tcp' || protocol === 'ssltcp'))
408 450
                     || (self.removeUdpCandidates && protocol === 'udp')) {
@@ -417,8 +459,10 @@ SDP.prototype.transportToJingle = function(mediaindex, elem) {
417 459
 
418 460
 SDP.prototype.rtcpFbToJingle = function(mediaindex, elem, payloadtype) { // XEP-0293
419 461
     const lines = SDPUtil.find_lines(this.media[mediaindex], `a=rtcp-fb:${payloadtype}`);
462
+
420 463
     lines.forEach(line => {
421 464
         const tmp = SDPUtil.parse_rtcpfb(line);
465
+
422 466
         if (tmp.type == 'trr-int') {
423 467
             elem.c('rtcp-fb-trr-int', {xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0', value: tmp.params[0]});
424 468
             elem.up();
@@ -435,6 +479,7 @@ SDP.prototype.rtcpFbToJingle = function(mediaindex, elem, payloadtype) { // XEP-
435 479
 SDP.prototype.rtcpFbFromJingle = function(elem, payloadtype) { // XEP-0293
436 480
     let media = '';
437 481
     let tmp = elem.find('>rtcp-fb-trr-int[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]');
482
+
438 483
     if (tmp.length) {
439 484
         media += 'a=rtcp-fb:' + '*' + ' ' + 'trr-int' + ' ';
440 485
         if (tmp.attr('value')) {
@@ -452,22 +497,34 @@ SDP.prototype.rtcpFbFromJingle = function(elem, payloadtype) { // XEP-0293
452 497
         }
453 498
         media += '\r\n';
454 499
     });
500
+
455 501
     return media;
456 502
 };
457 503
 
458 504
 // construct an SDP from a jingle stanza
459 505
 SDP.prototype.fromJingle = function(jingle) {
460 506
     const self = this;
507
+
461 508
     this.raw = 'v=0\r\n'
462 509
         + 'o=- 1923518516 2 IN IP4 0.0.0.0\r\n'// FIXME
463 510
         + 's=-\r\n'
464 511
         + 't=0 0\r\n';
512
+
465 513
     // http://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-04#section-8
466
-    if ($(jingle).find('>group[xmlns="urn:xmpp:jingle:apps:grouping:0"]').length) {
467
-        $(jingle).find('>group[xmlns="urn:xmpp:jingle:apps:grouping:0"]').each((idx, group) => {
468
-            const contents = $(group).find('>content').map((idx, content) => content.getAttribute('name')).get();
514
+    const groups
515
+        = $(jingle).find('>group[xmlns="urn:xmpp:jingle:apps:grouping:0"]');
516
+
517
+    if (groups.length) {
518
+        groups.each((idx, group) => {
519
+            const contents
520
+                = $(group)
521
+                    .find('>content')
522
+                    .map((idx, content) => content.getAttribute('name'))
523
+                    .get();
524
+
469 525
             if (contents.length > 0) {
470
-                self.raw += `a=group:${group.getAttribute('semantics') || group.getAttribute('type')} ${contents.join(' ')}\r\n`;
526
+                self.raw
527
+                    += `a=group:${group.getAttribute('semantics') || group.getAttribute('type')} ${contents.join(' ')}\r\n`;
471 528
             }
472 529
         });
473 530
     }
@@ -475,6 +532,7 @@ SDP.prototype.fromJingle = function(jingle) {
475 532
     this.session = this.raw;
476 533
     jingle.find('>content').each(function() {
477 534
         const m = self.jingle2media($(this));
535
+
478 536
         self.media.push(m);
479 537
     });
480 538
 
@@ -498,6 +556,7 @@ SDP.prototype.jingle2media = function(content) {
498 556
         '>transport>sctpmap[xmlns="urn:xmpp:jingle:transports:dtls-sctp:1"]');
499 557
 
500 558
     let tmp = { media: desc.attr('media') };
559
+
501 560
     tmp.port = '1';
502 561
     if (content.attr('senders') == 'rejected') {
503 562
         // estos hack to reject an m-line.
@@ -514,16 +573,20 @@ SDP.prototype.jingle2media = function(content) {
514 573
         media += `a=sctpmap:${sctp.attr('number')} ${sctp.attr('protocol')}`;
515 574
 
516 575
         const streamCount = sctp.attr('streams');
576
+
517 577
         if (streamCount) {
518 578
             media += ` ${streamCount}\r\n`;
519 579
         } else {
520 580
             media += '\r\n';
521 581
         }
522 582
     } else {
523
-        tmp.fmt = desc.find('payload-type').map(
524
-            function() {
525
-                return this.getAttribute('id');
526
-            }).get();
583
+        tmp.fmt
584
+            = desc
585
+                .find('payload-type')
586
+                .map(function() {
587
+                    return this.getAttribute('id');
588
+                })
589
+                .get();
527 590
         media += `${SDPUtil.build_mline(tmp)}\r\n`;
528 591
     }
529 592
 
@@ -587,11 +650,16 @@ SDP.prototype.jingle2media = function(content) {
587 650
         media += `${SDPUtil.build_rtpmap(this)}\r\n`;
588 651
         if ($(this).find('>parameter').length) {
589 652
             media += `a=fmtp:${this.getAttribute('id')} `;
590
-            media += $(this).find('parameter').map(function() {
591
-                return (this.getAttribute('name')
592
-                        ? `${this.getAttribute('name')}=` : '')
593
-                    + this.getAttribute('value');
594
-            }).get().join('; ');
653
+            media
654
+                += $(this)
655
+                    .find('parameter')
656
+                    .map(function() {
657
+                        return (this.getAttribute('name')
658
+                                ? `${this.getAttribute('name')}=` : '')
659
+                            + this.getAttribute('value');
660
+                    })
661
+                    .get()
662
+                    .join('; ');
595 663
             media += '\r\n';
596 664
         }
597 665
         // xep-0293
@@ -609,6 +677,7 @@ SDP.prototype.jingle2media = function(content) {
609 677
 
610 678
     content.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]>candidate').each(function() {
611 679
         let protocol = this.getAttribute('protocol');
680
+
612 681
         protocol = typeof protocol === 'string' ? protocol.toLowerCase() : '';
613 682
 
614 683
         if ((self.removeTcpCandidates
@@ -625,9 +694,13 @@ SDP.prototype.jingle2media = function(content) {
625 694
     // XEP-0339 handle ssrc-group attributes
626 695
     content.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
627 696
         const semantics = this.getAttribute('semantics');
628
-        const ssrcs = $(this).find('>source').map(function() {
629
-            return this.getAttribute('ssrc');
630
-        }).get();
697
+        const ssrcs
698
+            = $(this)
699
+                .find('>source')
700
+                .map(function() {
701
+                    return this.getAttribute('ssrc');
702
+                })
703
+                .get();
631 704
 
632 705
         if (ssrcs.length) {
633 706
             media += `a=ssrc-group:${semantics} ${ssrcs.join(' ')}\r\n`;
@@ -637,9 +710,12 @@ SDP.prototype.jingle2media = function(content) {
637 710
     tmp = content.find('description>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
638 711
     tmp.each(function() {
639 712
         const ssrc = this.getAttribute('ssrc');
713
+
714
+        // eslint-disable-next-line newline-per-chained-call
640 715
         $(this).find('>parameter').each(function() {
641 716
             const name = this.getAttribute('name');
642 717
             let value = this.getAttribute('value');
718
+
643 719
             value = SDPUtil.filter_special_chars(value);
644 720
             media += `a=ssrc:${ssrc} ${name}`;
645 721
             if (value && value.length) {

+ 12
- 0
modules/xmpp/SDPDiffer.js 查看文件

@@ -36,18 +36,22 @@ SDPDiffer.prototype.getNewMedia = function() {
36 36
                 return false;
37 37
             }
38 38
         }
39
+
39 40
         return true;
40 41
     }
41 42
 
42 43
     const myMedias = this.mySDP.getMediaSsrcMap();
43 44
     const othersMedias = this.otherSDP.getMediaSsrcMap();
44 45
     const newMedia = {};
46
+
45 47
     Object.keys(othersMedias).forEach(othersMediaIdx => {
46 48
         const myMedia = myMedias[othersMediaIdx];
47 49
         const othersMedia = othersMedias[othersMediaIdx];
50
+
48 51
         if(!myMedia && othersMedia) {
49 52
             // Add whole channel
50 53
             newMedia[othersMediaIdx] = othersMedia;
54
+
51 55
             return;
52 56
         }
53 57
         // Look for new ssrcs across the channel
@@ -72,8 +76,10 @@ SDPDiffer.prototype.getNewMedia = function() {
72 76
 
73 77
             // try to match the other ssrc-group with an ssrc-group of ours
74 78
             let matched = false;
79
+
75 80
             for (let i = 0; i < myMedia.ssrcGroups.length; i++) {
76 81
                 const mySsrcGroup = myMedia.ssrcGroups[i];
82
+
77 83
                 if (otherSsrcGroup.semantics == mySsrcGroup.semantics
78 84
                     && arrayEquals.apply(otherSsrcGroup.ssrcs,
79 85
                                       [mySsrcGroup.ssrcs])) {
@@ -99,6 +105,7 @@ SDPDiffer.prototype.getNewMedia = function() {
99 105
             }
100 106
         });
101 107
     });
108
+
102 109
     return newMedia;
103 110
 };
104 111
 
@@ -109,9 +116,11 @@ SDPDiffer.prototype.toJingle = function(modify) {
109 116
     const sdpMediaSsrcs = this.getNewMedia();
110 117
 
111 118
     let modified = false;
119
+
112 120
     Object.keys(sdpMediaSsrcs).forEach(mediaindex => {
113 121
         modified = true;
114 122
         const media = sdpMediaSsrcs[mediaindex];
123
+
115 124
         modify.c('content', {name: media.mid});
116 125
 
117 126
         modify.c('description',
@@ -121,12 +130,14 @@ SDPDiffer.prototype.toJingle = function(modify) {
121 130
         // generate sources from lines
122 131
         Object.keys(media.ssrcs).forEach(ssrcNum => {
123 132
             const mediaSsrc = media.ssrcs[ssrcNum];
133
+
124 134
             modify.c('source', { xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
125 135
             modify.attrs({ssrc: mediaSsrc.ssrc});
126 136
             // iterate over ssrc lines
127 137
             mediaSsrc.lines.forEach(line => {
128 138
                 const idx = line.indexOf(' ');
129 139
                 const kv = line.substr(idx + 1);
140
+
130 141
                 modify.c('parameter');
131 142
                 if (kv.indexOf(':') == -1) {
132 143
                     modify.attrs({ name: kv });
@@ -134,6 +145,7 @@ SDPDiffer.prototype.toJingle = function(modify) {
134 145
                     const nv = kv.split(':', 2);
135 146
                     const name = nv[0];
136 147
                     const value = SDPUtil.filter_special_chars(nv[1]);
148
+
137 149
                     modify.attrs({ name });
138 150
                     modify.attrs({ value });
139 151
                 }

+ 49
- 2
modules/xmpp/SDPUtil.js 查看文件

@@ -1,5 +1,6 @@
1 1
 import {getLogger} from 'jitsi-meet-logger';
2 2
 const logger = getLogger(__filename);
3
+
3 4
 import RandomUtil from '../util/RandomUtil';
4 5
 const RTCBrowserType = require('../RTC/RTCBrowserType');
5 6
 
@@ -12,6 +13,7 @@ const SDPUtil = {
12 13
     iceparams(mediadesc, sessiondesc) {
13 14
         let data = null;
14 15
         let pwd, ufrag;
16
+
15 17
         if ((ufrag = SDPUtil.find_line(mediadesc, 'a=ice-ufrag:', sessiondesc))
16 18
                 && (pwd = SDPUtil.find_line(mediadesc, 'a=ice-pwd:', sessiondesc))) {
17 19
             data = {
@@ -19,6 +21,7 @@ const SDPUtil = {
19 21
                 pwd: SDPUtil.parse_icepwd(pwd)
20 22
             };
21 23
         }
24
+
22 25
         return data;
23 26
     },
24 27
     parse_iceufrag(line) {
@@ -47,6 +50,7 @@ const SDPUtil = {
47 50
             parts.pop();
48 51
         }
49 52
         data.fmt = parts;
53
+
50 54
         return data;
51 55
     },
52 56
     build_mline(mline) {
@@ -61,6 +65,7 @@ const SDPUtil = {
61 65
         data.name = parts.shift();
62 66
         data.clockrate = parts.shift();
63 67
         data.channels = parts.length ? parts.shift() : '1';
68
+
64 69
         return data;
65 70
     },
66 71
     /**
@@ -74,13 +79,17 @@ const SDPUtil = {
74 79
         const protocol = parts[1];
75 80
         // Stream count is optional
76 81
         const streamCount = parts.length > 2 ? parts[2] : null;
82
+
83
+
77 84
         return [sctpPort, protocol, streamCount];// SCTP port
78 85
     },
79 86
     build_rtpmap(el) {
80 87
         let line = `a=rtpmap:${el.getAttribute('id')} ${el.getAttribute('name')}/${el.getAttribute('clockrate')}`;
88
+
81 89
         if (el.getAttribute('channels') && el.getAttribute('channels') != '1') {
82 90
             line += `/${el.getAttribute('channels')}`;
83 91
         }
92
+
84 93
         return line;
85 94
     },
86 95
     parse_crypto(line) {
@@ -93,6 +102,7 @@ const SDPUtil = {
93 102
         if (parts.length) {
94 103
             data['session-params'] = parts.join(' ');
95 104
         }
105
+
96 106
         return data;
97 107
     },
98 108
     parse_fingerprint(line) { // RFC 4572
@@ -101,6 +111,7 @@ const SDPUtil = {
101 111
 
102 112
         data.hash = parts.shift();
103 113
         data.fingerprint = parts.shift();
114
+
104 115
         // TODO assert that fingerprint satisfies 2UHEX *(":" 2UHEX) ?
105 116
         return data;
106 117
     },
@@ -112,10 +123,12 @@ const SDPUtil = {
112 123
         parts = parts.join(' ').split(';');
113 124
         for (let i = 0; i < parts.length; i++) {
114 125
             let key = parts[i].split('=')[0];
126
+
115 127
             while (key.length && key[0] == ' ') {
116 128
                 key = key.substring(1);
117 129
             }
118 130
             const value = parts[i].split('=')[1];
131
+
119 132
             if (key && value) {
120 133
                 data.push({name: key, value});
121 134
             } else if (key) {
@@ -123,6 +136,7 @@ const SDPUtil = {
123 136
                 data.push({name: '', value: key});
124 137
             }
125 138
         }
139
+
126 140
         return data;
127 141
     },
128 142
     parse_icecandidate(line) {
@@ -157,11 +171,16 @@ const SDPUtil = {
157 171
             }
158 172
         }
159 173
         candidate.network = '1';
160
-        candidate.id = Math.random().toString(36).substr(2, 10); // not applicable to SDP -- FIXME: should be unique, not just random
174
+
175
+        // not applicable to SDP -- FIXME: should be unique, not just random
176
+        // eslint-disable-next-line newline-per-chained-call
177
+        candidate.id = Math.random().toString(36).substr(2, 10);
178
+
161 179
         return candidate;
162 180
     },
163 181
     build_icecandidate(cand) {
164 182
         let line = [`a=candidate:${cand.foundation}`, cand.component, cand.protocol, cand.priority, cand.ip, cand.port, 'typ', cand.type].join(' ');
183
+
165 184
         line += ' ';
166 185
         switch (cand.type) {
167 186
         case 'srflx':
@@ -188,6 +207,7 @@ const SDPUtil = {
188 207
         line += 'generation';
189 208
         line += ' ';
190 209
         line += cand.hasOwnAttribute('generation') ? cand.generation : '0';
210
+
191 211
         return line;
192 212
     },
193 213
     parse_ssrc(desc) {
@@ -200,22 +220,27 @@ const SDPUtil = {
200 220
         for (let i = 0; i < lines.length; i++) {
201 221
             if (lines[i].substring(0, 7) == 'a=ssrc:') {
202 222
                 const idx = lines[i].indexOf(' ');
223
+
203 224
                 data[lines[i].substr(idx + 1).split(':', 2)[0]] = lines[i].substr(idx + 1).split(':', 2)[1];
204 225
             }
205 226
         }
227
+
206 228
         return data;
207 229
     },
208 230
     parse_rtcpfb(line) {
209 231
         const parts = line.substr(10).split(' ');
210 232
         const data = {};
233
+
211 234
         data.pt = parts.shift();
212 235
         data.type = parts.shift();
213 236
         data.params = parts;
237
+
214 238
         return data;
215 239
     },
216 240
     parse_extmap(line) {
217 241
         const parts = line.substr(9).split(' ');
218 242
         const data = {};
243
+
219 244
         data.value = parts.shift();
220 245
         if (data.value.indexOf('/') === -1) {
221 246
             data.direction = 'both';
@@ -225,10 +250,12 @@ const SDPUtil = {
225 250
         }
226 251
         data.uri = parts.shift();
227 252
         data.params = parts;
253
+
228 254
         return data;
229 255
     },
230 256
     find_line(haystack, needle, sessionpart) {
231 257
         let lines = haystack.split('\r\n');
258
+
232 259
         for (let i = 0; i < lines.length; i++) {
233 260
             if (lines[i].substring(0, needle.length) == needle) {
234 261
                 return lines[i];
@@ -244,6 +271,7 @@ const SDPUtil = {
244 271
                 return lines[j];
245 272
             }
246 273
         }
274
+
247 275
         return false;
248 276
     },
249 277
     find_lines(haystack, needle, sessionpart) {
@@ -265,6 +293,7 @@ const SDPUtil = {
265 293
                 needles.push(lines[j]);
266 294
             }
267 295
         }
296
+
268 297
         return needles;
269 298
     },
270 299
     candidateToJingle(line) {
@@ -275,6 +304,7 @@ const SDPUtil = {
275 304
         } else if (line.substring(0, 12) != 'a=candidate:') {
276 305
             logger.log('parseCandidate called with a line that is not a candidate line');
277 306
             logger.log(line);
307
+
278 308
             return null;
279 309
         }
280 310
         if (line.substring(line.length - 2) == '\r\n') {// chomp it
@@ -286,6 +316,7 @@ const SDPUtil = {
286 316
         if (elems[6] != 'typ') {
287 317
             logger.log('did not find typ in the right place');
288 318
             logger.log(line);
319
+
289 320
             return null;
290 321
         }
291 322
         candidate.foundation = elems[0].substring(12);
@@ -317,11 +348,16 @@ const SDPUtil = {
317 348
             }
318 349
         }
319 350
         candidate.network = '1';
320
-        candidate.id = Math.random().toString(36).substr(2, 10); // not applicable to SDP -- FIXME: should be unique, not just random
351
+
352
+        // not applicable to SDP -- FIXME: should be unique, not just random
353
+        // eslint-disable-next-line newline-per-chained-call
354
+        candidate.id = Math.random().toString(36).substr(2, 10);
355
+
321 356
         return candidate;
322 357
     },
323 358
     candidateFromJingle(cand) {
324 359
         let line = 'a=candidate:';
360
+
325 361
         line += cand.getAttribute('foundation');
326 362
         line += ' ';
327 363
         line += cand.getAttribute('component');
@@ -329,6 +365,7 @@ const SDPUtil = {
329 365
 
330 366
         let protocol = cand.getAttribute('protocol');
331 367
         // use tcp candidates for FF
368
+
332 369
         if (RTCBrowserType.isFirefox() && protocol.toLowerCase() == 'ssltcp') {
333 370
             protocol = 'tcp';
334 371
         }
@@ -369,6 +406,7 @@ const SDPUtil = {
369 406
         line += 'generation';
370 407
         line += ' ';
371 408
         line += cand.getAttribute('generation') || '0';
409
+
372 410
         return `${line}\r\n`;
373 411
     },
374 412
 
@@ -384,11 +422,13 @@ const SDPUtil = {
384 422
             .length;
385 423
         const numGroups
386 424
             = (videoMLine.ssrcGroups && videoMLine.ssrcGroups.length) || 0;
425
+
387 426
         if (numSsrcs > 1 && numGroups === 0) {
388 427
             // Ambiguous, can't figure out the primary
389 428
             return;
390 429
         }
391 430
         let primarySsrc = null;
431
+
392 432
         if (numSsrcs === 1) {
393 433
             primarySsrc = videoMLine.ssrcs[0].id;
394 434
         } else if (numSsrcs === 2) {
@@ -396,6 +436,7 @@ const SDPUtil = {
396 436
             const fidGroup
397 437
                 = videoMLine.ssrcGroups.find(
398 438
                     group => group.semantics === 'FID');
439
+
399 440
             if (fidGroup) {
400 441
                 primarySsrc = fidGroup.ssrcs.split(' ')[0];
401 442
             }
@@ -404,10 +445,12 @@ const SDPUtil = {
404 445
             const simGroup
405 446
                 = videoMLine.ssrcGroups.find(
406 447
                     group => group.semantics === 'SIM');
448
+
407 449
             if (simGroup) {
408 450
                 primarySsrc = simGroup.ssrcs.split(' ')[0];
409 451
             }
410 452
         }
453
+
411 454
         return primarySsrc;
412 455
     },
413 456
 
@@ -431,6 +474,7 @@ const SDPUtil = {
431 474
     getSsrcAttribute(mLine, ssrc, attributeName) {
432 475
         for (let i = 0; i < mLine.ssrcs.length; ++i) {
433 476
             const ssrcLine = mLine.ssrcs[i];
477
+
434 478
             if (ssrcLine.id === ssrc
435 479
                 && ssrcLine.attribute === attributeName) {
436 480
                 return ssrcLine.value;
@@ -475,8 +519,10 @@ const SDPUtil = {
475 519
      */
476 520
     preferVideoCodec(videoMLine, codecName) {
477 521
         let payloadType = null;
522
+
478 523
         for (let i = 0; i < videoMLine.rtp.length; ++i) {
479 524
             const rtp = videoMLine.rtp[i];
525
+
480 526
             if (rtp.codec === codecName) {
481 527
                 payloadType = rtp.payload;
482 528
                 break;
@@ -485,6 +531,7 @@ const SDPUtil = {
485 531
         if (payloadType) {
486 532
             const payloadTypes = videoMLine.payloads.split(' ').map(p => parseInt(p));
487 533
             const payloadIndex = payloadTypes.indexOf(payloadType);
534
+
488 535
             payloadTypes.splice(payloadIndex, 1);
489 536
             payloadTypes.unshift(payloadType);
490 537
             videoMLine.payloads = payloadTypes.join(' ');

+ 2
- 0
modules/xmpp/SDPUtil.spec.js 查看文件

@@ -13,9 +13,11 @@ describe('SDPUtil', () => {
13 13
         it('should move a preferred codec to the front', () => {
14 14
             const sdp = SampleSdpStrings.multiCodecVideoSdp;
15 15
             const videoMLine = sdp.media.find(m => m.type === 'video');
16
+
16 17
             SDPUtil.preferVideoCodec(videoMLine, 'H264');
17 18
             const newPayloadTypesOrder
18 19
                 = videoMLine.payloads.split(' ').map(ptStr => parseInt(ptStr));
20
+
19 21
             expect(newPayloadTypesOrder[0]).toEqual(126);
20 22
         });
21 23
     });

+ 7
- 0
modules/xmpp/SdpConsistency.js 查看文件

@@ -61,13 +61,16 @@ export default class SdpConsistency {
61 61
     makeVideoPrimarySsrcsConsistent(sdpStr) {
62 62
         const sdpTransformer = new SdpTransformWrap(sdpStr);
63 63
         const videoMLine = sdpTransformer.selectMedia('video');
64
+
64 65
         if (!videoMLine) {
65 66
             logger.error(`No 'video' media found in the sdp: ${sdpStr}`);
67
+
66 68
             return sdpStr;
67 69
         }
68 70
         if (videoMLine.direction === 'inactive') {
69 71
             logger.info(
70 72
                 'Sdp-consistency doing nothing, video mline is inactive');
73
+
71 74
             return sdpStr;
72 75
         }
73 76
         if (videoMLine.direction === 'recvonly') {
@@ -84,8 +87,10 @@ export default class SdpConsistency {
84 87
             }
85 88
         } else {
86 89
             const newPrimarySsrc = videoMLine.getPrimaryVideoSsrc();
90
+
87 91
             if (!newPrimarySsrc) {
88 92
                 logger.info('Sdp-consistency couldn\'t parse new primary ssrc');
93
+
89 94
                 return sdpStr;
90 95
             }
91 96
             if (this.cachedPrimarySsrc) {
@@ -97,6 +102,7 @@ export default class SdpConsistency {
97 102
                     if (group.semantics === 'FID') {
98 103
                         const primarySsrc = parsePrimarySSRC(group);
99 104
                         const rtxSsrc = parseSecondarySSRC(group);
105
+
100 106
                         if (primarySsrc === newPrimarySsrc) {
101 107
                             group.ssrcs
102 108
                                 = `${this.cachedPrimarySsrc} ${rtxSsrc}`;
@@ -110,6 +116,7 @@ export default class SdpConsistency {
110 116
                         this.cachedPrimarySsrc}`);
111 117
             }
112 118
         }
119
+
113 120
         return sdpTransformer.toRawSDP();
114 121
     }
115 122
 }

+ 14
- 0
modules/xmpp/SdpTransformUtil.js 查看文件

@@ -27,6 +27,7 @@ function _getSSRCCount(mLine) {
27 27
     if (!mLine.ssrcs) {
28 28
         return 0;
29 29
     }
30
+
30 31
     return mLine.ssrcs
31 32
             .map(ssrcInfo => ssrcInfo.id)
32 33
             .filter((ssrc, index, array) => array.indexOf(ssrc) === index)
@@ -73,6 +74,8 @@ export class SdpTransformWrap {
73 74
     selectMedia(mediaType) {
74 75
         const selectedMLine
75 76
             = this.parsedSDP.media.find(mLine => mLine.type === mediaType);
77
+
78
+
76 79
         return selectedMLine ? new MLineWrap(selectedMLine) : null;
77 80
     }
78 81
 
@@ -109,6 +112,7 @@ class MLineWrap {
109 112
         if (!this.mLine.ssrcs) {
110 113
             this.mLine.ssrcs = [];
111 114
         }
115
+
112 116
         return this.mLine.ssrcs;
113 117
     }
114 118
 
@@ -136,6 +140,7 @@ class MLineWrap {
136 140
         if (!this.mLine.ssrcGroups) {
137 141
             this.mLine.ssrcGroups = [];
138 142
         }
143
+
139 144
         return this.mLine.ssrcGroups;
140 145
     }
141 146
 
@@ -160,6 +165,8 @@ class MLineWrap {
160 165
         const attribute = this._ssrcs.find(
161 166
             ssrcObj => ssrcObj.id == ssrcNumber
162 167
             && ssrcObj.attribute === attrName);
168
+
169
+
163 170
         return attribute && attribute.value;
164 171
     }
165 172
 
@@ -255,6 +262,7 @@ class MLineWrap {
255 262
         }
256 263
 
257 264
         const numSsrcs = _getSSRCCount(this.mLine);
265
+
258 266
         if (numSsrcs === 1) {
259 267
             // Not using _ssrcs on purpose here
260 268
             return this.mLine.ssrcs[0].id;
@@ -262,10 +270,12 @@ class MLineWrap {
262 270
             // Look for a SIM or FID group
263 271
         if (this.mLine.ssrcGroups) {
264 272
             const simGroup = this.findGroup('SIM');
273
+
265 274
             if (simGroup) {
266 275
                 return parsePrimarySSRC(simGroup);
267 276
             }
268 277
             const fidGroup = this.findGroup('FID');
278
+
269 279
             if (fidGroup) {
270 280
                 return parsePrimarySSRC(fidGroup);
271 281
             }
@@ -283,6 +293,8 @@ class MLineWrap {
283 293
      */
284 294
     getRtxSSRC(primarySsrc) {
285 295
         const fidGroup = this.findGroupByPrimarySSRC('FID', primarySsrc);
296
+
297
+
286 298
         return fidGroup && parseSecondarySSRC(fidGroup);
287 299
     }
288 300
 
@@ -318,10 +330,12 @@ class MLineWrap {
318 330
             if (ssrcGroupInfo.semantics === 'FID') {
319 331
                 // secondary FID streams should be filtered out
320 332
                 const secondarySsrc = parseSecondarySSRC(ssrcGroupInfo);
333
+
321 334
                 videoSSRCs.splice(
322 335
                     videoSSRCs.indexOf(secondarySsrc), 1);
323 336
             }
324 337
         }
338
+
325 339
         return videoSSRCs;
326 340
     }
327 341
 

+ 37
- 3
modules/xmpp/moderator.js 查看文件

@@ -5,19 +5,25 @@ const XMPPEvents = require('../../service/xmpp/XMPPEvents');
5 5
 const AuthenticationEvents
6 6
     = require('../../service/authentication/AuthenticationEvents');
7 7
 const GlobalOnErrorHandler = require('../util/GlobalOnErrorHandler');
8
+
8 9
 import Settings from '../settings/Settings';
9 10
 
10 11
 function createExpBackoffTimer(step) {
11 12
     let count = 1;
13
+
14
+
12 15
     return function(reset) {
13 16
         // Reset call
14 17
         if (reset) {
15 18
             count = 1;
19
+
16 20
             return;
17 21
         }
18 22
         // Calculate next timeout
19 23
         const timeout = Math.pow(2, count - 1);
24
+
20 25
         count += 1;
26
+
21 27
         return timeout * step;
22 28
     };
23 29
 }
@@ -49,6 +55,7 @@ function Moderator(roomName, xmpp, emitter, options) {
49 55
                 logger.warn(
50 56
                     `Ignoring sessionId from different origin: ${
51 57
                         event.origin}`);
58
+
52 59
                 return;
53 60
             }
54 61
             Settings.setSessionId(event.data.sessionId);
@@ -74,6 +81,7 @@ Moderator.prototype.isSipGatewayEnabled = function() {
74 81
 Moderator.prototype.onMucMemberLeft = function(jid) {
75 82
     logger.info(`Someone left is it focus ? ${jid}`);
76 83
     const resource = Strophe.getResourceFromJid(jid);
84
+
77 85
     if (resource === 'focus') {
78 86
         logger.info(
79 87
             'Focus has left the room - leaving conference');
@@ -96,9 +104,11 @@ Moderator.prototype.getFocusComponent = function() {
96 104
     // Get focus component address
97 105
     let focusComponent = this.options.connection.hosts.focus;
98 106
     // If not specified use default:  'focus.domain'
107
+
99 108
     if (!focusComponent) {
100 109
         focusComponent = `focus.${this.options.connection.hosts.domain}`;
101 110
     }
111
+
102 112
     return focusComponent;
103 113
 };
104 114
 
@@ -211,12 +221,15 @@ Moderator.prototype.createConferenceIq = function() {
211 221
             }).up();
212 222
     }
213 223
     elem.up();
224
+
214 225
     return elem;
215 226
 };
216 227
 
217 228
 
218 229
 Moderator.prototype.parseSessionId = function(resultIq) {
230
+    // eslint-disable-next-line newline-per-chained-call
219 231
     const sessionId = $(resultIq).find('conference').attr('session-id');
232
+
220 233
     if (sessionId) {
221 234
         logger.info(`Received sessionId:  ${sessionId}`);
222 235
         Settings.setSessionId(sessionId);
@@ -224,9 +237,8 @@ Moderator.prototype.parseSessionId = function(resultIq) {
224 237
 };
225 238
 
226 239
 Moderator.prototype.parseConfigOptions = function(resultIq) {
227
-
228
-    this.setFocusUserJid(
229
-        $(resultIq).find('conference').attr('focusjid'));
240
+    // eslint-disable-next-line newline-per-chained-call
241
+    this.setFocusUserJid($(resultIq).find('conference').attr('focusjid'));
230 242
 
231 243
     const authenticationEnabled
232 244
         = $(resultIq).find(
@@ -247,6 +259,7 @@ Moderator.prototype.parseConfigOptions = function(resultIq) {
247 259
         this.parseSessionId(resultIq);
248 260
     }
249 261
 
262
+    // eslint-disable-next-line newline-per-chained-call
250 263
     const authIdentity = $(resultIq).find('>conference').attr('identity');
251 264
 
252 265
     this.eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,
@@ -299,42 +312,50 @@ Moderator.prototype._allocateConferenceFocusError = function(error, callback) {
299 312
     // If the session is invalid, remove and try again without session ID to get
300 313
     // a new one
301 314
     const invalidSession = $(error).find('>error>session-invalid').length;
315
+
302 316
     if (invalidSession) {
303 317
         logger.info('Session expired! - removing');
304 318
         Settings.clearSessionId();
305 319
     }
306 320
     if ($(error).find('>error>graceful-shutdown').length) {
307 321
         this.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
322
+
308 323
         return;
309 324
     }
310 325
     // Check for error returned by the reservation system
311 326
     const reservationErr = $(error).find('>error>reservation-error');
327
+
312 328
     if (reservationErr.length) {
313 329
         // Trigger error event
314 330
         const errorCode = reservationErr.attr('error-code');
315 331
         const errorTextNode = $(error).find('>error>text');
316 332
         let errorMsg;
333
+
317 334
         if (errorTextNode) {
318 335
             errorMsg = errorTextNode.text();
319 336
         }
320 337
         this.eventEmitter.emit(
321 338
                 XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
339
+
322 340
         return;
323 341
     }
324 342
     // Not authorized to create new room
325 343
     if ($(error).find('>error>not-authorized').length) {
326 344
         logger.warn('Unauthorized to start the conference', error);
327 345
         const toDomain = Strophe.getDomainFromJid(error.getAttribute('to'));
346
+
328 347
         if (toDomain !== this.options.connection.hosts.anonymousdomain) {
329 348
             // FIXME "is external" should come either from the focus or
330 349
             // config.js
331 350
             this.externalAuthEnabled = true;
332 351
         }
333 352
         this.eventEmitter.emit(XMPPEvents.AUTHENTICATION_REQUIRED);
353
+
334 354
         return;
335 355
     }
336 356
     const waitMs = this.getNextErrorTimeout();
337 357
     const errmsg = `Focus error, retry after ${waitMs}`;
358
+
338 359
     GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
339 360
     logger.error(errmsg, error);
340 361
     // Show message
@@ -342,6 +363,7 @@ Moderator.prototype._allocateConferenceFocusError = function(error, callback) {
342 363
     const retrySec = waitMs / 1000;
343 364
     // FIXME: message is duplicated ? Do not show in case of session invalid
344 365
     // which means just a retry
366
+
345 367
     if (!invalidSession) {
346 368
         this.eventEmitter.emit(
347 369
                 XMPPEvents.FOCUS_DISCONNECTED, focusComponent, retrySec);
@@ -368,6 +390,7 @@ Moderator.prototype._allocateConferenceFocusSuccess = function(
368 390
 
369 391
     // Reset the error timeout (because we haven't failed here).
370 392
     this.getNextErrorTimeout(true);
393
+    // eslint-disable-next-line newline-per-chained-call
371 394
     if ('true' === $(result).find('conference').attr('ready')) {
372 395
         // Reset the non-error timeout (because we've succeeded here).
373 396
         this.getNextTimeout(true);
@@ -375,6 +398,7 @@ Moderator.prototype._allocateConferenceFocusSuccess = function(
375 398
         callback();
376 399
     } else {
377 400
         const waitMs = this.getNextTimeout();
401
+
378 402
         logger.info(`Waiting for the focus... ${waitMs}`);
379 403
         window.setTimeout(() => this.allocateConferenceFocus(callback),
380 404
             waitMs);
@@ -389,7 +413,9 @@ Moderator.prototype.authenticate = function() {
389 413
                 this.parseSessionId(result);
390 414
                 resolve();
391 415
             }, error => {
416
+                // eslint-disable-next-line newline-per-chained-call
392 417
                 const code = $(error).find('>error').attr('code');
418
+
393 419
                 reject(error, code);
394 420
             }
395 421
         );
@@ -415,6 +441,7 @@ Moderator.prototype._getLoginUrl = function(popup, urlCb, failureCb) {
415 441
         'machine-uid': Settings.getMachineId()
416 442
     };
417 443
     let str = 'auth url'; // for logger
444
+
418 445
     if (popup) {
419 446
         attrs.popup = true;
420 447
         str = `POPUP ${str}`;
@@ -435,7 +462,9 @@ Moderator.prototype._getLoginUrl = function(popup, urlCb, failureCb) {
435 462
     this.connection.sendIQ(
436 463
         iq,
437 464
         result => {
465
+            // eslint-disable-next-line newline-per-chained-call
438 466
             let url = $(result).find('login-url').attr('url');
467
+
439 468
             url = decodeURIComponent(url);
440 469
             if (url) {
441 470
                 logger.info(`Got ${str}: ${url}`);
@@ -455,8 +484,10 @@ Moderator.prototype.getPopupLoginUrl = function(urlCallback, failureCallback) {
455 484
 Moderator.prototype.logout = function(callback) {
456 485
     const iq = $iq({to: this.getFocusComponent(), type: 'set'});
457 486
     const sessionId = Settings.getSessionId();
487
+
458 488
     if (!sessionId) {
459 489
         callback();
490
+
460 491
         return;
461 492
     }
462 493
     iq.c('logout', {
@@ -466,7 +497,9 @@ Moderator.prototype.logout = function(callback) {
466 497
     this.connection.sendIQ(
467 498
         iq,
468 499
         result => {
500
+            // eslint-disable-next-line newline-per-chained-call
469 501
             let logoutUrl = $(result).find('logout').attr('logout-url');
502
+
470 503
             if (logoutUrl) {
471 504
                 logoutUrl = decodeURIComponent(logoutUrl);
472 505
             }
@@ -476,6 +509,7 @@ Moderator.prototype.logout = function(callback) {
476 509
         },
477 510
         error => {
478 511
             const errmsg = 'Logout error';
512
+
479 513
             GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
480 514
             logger.error(errmsg, error);
481 515
         }

+ 26
- 10
modules/xmpp/recording.js 查看文件

@@ -54,11 +54,13 @@ Recording.action = {
54 54
 
55 55
 Recording.prototype.handleJibriPresence = function(jibri) {
56 56
     const attributes = jibri.attributes;
57
+
57 58
     if(!attributes) {
58 59
         return;
59 60
     }
60 61
 
61 62
     const newState = attributes.status;
63
+
62 64
     logger.log('Handle jibri presence : ', newState);
63 65
 
64 66
     if (newState === this.state) {
@@ -91,14 +93,16 @@ Recording.prototype.setRecordingJibri
91 93
         options = options || {};
92 94
 
93 95
     // FIXME jibri does not accept IQ without 'url' attribute set ?
94
-        const iq = $iq({to: this.focusMucJid, type: 'set'})
95
-        .c('jibri', {
96
-            'xmlns': 'http://jitsi.org/protocol/jibri',
97
-            'action': state === Recording.status.ON
98
-                    ? Recording.action.START
99
-                    : Recording.action.STOP,
100
-            'streamid': options.streamId,
101
-        }).up();
96
+        const iq
97
+            = $iq({to: this.focusMucJid, type: 'set'})
98
+                .c('jibri', {
99
+                    'xmlns': 'http://jitsi.org/protocol/jibri',
100
+                    'action': state === Recording.status.ON
101
+                            ? Recording.action.START
102
+                            : Recording.action.STOP,
103
+                    'streamid': options.streamId,
104
+                })
105
+                .up();
102 106
 
103 107
         logger.log(`Set jibri recording: ${state}`, iq.nodeTree);
104 108
         logger.log(iq.nodeTree);
@@ -106,8 +110,10 @@ Recording.prototype.setRecordingJibri
106 110
         iq,
107 111
         result => {
108 112
             logger.log('Result', result);
109
-            callback($(result).find('jibri').attr('state'),
110
-            $(result).find('jibri').attr('url'));
113
+
114
+            const jibri = $(result).find('jibri');
115
+
116
+            callback(jibri.attr('state'), jibri.attr('url'));
111 117
         },
112 118
         error => {
113 119
             logger.log('Failed to start recording, error: ', error);
@@ -128,17 +134,20 @@ Recording.prototype.setRecordingJirecon
128 134
                 ? Recording.action.START
129 135
                 : Recording.action.STOP,
130 136
             mucjid: this.roomjid});
137
+
131 138
         if (state === 'off') {
132 139
             iq.attrs({rid: this.jireconRid});
133 140
         }
134 141
 
135 142
         logger.log('Start recording');
136 143
         const self = this;
144
+
137 145
         this.connection.sendIQ(
138 146
         iq,
139 147
         result => {
140 148
             // TODO wait for an IQ with the real status, since this is
141 149
             // provisional?
150
+            // eslint-disable-next-line newline-per-chained-call
142 151
             self.jireconRid = $(result).find('recording').attr('rid');
143 152
             logger.log(
144 153
                 `Recording ${
@@ -163,12 +172,14 @@ Recording.prototype.setRecordingJirecon
163 172
 Recording.prototype.setRecordingColibri
164 173
 = function(state, callback, errCallback, options) {
165 174
     const elem = $iq({to: this.focusMucJid, type: 'set'});
175
+
166 176
     elem.c('conference', {
167 177
         xmlns: 'http://jitsi.org/protocol/colibri'
168 178
     });
169 179
     elem.c('recording', {state, token: options.token});
170 180
 
171 181
     const self = this;
182
+
172 183
     this.connection.sendIQ(elem,
173 184
         result => {
174 185
             logger.log('Set recording "', state, '". Result:', result);
@@ -180,7 +191,9 @@ Recording.prototype.setRecordingColibri
180 191
 
181 192
             if (newState === 'pending') {
182 193
                 self.connection.addHandler(iq => {
194
+                    // eslint-disable-next-line newline-per-chained-call
183 195
                     const state = $(iq).find('recording').attr('state');
196
+
184 197
                     if (state) {
185 198
                         self.state = newState;
186 199
                         callback(state);
@@ -209,6 +222,7 @@ Recording.prototype.setRecording
209 222
         break;
210 223
     default: {
211 224
         const errmsg = 'Unknown recording type!';
225
+
212 226
         GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
213 227
         logger.error(errmsg);
214 228
         break;
@@ -244,6 +258,7 @@ Recording.prototype.toggleRecording = function(options, statusChangeHandler) {
244 258
         statusChangeHandler(Recording.status.FAILED,
245 259
                             JitsiRecorderErrors.NO_TOKEN);
246 260
         logger.error('No token passed!');
261
+
247 262
         return;
248 263
     }
249 264
 
@@ -253,6 +268,7 @@ Recording.prototype.toggleRecording = function(options, statusChangeHandler) {
253 268
                     : Recording.status.OFF;
254 269
 
255 270
     const self = this;
271
+
256 272
     logger.log('Toggle recording (old state, new state): ', oldState, newState);
257 273
     this.setRecording(
258 274
         newState,

+ 13
- 0
modules/xmpp/strophe.emuc.js 查看文件

@@ -6,6 +6,7 @@
6 6
 
7 7
 import {getLogger} from 'jitsi-meet-logger';
8 8
 const logger = getLogger(__filename);
9
+
9 10
 import ChatRoom from './ChatRoom';
10 11
 import {ConnectionPluginListenable} from './ConnectionPlugin';
11 12
 import XMPPEvents from '../../service/xmpp/XMPPEvents';
@@ -34,8 +35,10 @@ class MucConnectionPlugin extends ConnectionPluginListenable {
34 35
 
35 36
     createRoom(jid, password, options) {
36 37
         const roomJid = Strophe.getBareJidFromJid(jid);
38
+
37 39
         if (this.rooms[roomJid]) {
38 40
             const errmsg = 'You are already in the room!';
41
+
39 42
             logger.error(errmsg);
40 43
             throw new Error(errmsg);
41 44
         }
@@ -43,6 +46,7 @@ class MucConnectionPlugin extends ConnectionPluginListenable {
43 46
             password, this.xmpp, options);
44 47
         this.eventEmitter.emit(
45 48
             XMPPEvents.EMUC_ROOM_ADDED, this.rooms[roomJid]);
49
+
46 50
         return this.rooms[roomJid];
47 51
     }
48 52
 
@@ -61,6 +65,7 @@ class MucConnectionPlugin extends ConnectionPluginListenable {
61 65
         }
62 66
 
63 67
         const room = this.rooms[Strophe.getBareJidFromJid(from)];
68
+
64 69
         if(!room) {
65 70
             return;
66 71
         }
@@ -79,22 +84,26 @@ class MucConnectionPlugin extends ConnectionPluginListenable {
79 84
     onPresenceUnavailable(pres) {
80 85
         const from = pres.getAttribute('from');
81 86
         const room = this.rooms[Strophe.getBareJidFromJid(from)];
87
+
82 88
         if(!room) {
83 89
             return;
84 90
         }
85 91
 
86 92
         room.onPresenceUnavailable(pres, from);
93
+
87 94
         return true;
88 95
     }
89 96
 
90 97
     onPresenceError(pres) {
91 98
         const from = pres.getAttribute('from');
92 99
         const room = this.rooms[Strophe.getBareJidFromJid(from)];
100
+
93 101
         if(!room) {
94 102
             return;
95 103
         }
96 104
 
97 105
         room.onPresenceError(pres, from);
106
+
98 107
         return true;
99 108
     }
100 109
 
@@ -102,22 +111,26 @@ class MucConnectionPlugin extends ConnectionPluginListenable {
102 111
         // FIXME: this is a hack. but jingle on muc makes nickchanges hard
103 112
         const from = msg.getAttribute('from');
104 113
         const room = this.rooms[Strophe.getBareJidFromJid(from)];
114
+
105 115
         if(!room) {
106 116
             return;
107 117
         }
108 118
 
109 119
         room.onMessage(msg, from);
120
+
110 121
         return true;
111 122
     }
112 123
 
113 124
     onMute(iq) {
114 125
         const from = iq.getAttribute('from');
115 126
         const room = this.rooms[Strophe.getBareJidFromJid(from)];
127
+
116 128
         if(!room) {
117 129
             return;
118 130
         }
119 131
 
120 132
         room.onMute(iq);
133
+
121 134
         return true;
122 135
     }
123 136
 }

+ 28
- 2
modules/xmpp/strophe.jingle.js 查看文件

@@ -2,12 +2,17 @@
2 2
 
3 3
 import { getLogger } from 'jitsi-meet-logger';
4 4
 const logger = getLogger(__filename);
5
+
5 6
 import JingleSessionPC from './JingleSessionPC';
6 7
 import XMPPEvents from '../../service/xmpp/XMPPEvents';
7 8
 import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
8 9
 import Statistics from '../statistics/statistics';
9 10
 import ConnectionPlugin from './ConnectionPlugin';
10 11
 
12
+// XXX Strophe is build around the idea of chaining function calls so allow long
13
+// function call chains.
14
+/* eslint-disable newline-per-chained-call */
15
+
11 16
 class JingleConnectionPlugin extends ConnectionPlugin {
12 17
     constructor(xmpp, eventEmitter) {
13 18
         super();
@@ -39,8 +44,10 @@ class JingleConnectionPlugin extends ConnectionPlugin {
39 44
             to: fromJid,
40 45
             id: iq.getAttribute('id')
41 46
         });
47
+
42 48
         logger.log(`on jingle ${action} from ${fromJid}`, iq);
43 49
         let sess = this.sessions[sid];
50
+
44 51
         if ('session-initiate' != action) {
45 52
             if (!sess) {
46 53
                 ack.attrs({ type: 'error' });
@@ -50,6 +57,7 @@ class JingleConnectionPlugin extends ConnectionPlugin {
50 57
                     .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
51 58
                 logger.warn('invalid session id', iq);
52 59
                 this.connection.send(ack);
60
+
53 61
                 return true;
54 62
             }
55 63
             // local jid is not checked
@@ -61,6 +69,7 @@ class JingleConnectionPlugin extends ConnectionPlugin {
61 69
                     .c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
62 70
                     .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
63 71
                 this.connection.send(ack);
72
+
64 73
                 return true;
65 74
             }
66 75
         } else if (sess !== undefined) {
@@ -71,17 +80,21 @@ class JingleConnectionPlugin extends ConnectionPlugin {
71 80
                 .c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up();
72 81
             logger.warn('duplicate session id', sid, iq);
73 82
             this.connection.send(ack);
83
+
74 84
             return true;
75 85
         }
76 86
         const now = window.performance.now();
77 87
         // see http://xmpp.org/extensions/xep-0166.html#concepts-session
88
+
78 89
         switch (action) {
79 90
         case 'session-initiate': {
80 91
             logger.log('(TIME) received session-initiate:\t', now);
81 92
             const startMuted = $(iq).find('jingle>startmuted');
93
+
82 94
             if (startMuted && startMuted.length > 0) {
83 95
                 const audioMuted = startMuted.attr('audio');
84 96
                 const videoMuted = startMuted.attr('video');
97
+
85 98
                 this.eventEmitter.emit(XMPPEvents.START_MUTED_FROM_FOCUS,
86 99
                             audioMuted === 'true', videoMuted === 'true');
87 100
             }
@@ -105,9 +118,10 @@ class JingleConnectionPlugin extends ConnectionPlugin {
105 118
             logger.log('terminating...', sess.sid);
106 119
             let reasonCondition = null;
107 120
             let reasonText = null;
121
+
108 122
             if ($(iq).find('>jingle>reason').length) {
109 123
                 reasonCondition
110
-                        = $(iq).find('>jingle>reason>:first')[0].tagName;
124
+                    = $(iq).find('>jingle>reason>:first')[0].tagName;
111 125
                 reasonText = $(iq).find('>jingle>reason>text').text();
112 126
             }
113 127
             this.terminate(sess.sid, reasonCondition, reasonText);
@@ -122,6 +136,7 @@ class JingleConnectionPlugin extends ConnectionPlugin {
122 136
 
123 137
             sess.replaceTransport($(iq).find('>jingle'), () => {
124 138
                 const successTime = window.performance.now();
139
+
125 140
                 logger.info(
126 141
                         '(TIME) Transport replace success!', successTime);
127 142
                 Statistics.analytics.sendEvent(
@@ -151,6 +166,7 @@ class JingleConnectionPlugin extends ConnectionPlugin {
151 166
             break;
152 167
         }
153 168
         this.connection.send(ack);
169
+
154 170
         return true;
155 171
     }
156 172
 
@@ -181,10 +197,12 @@ class JingleConnectionPlugin extends ConnectionPlugin {
181 197
                 .c('service', {host: `turn.${this.connection.domain}`}),
182 198
             res => {
183 199
                 const iceservers = [];
200
+
184 201
                 $(res).find('>services>service').each((idx, el) => {
185 202
                     el = $(el);
186 203
                     const dict = {};
187 204
                     const type = el.attr('type');
205
+
188 206
                     switch (type) {
189 207
                     case 'stun':
190 208
                         dict.url = `stun:${el.attr('host')}`;
@@ -198,6 +216,7 @@ class JingleConnectionPlugin extends ConnectionPlugin {
198 216
                         dict.url = `${type}:`;
199 217
                         const username = el.attr('username');
200 218
                             // https://code.google.com/p/webrtc/issues/detail?id=1508
219
+
201 220
                         if (username) {
202 221
                             if (navigator.userAgent.match(
203 222
                                     /Chrom(e|ium)\/([0-9]+)\./)
@@ -213,10 +232,12 @@ class JingleConnectionPlugin extends ConnectionPlugin {
213 232
                         }
214 233
                         dict.url += el.attr('host');
215 234
                         const port = el.attr('port');
235
+
216 236
                         if (port && port != '3478') {
217 237
                             dict.url += `:${el.attr('port')}`;
218 238
                         }
219 239
                         const transport = el.attr('transport');
240
+
220 241
                         if (transport && transport != 'udp') {
221 242
                             dict.url += `?transport=${transport}`;
222 243
                         }
@@ -241,9 +262,11 @@ class JingleConnectionPlugin extends ConnectionPlugin {
241 262
      */
242 263
     getLog() {
243 264
         const data = {};
265
+
244 266
         Object.keys(this.sessions).forEach(sid => {
245 267
             const session = this.sessions[sid];
246 268
             const pc = session.peerconnection;
269
+
247 270
             if (pc && pc.updateLog) {
248 271
                 // FIXME: should probably be a .dump call
249 272
                 data[`jingle_${sid}`] = {
@@ -253,12 +276,15 @@ class JingleConnectionPlugin extends ConnectionPlugin {
253 276
                 };
254 277
             }
255 278
         });
279
+
256 280
         return data;
257 281
     }
258 282
 }
259 283
 
284
+/* eslint-enable newline-per-chained-call */
260 285
 
261 286
 module.exports = function(XMPP, eventEmitter) {
262
-    Strophe.addConnectionPlugin('jingle',
287
+    Strophe.addConnectionPlugin(
288
+        'jingle',
263 289
         new JingleConnectionPlugin(XMPP, eventEmitter));
264 290
 };

+ 6
- 0
modules/xmpp/strophe.ping.js 查看文件

@@ -2,6 +2,7 @@
2 2
 
3 3
 import { getLogger } from 'jitsi-meet-logger';
4 4
 const logger = getLogger(__filename);
5
+
5 6
 import ConnectionPlugin from './ConnectionPlugin';
6 7
 import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
7 8
 
@@ -57,6 +58,7 @@ class PingConnectionPlugin extends ConnectionPlugin {
57 58
      */
58 59
     ping(jid, success, error, timeout) {
59 60
         const iq = $iq({type: 'get', to: jid});
61
+
60 62
         iq.c('ping', {xmlns: Strophe.NS.PING});
61 63
         this.connection.sendIQ(iq, success, error, timeout);
62 64
     }
@@ -71,6 +73,7 @@ class PingConnectionPlugin extends ConnectionPlugin {
71 73
         this.xmpp.caps.getFeatures(jid).then(features =>
72 74
             callback(features.has('urn:xmpp:ping')), error => {
73 75
             const errmsg = 'Ping feature discovery error';
76
+
74 77
             GlobalOnErrorHandler.callErrorHandler(
75 78
                 new Error(`${errmsg}: ${error}`));
76 79
             logger.error(errmsg, error);
@@ -88,8 +91,10 @@ class PingConnectionPlugin extends ConnectionPlugin {
88 91
     startInterval(remoteJid, interval = PING_INTERVAL) {
89 92
         if (this.intervalId) {
90 93
             const errmsg = 'Ping task scheduled already';
94
+
91 95
             GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
92 96
             logger.error(errmsg);
97
+
93 98
             return;
94 99
         }
95 100
         this.intervalId = window.setInterval(() => {
@@ -98,6 +103,7 @@ class PingConnectionPlugin extends ConnectionPlugin {
98 103
             }, error => {
99 104
                 this.failedPings += 1;
100 105
                 const errmsg = `Ping ${error ? 'error' : 'timeout'}`;
106
+
101 107
                 if (this.failedPings >= PING_THRESHOLD) {
102 108
                     GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
103 109
                     logger.error(errmsg, error);

+ 8
- 2
modules/xmpp/strophe.rayo.js 查看文件

@@ -2,6 +2,7 @@
2 2
 
3 3
 import { getLogger } from 'jitsi-meet-logger';
4 4
 const logger = getLogger(__filename);
5
+
5 6
 import ConnectionPlugin from './ConnectionPlugin';
6 7
 
7 8
 const RAYO_XMLNS = 'urn:xmpp:rayo:1';
@@ -22,12 +23,14 @@ class RayoConnectionPlugin extends ConnectionPlugin {
22 23
         return new Promise((resolve, reject) => {
23 24
             if(!focusMucJid) {
24 25
                 reject(new Error('Internal error!'));
26
+
25 27
                 return;
26 28
             }
27 29
             const req = $iq({
28 30
                 type: 'set',
29 31
                 to: focusMucJid
30 32
             });
33
+
31 34
             req.c('dial', {
32 35
                 xmlns: RAYO_XMLNS,
33 36
                 to,
@@ -48,9 +51,10 @@ class RayoConnectionPlugin extends ConnectionPlugin {
48 51
             this.connection.sendIQ(req, result => {
49 52
                 logger.info('Dial result ', result);
50 53
 
54
+                // eslint-disable-next-line newline-per-chained-call
51 55
                 const resource = $(result).find('ref').attr('uri');
52
-                this.call_resource
53
-                    = resource.substr('xmpp:'.length);
56
+
57
+                this.call_resource = resource.substr('xmpp:'.length);
54 58
                 logger.info(`Received call resource: ${this.call_resource}`);
55 59
                 resolve();
56 60
             }, error => {
@@ -65,6 +69,7 @@ class RayoConnectionPlugin extends ConnectionPlugin {
65 69
             if (!this.call_resource) {
66 70
                 reject(new Error('No call in progress'));
67 71
                 logger.warn('No call in progress');
72
+
68 73
                 return;
69 74
             }
70 75
 
@@ -72,6 +77,7 @@ class RayoConnectionPlugin extends ConnectionPlugin {
72 77
                 type: 'set',
73 78
                 to: this.call_resource
74 79
             });
80
+
75 81
             req.c('hangup', {
76 82
                 xmlns: RAYO_XMLNS
77 83
             });

+ 2
- 0
modules/xmpp/strophe.util.js 查看文件

@@ -4,6 +4,7 @@
4 4
  */
5 5
 import {getLogger} from 'jitsi-meet-logger';
6 6
 const logger = getLogger(__filename);
7
+
7 8
 import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
8 9
 
9 10
 /**
@@ -68,6 +69,7 @@ export default function() {
68 69
         case Strophe.LogLevel.WARN:
69 70
             logger.warn(`Strophe: ${msg}`);
70 71
             const errStatusCapture = lastErrorStatusRegExpr.exec(msg);
72
+
71 73
             if (errStatusCapture && errStatusCapture.length === 2) {
72 74
                 lastErrorStatus = parseInt(errStatusCapture[1]);
73 75
                 logger.debug(

+ 11
- 0
modules/xmpp/xmpp.js 查看文件

@@ -2,6 +2,7 @@
2 2
 
3 3
 import { getLogger } from 'jitsi-meet-logger';
4 4
 const logger = getLogger(__filename);
5
+
5 6
 import RandomUtil from '../util/RandomUtil';
6 7
 import * as JitsiConnectionErrors from '../../JitsiConnectionErrors';
7 8
 import * as JitsiConnectionEvents from '../../JitsiConnectionEvents';
@@ -105,6 +106,7 @@ export default class XMPP extends Listenable {
105 106
     connectionHandler(password, status, msg) {
106 107
         const now = window.performance.now();
107 108
         const statusStr = Strophe.getStatusString(status).toLowerCase();
109
+
108 110
         this.connectionTimes[statusStr] = now;
109 111
         logger.log(
110 112
             `(TIME) Strophe ${statusStr}${msg ? `[${msg}]` : ''}:\t`,
@@ -119,6 +121,7 @@ export default class XMPP extends Listenable {
119 121
 
120 122
             // Schedule ping ?
121 123
             const pingJid = this.connection.domain;
124
+
122 125
             this.connection.ping.hasPingSupport(
123 126
                 pingJid,
124 127
                 hasPing => {
@@ -152,6 +155,7 @@ export default class XMPP extends Listenable {
152 155
             this.connection.ping.stopInterval();
153 156
             const wasIntentionalDisconnect = this.disconnectInProgress;
154 157
             const errMsg = msg ? msg : this.lastErrorMsg;
158
+
155 159
             this.disconnectInProgress = false;
156 160
             if (this.anonymousConnectionFailed) {
157 161
                 // prompt user for username and password
@@ -175,6 +179,7 @@ export default class XMPP extends Listenable {
175 179
                 // XXX if the last request error is within 5xx range it means it
176 180
                 // was a server failure
177 181
                 const lastErrorStatus = Strophe.getLastErrorStatus();
182
+
178 183
                 if (lastErrorStatus >= 500 && lastErrorStatus < 600) {
179 184
                     this.eventEmitter.emit(
180 185
                         JitsiConnectionEvents.CONNECTION_FAILED,
@@ -239,6 +244,7 @@ export default class XMPP extends Listenable {
239 244
      */
240 245
     attach(options) {
241 246
         const now = this.connectionTimes.attaching = window.performance.now();
247
+
242 248
         logger.log(`(TIME) Strophe Attaching\t:${now}`);
243 249
         this.connection.attach(options.jid, options.sid,
244 250
             parseInt(options.rid,10) + 1,
@@ -256,6 +262,7 @@ export default class XMPP extends Listenable {
256 262
                     || this.options.hosts.domain;
257 263
             // Force authenticated domain if room is appended with '?login=true'
258 264
             // or if we're joining with the token
265
+
259 266
             if (this.options.hosts.anonymousdomain
260 267
                     && (window.location.search.indexOf('login=true') !== -1
261 268
                         || this.options.token)) {
@@ -263,6 +270,7 @@ export default class XMPP extends Listenable {
263 270
             }
264 271
             jid = configDomain || window.location.hostname;
265 272
         }
273
+
266 274
         return this._connect(jid, password);
267 275
     }
268 276
 
@@ -297,6 +305,8 @@ export default class XMPP extends Listenable {
297 305
      */
298 306
     getJingleLog() {
299 307
         const jingle = this.connection.jingle;
308
+
309
+
300 310
         return jingle ? jingle.getLog() : {};
301 311
     }
302 312
 
@@ -334,6 +344,7 @@ export default class XMPP extends Listenable {
334 344
                 || !this.connection
335 345
                 || !this.connection.connected) {
336 346
             this.eventEmitter.emit(JitsiConnectionEvents.WRONG_STATE);
347
+
337 348
             return;
338 349
         }
339 350
 

+ 1
- 0
service/RTC/Resolutions.js 查看文件

@@ -52,4 +52,5 @@ const Resolutions = {
52 52
         order: 1
53 53
     }
54 54
 };
55
+
55 56
 module.exports = Resolutions;

+ 1
- 0
service/RTC/VideoType.js 查看文件

@@ -13,4 +13,5 @@ const VideoType = {
13 13
      */
14 14
     DESKTOP: 'desktop'
15 15
 };
16
+
16 17
 module.exports = VideoType;

+ 1
- 0
service/authentication/AuthenticationEvents.js 查看文件

@@ -9,4 +9,5 @@ const AuthenticationEvents = {
9 9
      */
10 10
     IDENTITY_UPDATED: 'authentication.identity_updated'
11 11
 };
12
+
12 13
 module.exports = AuthenticationEvents;

+ 1
- 0
service/statistics/constants.js 查看文件

@@ -1,4 +1,5 @@
1 1
 const Constants = {
2 2
     LOCAL_JID: 'local'
3 3
 };
4
+
4 5
 module.exports = Constants;

+ 1
- 0
service/xmpp/XMPPEvents.js 查看文件

@@ -156,4 +156,5 @@ const XMPPEvents = {
156 156
     // changed.
157 157
     ICE_CONNECTION_STATE_CHANGED: 'xmpp.ice_connection_state_changed'
158 158
 };
159
+
159 160
 module.exports = XMPPEvents;

Loading…
取消
儲存