瀏覽代碼

Calls the global error handler on every logger.error

master
hristoterezov 9 年之前
父節點
當前提交
dd3e1bc4a9

+ 16
- 4
JitsiConference.js 查看文件

@@ -15,6 +15,7 @@ var JitsiTrackEvents = require("./JitsiTrackEvents");
15 15
 var JitsiTrackErrors = require("./JitsiTrackErrors");
16 16
 var Settings = require("./modules/settings/Settings");
17 17
 var ComponentsVersions = require("./modules/version/ComponentsVersions");
18
+var GlobalOnErrorHandler = require("./modules/util/GlobalOnErrorHandler");
18 19
 
19 20
 /**
20 21
  * Creates a JitsiConference object with the given name and properties.
@@ -29,7 +30,8 @@ function JitsiConference(options) {
29 30
     if(!options.name || options.name.toLowerCase() !== options.name) {
30 31
         logger.error("Invalid conference name (no conference name passed or it"
31 32
             + "contains invalid characters like capital letters)!");
32
-         return;
33
+        throw new Error("Invalid conference name (no conference name passed or "
34
+            + "it contains invalid characters like capital letters)!");
33 35
     }
34 36
     this.options = options;
35 37
     this.connection = this.options.connection;
@@ -118,6 +120,7 @@ JitsiConference.prototype.leave = function () {
118 120
     ).then(this._leaveRoomAndRemoveParticipants.bind(this))
119 121
     .catch(function (error) {
120 122
         logger.error(error);
123
+        GlobalOnErrorHandler.callUnhandlerRejectionHandler({promise: this, reason: error});
121 124
         // We are proceeding with leaving the conference because room.leave may
122 125
         // succeed.
123 126
         this._leaveRoomAndRemoveParticipants();
@@ -924,10 +927,16 @@ function setupListeners(conference) {
924 927
             // Accept incoming call
925 928
             conference.room.setJingleSession(jingleSession);
926 929
             conference.room.connectionTimes["session.initiate"] = now;
927
-            jingleSession.initialize(false /* initiator */, conference.room);
930
+            try{
931
+                jingleSession.initialize(false /* initiator */,
932
+                    conference.room);
933
+            } catch (error) {
934
+                GlobalOnErrorHandler.callErrorHandler(error);
935
+            };
928 936
             conference.rtc.onIncommingCall(jingleSession);
929 937
             jingleSession.acceptOffer(jingleOffer, null,
930 938
                 function (error) {
939
+                    GlobalOnErrorHandler.callErrorHandler(error);
931 940
                     logger.error(
932 941
                         "Failed to accept incoming Jingle session", error);
933 942
                 }
@@ -936,6 +945,9 @@ function setupListeners(conference) {
936 945
                     jingleSession.peerconnection);
937 946
         } else {
938 947
             // Error cause this should never happen unless something is wrong !
948
+            GlobalOnErrorHandler.callErrorHandler(new Error(
949
+                "Rejecting session-initiate from non focus user: "
950
+                    + jingleSession.peerjid));
939 951
             logger.error(
940 952
                 "Rejecting session-initiate from non focus user: "
941 953
                         + jingleSession.peerjid);
@@ -1018,8 +1030,8 @@ function setupListeners(conference) {
1018 1030
     conference.room.addListener(XMPPEvents.GRACEFUL_SHUTDOWN, function () {
1019 1031
         conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.GRACEFUL_SHUTDOWN);
1020 1032
     });
1021
-    conference.room.addListener(XMPPEvents.JINGLE_FATAL_ERROR, function () {
1022
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.JINGLE_FATAL_ERROR);
1033
+    conference.room.addListener(XMPPEvents.JINGLE_FATAL_ERROR, function (session, error) {
1034
+        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.JINGLE_FATAL_ERROR, error);
1023 1035
     });
1024 1036
     conference.room.addListener(XMPPEvents.MUC_DESTROYED, function (reason) {
1025 1037
         conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONFERENCE_DESTROYED, reason);

+ 4
- 22
JitsiMeetJS.js 查看文件

@@ -15,6 +15,7 @@ var RTCUIHelper = require("./modules/RTC/RTCUIHelper");
15 15
 var Statistics = require("./modules/statistics/statistics");
16 16
 var Resolutions = require("./service/RTC/Resolutions");
17 17
 var ScriptUtil = require("./modules/util/ScriptUtil");
18
+var GlobalOnErrorHandler = require("./modules/util/GlobalOnErrorHandler");
18 19
 
19 20
 function getLowerResolution(resolution) {
20 21
     if(!Resolutions[resolution])
@@ -58,29 +59,10 @@ var LibJitsiMeet = {
58 59
     _gumFailedHandler: [],
59 60
     init: function (options) {
60 61
         Statistics.audioLevelsEnabled = !options.disableAudioLevels;
61
-
62
+        
62 63
         if (options.enableWindowOnErrorHandler) {
63
-            // if an old handler exists also fire its events
64
-            var oldOnErrorHandler = window.onerror;
65
-            window.onerror = function (message, source, lineno, colno, error) {
66
-
67
-                this.getGlobalOnErrorHandler(
68
-                    message, source, lineno, colno, error);
69
-
70
-                if (oldOnErrorHandler)
71
-                    oldOnErrorHandler(message, source, lineno, colno, error);
72
-            }.bind(this);
73
-
74
-            // if an old handler exists also fire its events
75
-            var oldOnUnhandledRejection = window.onunhandledrejection;
76
-            window.onunhandledrejection = function(event) {
77
-
78
-                this.getGlobalOnErrorHandler(
79
-                    null, null, null, null, event.reason);
80
-
81
-                if(oldOnUnhandledRejection)
82
-                    oldOnUnhandledRejection(event);
83
-            }.bind(this);
64
+            GlobalOnErrorHandler.addHandler(
65
+                this.getGlobalOnErrorHandler.bind(this));
84 66
         }
85 67
 
86 68
         return RTC.init(options || {});

+ 4
- 4
doc/API.md 查看文件

@@ -126,10 +126,10 @@ JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
126 126
         - LOCAL_TRACK_STOPPED - indicates that a local track was stopped. This
127 127
         event can be fired when ```dispose()``` method is called or for other reasons.
128 128
         - TRACK_AUDIO_OUTPUT_CHANGED - indicates that audio output device for track was changed (parameters - deviceId (string) - new audio output device ID).
129
-        
129
+
130 130
     4. mediaDevices
131 131
         - DEVICE_LIST_CHANGED - indicates that list of currently connected devices has changed (parameters - devices(MediaDeviceInfo[])).
132
-        
132
+
133 133
 
134 134
 * ```JitsiMeetJS.errors``` - JS object that contains all errors used by the API. You can use that object to check the reported errors from the API
135 135
     We have two error types - connection and conference. You can access the events with the following code ```JitsiMeetJS.errors.<error_type>.<error_name>```.
@@ -144,7 +144,7 @@ JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
144 144
         - VIDEOBRIDGE_NOT_AVAILABLE - video bridge issues.
145 145
         - RESERVATION_ERROR - error in reservation system
146 146
         - GRACEFUL_SHUTDOWN - graceful shutdown
147
-        - JINGLE_FATAL_ERROR - error in jingle
147
+        - JINGLE_FATAL_ERROR - error in jingle (the orriginal error is attached as parameter.)
148 148
         - CONFERENCE_DESTROYED - conference has been destroyed
149 149
         - CHAT_ERROR - chat error happened
150 150
         - FOCUS_DISCONNECTED - focus error happened
@@ -352,7 +352,7 @@ We have the following methods for controling the tracks:
352 352
 9. getParticipantId() - returns id(string) of the track owner
353 353
 
354 354
    Note: This method is implemented only for the remote tracks.
355
-   
355
+
356 356
 10. setAudioOutput(audioOutputDeviceId) - sets new audio output device for track's DOM elements. Video tracks are ignored.
357 357
 
358 358
 11. getDeviceId() - returns device ID associated with track (for local tracks only)

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

@@ -5,6 +5,7 @@
5 5
 
6 6
 var logger = require("jitsi-meet-logger").getLogger(__filename);
7 7
 var RTCEvents = require("../../service/RTC/RTCEvents");
8
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
8 9
 
9 10
 
10 11
 /**
@@ -71,6 +72,8 @@ DataChannels.prototype.onDataChannel = function (event) {
71 72
     };
72 73
 
73 74
     dataChannel.onerror = function (error) {
75
+        var e = new Error("Data Channel Error:" + error);
76
+        GlobalOnErrorHandler.callErrorHandler(e);
74 77
         logger.error("Data Channel Error:", error, dataChannel);
75 78
     };
76 79
 
@@ -83,10 +86,11 @@ DataChannels.prototype.onDataChannel = function (event) {
83 86
             obj = JSON.parse(data);
84 87
         }
85 88
         catch (e) {
89
+            GlobalOnErrorHandler.callErrorHandler(e);
86 90
             logger.error(
87 91
                 "Failed to parse data channel message as JSON: ",
88 92
                 data,
89
-                dataChannel);
93
+                dataChannel, e);
90 94
         }
91 95
         if (('undefined' !== typeof(obj)) && (null !== obj)) {
92 96
             var colibriClass = obj.colibriClass;

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

@@ -224,7 +224,7 @@ JitsiLocalTrack.prototype._setMute = function (mute, resolve, reject) {
224 224
                             // This is not good when video type changes after
225 225
                             // unmute, but let's not crash here
226 226
                             if (self.videoType != streamInfo.videoType) {
227
-                                logger.error(
227
+                                logger.warn(
228 228
                                     "Video type has changed after unmute!",
229 229
                                     self.videoType, streamInfo.videoType);
230 230
                                 self.videoType = streamInfo.videoType;

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

@@ -347,8 +347,7 @@ JitsiTrack.prototype.setAudioOutput = function (audioOutputDeviceId) {
347 347
             .catch(function (error) {
348 348
                 logger.error('Failed to change audio output device on element',
349 349
                     element, error);
350
-
351
-                    throw error;
350
+                throw error;
352 351
             });
353 352
     }))
354 353
     .then(function () {

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

@@ -10,6 +10,7 @@ var DataChannels = require("./DataChannels");
10 10
 var JitsiRemoteTrack = require("./JitsiRemoteTrack.js");
11 11
 var MediaType = require("../../service/RTC/MediaType");
12 12
 var VideoType = require("../../service/RTC/VideoType");
13
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
13 14
 
14 15
 function createLocalTracks(tracksInfo, options) {
15 16
     var newTracks = [];
@@ -115,8 +116,13 @@ RTC.prototype.onIncommingCall = function(event) {
115 116
                 msid: localTrack.initialMSID
116 117
             };
117 118
         }
118
-        this.room.addStream(
119
-            localTrack.getOriginalStream(), function () {}, ssrcInfo, true);
119
+        try {
120
+            this.room.addStream(
121
+                localTrack.getOriginalStream(), function () {}, ssrcInfo, true);
122
+        } catch(e) {
123
+            GlobalOnErrorHandler.callErrorHandler(e);
124
+            logger.error(e);
125
+        }
120 126
     }.bind(this));
121 127
 };
122 128
 

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

@@ -16,6 +16,7 @@ var screenObtainer = require("./ScreenObtainer");
16 16
 var JitsiTrackErrors = require("../../JitsiTrackErrors");
17 17
 var MediaType = require("../../service/RTC/MediaType");
18 18
 var VideoType = require("../../service/RTC/VideoType");
19
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
19 20
 
20 21
 var eventEmitter = new EventEmitter();
21 22
 
@@ -181,6 +182,9 @@ function getConstraints(um, options) {
181 182
             };
182 183
 
183 184
         } else {
185
+            GlobalOnErrorHandler.callErrorHandler(new Error(
186
+                "'screen' WebRTC media source is supported only in Chrome" +
187
+                " and with Temasys plugin"));
184 188
             logger.error(
185 189
                 "'screen' WebRTC media source is supported only in Chrome" +
186 190
                 " and with Temasys plugin");
@@ -565,6 +569,8 @@ function wrapAttachMediaStream(origAttachMediaStream) {
565 569
             stream.getAudioTracks && stream.getAudioTracks().length) {
566 570
             element.setSinkId(RTCUtils.getAudioOutputDevice())
567 571
                 .catch(function (ex) {
572
+                    GlobalOnErrorHandler.callUnhandlerRejectionHandler(
573
+                        {promise: this, reason: ex});
568 574
                     logger.error('Failed to set audio output on element',
569 575
                         element, ex);
570 576
                 });
@@ -750,10 +756,12 @@ var RTCUtils = {
750 756
                 });
751 757
             } else {
752 758
                 try {
753
-                    logger.error('Browser does not appear to be WebRTC-capable');
759
+                    logger.error(
760
+                        'Browser does not appear to be WebRTC-capable');
754 761
                 } catch (e) {
755 762
                 }
756
-                reject('Browser does not appear to be WebRTC-capable');
763
+                reject(
764
+                    new Error('Browser does not appear to be WebRTC-capable'));
757 765
                 return;
758 766
             }
759 767
 

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

@@ -4,6 +4,7 @@ var logger = require("jitsi-meet-logger").getLogger(__filename);
4 4
 var RTCBrowserType = require("./RTCBrowserType");
5 5
 var AdapterJS = require("./adapter.screenshare");
6 6
 var JitsiTrackErrors = require("../../JitsiTrackErrors");
7
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
7 8
 
8 9
 /**
9 10
  * Indicates whether the Chrome desktop sharing extension is installed.
@@ -295,6 +296,7 @@ function isUpdateRequired(minVersion, extVersion) {
295 296
         return false;
296 297
     }
297 298
     catch (e) {
299
+        GlobalOnErrorHandler.callErrorHandler(e);
298 300
         logger.error("Failed to parse extension version", e);
299 301
         return true;
300 302
     }

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

@@ -1,5 +1,6 @@
1 1
 /* global $, Strophe, callstats */
2 2
 var logger = require("jitsi-meet-logger").getLogger(__filename);
3
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
3 4
 
4 5
 var jsSHA = require('jssha');
5 6
 var io = require('socket.io-client');
@@ -80,6 +81,7 @@ function _try_catch (f) {
80 81
         try {
81 82
             f.apply(this, arguments);
82 83
         } catch (e) {
84
+            GlobalOnErrorHandler.callErrorHandler(e);
83 85
             logger.error(e);
84 86
         }
85 87
     };
@@ -125,6 +127,7 @@ var CallStats = _try_catch(function(jingleSession, Settings, options) {
125 127
         // The callstats.io API failed to initialize (e.g. because its
126 128
         // download failed to succeed in general or on time). Further
127 129
         // attempts to utilize it cannot possibly succeed.
130
+        GlobalOnErrorHandler.callErrorHandler(e);
128 131
         callStats = null;
129 132
         logger.error(e);
130 133
     }

+ 3
- 2
modules/statistics/RTPStatsCollector.js 查看文件

@@ -4,6 +4,7 @@
4 4
 var logger = require("jitsi-meet-logger").getLogger(__filename);
5 5
 var RTCBrowserType = require("../RTC/RTCBrowserType");
6 6
 var StatisticsEvents = require("../../service/statistics/Events");
7
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
7 8
 
8 9
 /* Whether we support the browser we are running into for logging statistics */
9 10
 var browserSupported = RTCBrowserType.isChrome() ||
@@ -300,6 +301,7 @@ StatsCollector.prototype.stop = function () {
300 301
  * @param error an error that occurred on <tt>getStats</tt> call.
301 302
  */
302 303
 StatsCollector.prototype.errorCallback = function (error) {
304
+    GlobalOnErrorHandler.callErrorHandler(error);
303 305
     logger.error("Get stats error", error);
304 306
     this.stop();
305 307
 };
@@ -322,7 +324,6 @@ StatsCollector.prototype.start = function () {
322 324
                     else {
323 325
                         results = report.result();
324 326
                     }
325
-                    //logger.error("Got interval report", results);
326 327
                     self.currentAudioLevelsReport = results;
327 328
                     self.processAudioLevelReport();
328 329
                     self.baselineAudioLevelsReport =
@@ -350,12 +351,12 @@ StatsCollector.prototype.start = function () {
350 351
                             //chrome
351 352
                             results = report.result();
352 353
                         }
353
-                        //logger.error("Got interval report", results);
354 354
                         self.currentStatsReport = results;
355 355
                         try {
356 356
                             self.processStatsReport();
357 357
                         }
358 358
                         catch (e) {
359
+                            GlobalOnErrorHandler.callErrorHandler(e);
359 360
                             logger.error("Unsupported key:" + e, e);
360 361
                         }
361 362
 

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

@@ -0,0 +1,82 @@
1
+/**
2
+ * This utility class defines custom onerror and onunhandledrejection functions
3
+ * The custom error handlers are respecting the previous defined error handlers
4
+ * GlobalOnErrorHandler class provides utilities to add many custom error
5
+ * handlers and to execute the error handlers directly.
6
+ */
7
+
8
+
9
+/**
10
+ * List with global error handlers that will be executed.
11
+ */
12
+var handlers = [];
13
+
14
+// if an old handler exists also fire its events
15
+var oldOnErrorHandler = window.onerror;
16
+
17
+/**
18
+ * Custom error handler that calls the old global error handler and executes
19
+ * all handlers that were previously added.
20
+ */
21
+function JitsiGlobalErrorHandler(message, source, lineno, colno, error) {
22
+    handlers.forEach(function (handler) {
23
+        handler(message, source, lineno, colno, error);
24
+    });
25
+    if (oldOnErrorHandler)
26
+        oldOnErrorHandler(message, source, lineno, colno, error);
27
+}
28
+
29
+// if an old handler exists also fire its events
30
+var oldOnUnhandledRejection = window.onunhandledrejection;
31
+
32
+/**
33
+ * Custom handler that calls the old global handler and executes
34
+ * all handlers that were previously added. This handler handles rejected
35
+ * Promises.
36
+ */
37
+function JitsiGlobalUnhandlerRejection(event) {
38
+    handlers.forEach(function (handler) {
39
+        handler(null, null, null, null, event.reason);
40
+    });
41
+    if(oldOnUnhandledRejection)
42
+        oldOnUnhandledRejection(event);
43
+}
44
+
45
+//Setting the custom error handlers.
46
+window.onerror = JitsiGlobalErrorHandler;
47
+window.onunhandledrejection = JitsiGlobalUnhandlerRejection;
48
+
49
+
50
+var GlobalOnErrorHandler = {
51
+    /**
52
+     * Adds new error handlers.
53
+     * @param handler the new handler.
54
+     */
55
+    addHandler: function (handler) {
56
+        handlers.push(handler);
57
+    },
58
+    /**
59
+     * Calls the global error handler if there is one.
60
+     * @param error the error that is going to be passed to the error handler
61
+     */
62
+    callErrorHandler: function (error) {
63
+        var errHandler = window.onerror;
64
+        if(!errHandler)
65
+            return;
66
+        errHandler.call(null, null, null, null, null, error);
67
+    },
68
+    /**
69
+     * Calls the global rejection handler if there is one.
70
+     * @param error the error that is going to be passed to the rejection
71
+     * handler.
72
+     */
73
+    callUnhandlerRejectionHandler: function (error) {
74
+        var errHandler = window.onunhandledrejection;
75
+        if(!errHandler)
76
+            return;
77
+        errHandler.call(null, error);
78
+    }
79
+};
80
+
81
+
82
+module.exports = GlobalOnErrorHandler;

+ 7
- 2
modules/xmpp/ChatRoom.js 查看文件

@@ -6,6 +6,8 @@ var MediaType = require("../../service/RTC/MediaType");
6 6
 var Moderator = require("./moderator");
7 7
 var EventEmitter = require("events");
8 8
 var Recorder = require("./recording");
9
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
10
+
9 11
 var JIBRI_XMLNS = 'http://jitsi.org/protocol/jibri';
10 12
 
11 13
 var parser = {
@@ -198,8 +200,9 @@ ChatRoom.prototype.createNonAnonymousRoom = function () {
198 200
         if (!$(form).find(
199 201
                 '>query>x[xmlns="jabber:x:data"]' +
200 202
                 '>field[var="muc#roomconfig_whois"]').length) {
201
-
202
-            logger.error('non-anonymous rooms not supported');
203
+            GlobalOnErrorHandler.callErrorHandler(
204
+                new Error("non-anonymous rooms not supported"));
205
+            logger.error("non-anonymous rooms not supported");
203 206
             return;
204 207
         }
205 208
 
@@ -218,6 +221,7 @@ ChatRoom.prototype.createNonAnonymousRoom = function () {
218 221
         self.connection.sendIQ(formSubmit);
219 222
 
220 223
     }, function (error) {
224
+        GlobalOnErrorHandler.callErrorHandler(error);
221 225
         logger.error("Error getting room configuration form");
222 226
     });
223 227
 };
@@ -374,6 +378,7 @@ ChatRoom.prototype.processNode = function (node, from) {
374 378
             this.presHandlers[node.tagName](
375 379
                 node, Strophe.getResourceFromJid(from), from);
376 380
     } catch (e) {
381
+        GlobalOnErrorHandler.callErrorHandler(e);
377 382
         logger.error('Error processing:' + node.tagName
378 383
             + ' node.', e);
379 384
     }

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

@@ -69,9 +69,11 @@ function JingleSession(me, sid, peerjid, connection,
69 69
  */
70 70
 JingleSession.prototype.initialize = function(isInitiator, room) {
71 71
     if (this.state !== null) {
72
+
72 73
         logger.error('attempt to initiate on session ' + this.sid +
73 74
         'in state ' + this.state);
74
-        return;
75
+        throw new Error('attempt to initiate on session ' + this.sid +
76
+            'in state ' + this.state);
75 77
     }
76 78
     this.room = room;
77 79
     this.state = 'pending';

+ 89
- 49
modules/xmpp/JingleSessionPC.js 查看文件

@@ -11,6 +11,7 @@ var async = require("async");
11 11
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
12 12
 var RTCBrowserType = require("../RTC/RTCBrowserType");
13 13
 var RTC = require("../RTC/RTC");
14
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
14 15
 
15 16
 /**
16 17
  * Constant tells how long we're going to wait for IQ response, before timeout
@@ -175,7 +176,10 @@ JingleSessionPC.prototype.sendIceCandidate = function (candidate) {
175 176
         var ice = SDPUtil.iceparams(this.localSDP.media[candidate.sdpMLineIndex], this.localSDP.session);
176 177
         var jcand = SDPUtil.candidateToJingle(candidate.candidate);
177 178
         if (!(ice && jcand)) {
178
-            logger.error('failed to get ice && jcand');
179
+            //FIxed
180
+            GlobalOnErrorHandler.callErrorHandler(
181
+                new Error("failed to get ice && jcand"));
182
+            logger.error("failed to get ice && jcand");
179 183
             return;
180 184
         }
181 185
         ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
@@ -247,7 +251,10 @@ JingleSessionPC.prototype.sendIceCandidates = function (candidates) {
247 251
     // might merge last-candidate notification into this, but it is called alot later. See webrtc issue #2340
248 252
     //logger.log('was this the last candidate', this.lasticecandidate);
249 253
     this.connection.sendIQ(
250
-        cand, null, this.newJingleErrorHandler(cand), IQ_TIMEOUT);
254
+        cand, null, this.newJingleErrorHandler(cand, function (error) {
255
+            GlobalOnErrorHandler.callErrorHandler(
256
+                new Error("Jingle error: " + JSON.stringify(error)));
257
+        }), IQ_TIMEOUT);
251 258
 };
252 259
 
253 260
 JingleSessionPC.prototype.readSsrcInfo = function (contents) {
@@ -405,7 +412,8 @@ JingleSessionPC.prototype.setLocalDescription = function (sdp, success,
405 412
             logger.error('setLocalDescription failed', error);
406 413
             if (failure)
407 414
                 failure(error);
408
-            self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
415
+            self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED,
416
+                error);
409 417
         }
410 418
     );
411 419
     // Some checks for STUN and TURN candiates present in local SDP
@@ -608,6 +616,7 @@ JingleSessionPC.prototype.sendTransportReject = function(success, failure) {
608 616
         IQ_TIMEOUT);
609 617
 };
610 618
 
619
+//FIXME: I think this method is not used!
611 620
 JingleSessionPC.prototype.terminate = function (reason,  text,
612 621
                                                 success, failure) {
613 622
     var term = $iq({to: this.peerjid,
@@ -774,7 +783,11 @@ JingleSessionPC.prototype.removeSource = function (elem) {
774 783
             var ssrc = $(this).attr('ssrc');
775 784
             // This should never happen, but can be useful for bug detection
776 785
             if(mySdp.containsSSRC(ssrc)){
777
-                logger.error("Got remove stream request for my own ssrc: "+ssrc);
786
+                GlobalOnErrorHandler.callErrorHandler(
787
+                    new Error("Got remove stream request for my own ssrc: " +
788
+                    ssrc));
789
+                logger.error("Got remove stream request for my own ssrc: " +
790
+                    ssrc);
778 791
                 return;
779 792
             }
780 793
             ssrcs.push(ssrc);
@@ -853,6 +866,8 @@ JingleSessionPC.prototype._modifySources = function (successCallback, queueCallb
853 866
 
854 867
             if(self.signalingState == 'closed') {
855 868
                 logger.error("createAnswer attempt on closed state");
869
+                GlobalOnErrorHandler.callErrorHandler(
870
+                    new Error("createAnswer attempt on closed state"));
856 871
                 queueCallback("createAnswer attempt on closed state");
857 872
                 return;
858 873
             }
@@ -891,18 +906,26 @@ JingleSessionPC.prototype._modifySources = function (successCallback, queueCallb
891 906
                             queueCallback();
892 907
                         },
893 908
                         function(error) {
894
-                            logger.error('modified setLocalDescription failed', error);
909
+                            GlobalOnErrorHandler.callErrorHandler(new Error(
910
+                                "modified setLocalDescription failed" +
911
+                                error));
912
+                            logger.error("modified setLocalDescription failed",
913
+                                error);
895 914
                             queueCallback(error);
896 915
                         }
897 916
                     );
898 917
                 },
899 918
                 function(error) {
919
+                    GlobalOnErrorHandler.callErrorHandler(new Error(
920
+                        "modified answer failed" + error));
900 921
                     logger.error('modified answer failed', error);
901 922
                     queueCallback(error);
902 923
                 }
903 924
             );
904 925
         },
905 926
         function(error) {
927
+            GlobalOnErrorHandler.callErrorHandler(new Error(
928
+                'modify failed' + error));
906 929
             logger.error('modify failed', error);
907 930
             queueCallback(error);
908 931
         }
@@ -1112,7 +1135,10 @@ JingleSessionPC.prototype.notifyMySSRCUpdate = function (old_sdp, new_sdp) {
1112 1135
     if (removed && remove) {
1113 1136
         logger.info("Sending source-remove", remove.tree());
1114 1137
         this.connection.sendIQ(
1115
-            remove, null, this.newJingleErrorHandler(remove), IQ_TIMEOUT);
1138
+            remove, null, this.newJingleErrorHandler(remove, function (error) {
1139
+                GlobalOnErrorHandler.callErrorHandler(
1140
+                    new Error("Jingle error: " + JSON.stringify(error)));
1141
+            }), IQ_TIMEOUT);
1116 1142
     } else {
1117 1143
         logger.log('removal not necessary');
1118 1144
     }
@@ -1134,7 +1160,10 @@ JingleSessionPC.prototype.notifyMySSRCUpdate = function (old_sdp, new_sdp) {
1134 1160
     if (added && add) {
1135 1161
         logger.info("Sending source-add", add.tree());
1136 1162
         this.connection.sendIQ(
1137
-            add, null, this.newJingleErrorHandler(add), IQ_TIMEOUT);
1163
+            add, null, this.newJingleErrorHandler(add, function (error) {
1164
+                GlobalOnErrorHandler.callErrorHandler(
1165
+                    new Error("Jingle error: " + JSON.stringify(error)));
1166
+            }), IQ_TIMEOUT);
1138 1167
     } else {
1139 1168
         logger.log('addition not necessary');
1140 1169
     }
@@ -1187,9 +1216,6 @@ JingleSessionPC.prototype.newJingleErrorHandler = function(request, failureCb) {
1187 1216
         if (failureCb) {
1188 1217
             failureCb(error);
1189 1218
         }
1190
-
1191
-        this.room.eventEmitter.emit(XMPPEvents.JINGLE_ERROR, error);
1192
-
1193 1219
     }.bind(this);
1194 1220
 };
1195 1221
 
@@ -1249,45 +1275,50 @@ JingleSessionPC.prototype.remoteTrackAdded = function (stream, track) {
1249 1275
         owner: undefined, /* to be determined below */
1250 1276
         muted: null /* will be set in the ChatRoom */
1251 1277
     };
1278
+    try{
1279
+        // look up an associated JID for a stream id
1280
+        if (!mediaType) {
1281
+            logger.error("MediaType undefined", track);
1282
+            throw new Error("MediaType undefined for remote track");
1283
+        }
1252 1284
 
1253
-    // look up an associated JID for a stream id
1254
-    if (!mediaType) {
1255
-        logger.error("MediaType undefined", track);
1256
-        return;
1257
-    }
1258
-
1259
-    var remoteSDP = new SDP(this.peerconnection.remoteDescription.sdp);
1260
-    var medialines = remoteSDP.media.filter(function (mediaLines) {
1261
-        return mediaLines.startsWith("m=" + mediaType);
1262
-    });
1263
-
1264
-    if (!medialines.length) {
1265
-        logger.error("No media for type " + mediaType + " found in remote SDP");
1266
-        return;
1267
-    }
1285
+        var remoteSDP = new SDP(this.peerconnection.remoteDescription.sdp);
1286
+        var medialines = remoteSDP.media.filter(function (mediaLines){
1287
+            return mediaLines.startsWith("m=" + mediaType);
1288
+        });
1289
+        if (!medialines.length) {
1290
+            logger.error("No media for type " + mediaType + " found in remote SDP");
1291
+            throw new Error("No media for type " + mediaType +
1292
+                " found in remote SDP for remote track");
1293
+        }
1268 1294
 
1269
-    var ssrclines = SDPUtil.find_lines(medialines[0], 'a=ssrc:');
1270
-    ssrclines = ssrclines.filter(function (line) {
1271
-        var msid = RTCBrowserType.isTemasysPluginUsed() ? 'mslabel' : 'msid';
1272
-        return line.indexOf(msid + ':' + streamId) !== -1;
1273
-    });
1295
+        var ssrclines = SDPUtil.find_lines(medialines[0], 'a=ssrc:');
1296
+        ssrclines = ssrclines.filter(function (line) {
1297
+            var msid = RTCBrowserType.isTemasysPluginUsed() ? 'mslabel' : 'msid';
1298
+            return line.indexOf(msid + ':' + streamId) !== -1;
1299
+        });
1274 1300
 
1275
-    var thessrc;
1276
-    if (ssrclines.length) {
1277
-        thessrc = ssrclines[0].substring(7).split(' ')[0];
1278
-        if (!this.ssrcOwners[thessrc]) {
1279
-            logger.error("No SSRC owner known for: " + thessrc);
1280
-            return;
1301
+        var thessrc;
1302
+        if (ssrclines.length) {
1303
+            thessrc = ssrclines[0].substring(7).split(' ')[0];
1304
+            if (!this.ssrcOwners[thessrc]) {
1305
+                logger.error("No SSRC owner known for: " + thessrc);
1306
+                throw new Error("No SSRC owner known for: " + thessrc +
1307
+                    " for remote track");
1308
+            }
1309
+            jitsiTrackAddedEvent.owner = this.ssrcOwners[thessrc];
1310
+            logger.log('associated jid', this.ssrcOwners[thessrc], thessrc);
1311
+        } else {
1312
+            logger.error("No SSRC lines for ", streamId);
1313
+            throw new Error("No SSRC lines for streamId " + streamId +
1314
+                " for remote track");
1281 1315
         }
1282
-        jitsiTrackAddedEvent.owner = this.ssrcOwners[thessrc];
1283
-        logger.log('associated jid', this.ssrcOwners[thessrc], thessrc);
1284
-    } else {
1285
-        logger.error("No SSRC lines for ", streamId);
1286
-        return;
1287
-    }
1288
-    jitsiTrackAddedEvent.ssrc = thessrc;
1316
+        jitsiTrackAddedEvent.ssrc = thessrc;
1289 1317
 
1290
-    this.room.remoteTrackAdded(jitsiTrackAddedEvent);
1318
+        this.room.remoteTrackAdded(jitsiTrackAddedEvent);
1319
+    } catch (error) {
1320
+        GlobalOnErrorHandler.callErrorHandler(error);
1321
+    }
1291 1322
 };
1292 1323
 
1293 1324
 /**
@@ -1321,13 +1352,21 @@ JingleSessionPC.prototype.remoteTrackRemoved = function (stream, track) {
1321 1352
     logger.info("Remote track removed", stream, track);
1322 1353
     var streamId = RTC.getStreamID(stream);
1323 1354
     var trackId = track && track.id;
1324
-    if (!streamId) {
1325
-        logger.error("No stream ID for", stream);
1326
-    } else if (!trackId) {
1327
-        logger.error("No track ID for", track);
1328
-    } else {
1355
+    try{
1356
+        if (!streamId) {
1357
+            logger.error("No stream ID for", stream);
1358
+            throw new Error("Remote track removal failed - No stream ID");
1359
+        }
1360
+
1361
+        if (!trackId) {
1362
+            logger.error("No track ID for", track);
1363
+            throw new Error("Remote track removal failed - No track ID");
1364
+        }
1365
+
1329 1366
         this.room.eventEmitter.emit(
1330 1367
             XMPPEvents.REMOTE_TRACK_REMOVED, streamId, trackId);
1368
+    } catch (error) {
1369
+        GlobalOnErrorHandler.callErrorHandler(error);
1331 1370
     }
1332 1371
 };
1333 1372
 
@@ -1365,6 +1404,7 @@ JingleSessionPC.prototype.fixJingle = function(jingle) {
1365 1404
             this.fixSourceRemoveJingle(jingle);
1366 1405
             break;
1367 1406
         default:
1407
+            GlobalOnErrorHandler.callErrorHandler("Unknown jingle action!");
1368 1408
             logger.error("Unknown jingle action!");
1369 1409
             return false;
1370 1410
     }

+ 21
- 30
modules/xmpp/TraceablePeerConnection.js 查看文件

@@ -5,6 +5,7 @@ var RTCBrowserType = require("../RTC/RTCBrowserType.js");
5 5
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
6 6
 var transform = require('sdp-transform');
7 7
 var RandomUtil = require('../util/RandomUtil');
8
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
8 9
 
9 10
 var SIMULCAST_LAYERS = 3;
10 11
 
@@ -201,6 +202,8 @@ TraceablePeerConnection.prototype.ssrcReplacement = function (desc) {
201 202
                         ssrcOperation.ssrc.ssrcs.length) {
202 203
                         ssrc = ssrcOperation.ssrc.ssrcs[0];
203 204
                     } else {
205
+                        GlobalOnErrorHandler.callErrorHandler(
206
+                            new Error("SSRC replacement error!"));
204 207
                         logger.error("SSRC replacement error!");
205 208
                         break;
206 209
                     }
@@ -467,17 +470,10 @@ Object.keys(getters).forEach(function (prop) {
467 470
 
468 471
 TraceablePeerConnection.prototype.addStream = function (stream, ssrcInfo) {
469 472
     this.trace('addStream', stream? stream.id : "null");
470
-    try
471
-    {
472
-        if(stream)
473
-            this.peerconnection.addStream(stream);
474
-        if(ssrcInfo && this.replaceSSRCs[ssrcInfo.mtype])
475
-            this.replaceSSRCs[ssrcInfo.mtype].push(ssrcInfo);
476
-    }
477
-    catch (e)
478
-    {
479
-        logger.error(e);
480
-    }
473
+    if(stream)
474
+        this.peerconnection.addStream(stream);
475
+    if(ssrcInfo && this.replaceSSRCs[ssrcInfo.mtype])
476
+        this.replaceSSRCs[ssrcInfo.mtype].push(ssrcInfo);
481 477
 };
482 478
 
483 479
 TraceablePeerConnection.prototype.removeStream = function (stream, stopStreams,
@@ -486,28 +482,23 @@ ssrcInfo) {
486 482
     if(stopStreams) {
487 483
         RTC.stopMediaStream(stream);
488 484
     }
489
-
490
-    try {
491
-        // FF doesn't support this yet.
492
-        if (this.peerconnection.removeStream) {
493
-            this.peerconnection.removeStream(stream);
494
-            // Removing all cached ssrcs for the streams that are removed or
495
-            // muted.
496
-            if(ssrcInfo && this.replaceSSRCs[ssrcInfo.mtype]) {
497
-                for(i = 0; i < this.replaceSSRCs[ssrcInfo.mtype].length; i++) {
498
-                    var op = this.replaceSSRCs[ssrcInfo.mtype][i];
499
-                    if(op.type === "unmute" &&
500
-                        op.ssrc.ssrcs.join("_") ===
501
-                        ssrcInfo.ssrc.ssrcs.join("_")) {
502
-                        this.replaceSSRCs[ssrcInfo.mtype].splice(i, 1);
503
-                        break;
504
-                    }
485
+    // FF doesn't support this yet.
486
+    if (this.peerconnection.removeStream) {
487
+        this.peerconnection.removeStream(stream);
488
+        // Removing all cached ssrcs for the streams that are removed or
489
+        // muted.
490
+        if(ssrcInfo && this.replaceSSRCs[ssrcInfo.mtype]) {
491
+            for(i = 0; i < this.replaceSSRCs[ssrcInfo.mtype].length; i++) {
492
+                var op = this.replaceSSRCs[ssrcInfo.mtype][i];
493
+                if(op.type === "unmute" &&
494
+                    op.ssrc.ssrcs.join("_") ===
495
+                    ssrcInfo.ssrc.ssrcs.join("_")) {
496
+                    this.replaceSSRCs[ssrcInfo.mtype].splice(i, 1);
497
+                    break;
505 498
                 }
506
-                this.replaceSSRCs[ssrcInfo.mtype].push(ssrcInfo);
507 499
             }
500
+            this.replaceSSRCs[ssrcInfo.mtype].push(ssrcInfo);
508 501
         }
509
-    } catch (e) {
510
-        logger.error(e);
511 502
     }
512 503
 };
513 504
 

+ 12
- 1
modules/xmpp/moderator.js 查看文件

@@ -2,9 +2,9 @@
2 2
 
3 3
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4 4
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
5
-
6 5
 var AuthenticationEvents
7 6
     = require("../../service/authentication/AuthenticationEvents");
7
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
8 8
 
9 9
 function createExpBackoffTimer(step) {
10 10
     var count = 1;
@@ -356,6 +356,8 @@ Moderator.prototype._allocateConferenceFocusError = function (error, callback) {
356 356
         return;
357 357
     }
358 358
     var waitMs = self.getNextErrorTimeout();
359
+    GlobalOnErrorHandler.callErrorHandler(
360
+        new Error("Focus error, retry after "+ waitMs));
359 361
     logger.error("Focus error, retry after " + waitMs, error);
360 362
     // Show message
361 363
     var focusComponent = self.getFocusComponent();
@@ -441,12 +443,16 @@ Moderator.prototype.getLoginUrl =  function (urlCallback, failureCallback) {
441 443
                 logger.info("Got auth url: " + url);
442 444
                 urlCallback(url);
443 445
             } else {
446
+                GlobalOnErrorHandler.callErrorHandler(
447
+                    new Error("Failed to get auth url from the focus"));
444 448
                 logger.error(
445 449
                     "Failed to get auth url from the focus", result);
446 450
                 failureCallback(result);
447 451
             }
448 452
         },
449 453
         function (error) {
454
+            GlobalOnErrorHandler.callErrorHandler(
455
+                new Error("Get auth url error"));
450 456
             logger.error("Get auth url error", error);
451 457
             failureCallback(error);
452 458
         }
@@ -470,12 +476,16 @@ Moderator.prototype.getPopupLoginUrl = function (urlCallback, failureCallback) {
470 476
                 logger.info("Got POPUP auth url:  " + url);
471 477
                 urlCallback(url);
472 478
             } else {
479
+                GlobalOnErrorHandler.callErrorHandler(
480
+                    new Error("Failed to get POPUP auth url from the focus"));
473 481
                 logger.error(
474 482
                     "Failed to get POPUP auth url from the focus", result);
475 483
                failureCallback(result);
476 484
             }
477 485
         },
478 486
         function (error) {
487
+            GlobalOnErrorHandler.callErrorHandler(
488
+                new Error("Get POPUP auth url error"));
479 489
             logger.error('Get POPUP auth url error', error);
480 490
             failureCallback(error);
481 491
         }
@@ -505,6 +515,7 @@ Moderator.prototype.logout =  function (callback) {
505 515
             callback(logoutUrl);
506 516
         }.bind(this),
507 517
         function (error) {
518
+            GlobalOnErrorHandler.callErrorHandler(new Error("Logout error"));
508 519
             logger.error("Logout error", error);
509 520
         }
510 521
     );

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

@@ -2,6 +2,7 @@
2 2
    Toolbar, Util, Promise */
3 3
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
4 4
 var JitsiRecorderErrors = require("../../JitsiRecorderErrors");
5
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
5 6
 
6 7
 var logger = require("jitsi-meet-logger").getLogger(__filename);
7 8
 
@@ -201,6 +202,8 @@ function (state, callback, errCallback, options) {
201 202
             this.setRecordingJibri(state, callback, errCallback, options);
202 203
             break;
203 204
         default:
205
+            GlobalOnErrorHandler.callErrorHandler(
206
+                new Error("Unknown recording type!"));
204 207
             logger.error("Unknown recording type!");
205 208
             return;
206 209
     }

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

@@ -28,6 +28,7 @@ module.exports = function(XMPP) {
28 28
             var roomJid = Strophe.getBareJidFromJid(jid);
29 29
             if (this.rooms[roomJid]) {
30 30
                 logger.error("You are already in the room!");
31
+                throw new Error("You are already in the room!");
31 32
                 return;
32 33
             }
33 34
             this.rooms[roomJid] = new ChatRoom(this.connection, jid,

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

@@ -5,6 +5,7 @@ var logger = require("jitsi-meet-logger").getLogger(__filename);
5 5
 var JingleSession = require("./JingleSessionPC");
6 6
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
7 7
 var RTCBrowserType = require("../RTC/RTCBrowserType");
8
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
8 9
 
9 10
 
10 11
 module.exports = function(XMPP, eventEmitter) {
@@ -154,6 +155,7 @@ module.exports = function(XMPP, eventEmitter) {
154 155
                                 window.performance.now());
155 156
                         },
156 157
                         function(error) {
158
+                            GlobalOnErrorHandler.callErrorHandler(error);
157 159
                             logger.error('Transport replace failed', error);
158 160
                             sess.sendTransportReject();
159 161
                         });

+ 7
- 1
modules/xmpp/strophe.ping.js 查看文件

@@ -1,7 +1,7 @@
1 1
 /* global $, $iq, Strophe */
2 2
 
3 3
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4
-
4
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
5 5
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
6 6
 
7 7
 /**
@@ -77,6 +77,8 @@ module.exports = function (XMPP, eventEmitter) {
77 77
                         callback(ping.length > 0);
78 78
                     },
79 79
                     function (error) {
80
+                        GlobalOnErrorHandler.callErrorHandler(
81
+                            new Error("Ping feature discovery error" + error));
80 82
                         logger.error("Ping feature discovery error", error);
81 83
                         callback(false);
82 84
                     }
@@ -96,6 +98,8 @@ module.exports = function (XMPP, eventEmitter) {
96 98
          */
97 99
         startInterval: function (remoteJid, interval) {
98 100
             if (this.intervalId) {
101
+                GlobalOnErrorHandler.callErrorHandler(
102
+                    new Error("Ping task scheduled already"));
99 103
                 logger.error("Ping task scheduled already");
100 104
                 return;
101 105
             }
@@ -110,6 +114,8 @@ module.exports = function (XMPP, eventEmitter) {
110 114
                 },
111 115
                 function (error) {
112 116
                     self.failedPings += 1;
117
+                    GlobalOnErrorHandler.callErrorHandler(
118
+                        new Error("Ping " + (error ? "error" : "timeout")));
113 119
                     logger.error(
114 120
                         "Ping " + (error ? "error" : "timeout"), error);
115 121
                     if (self.failedPings >= PING_THRESHOLD) {

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

@@ -3,6 +3,7 @@
3 3
  * Strophe logger implementation. Logs from level WARN and above.
4 4
  */
5 5
 var logger = require("jitsi-meet-logger").getLogger(__filename);
6
+var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
6 7
 
7 8
 module.exports = function () {
8 9
 
@@ -13,6 +14,8 @@ module.exports = function () {
13 14
                 break;
14 15
             case Strophe.LogLevel.ERROR:
15 16
             case Strophe.LogLevel.FATAL:
17
+                GlobalOnErrorHandler.callErrorHandler(
18
+                    new Error("Strophe: " + msg));
16 19
                 logger.error("Strophe: " + msg);
17 20
                 break;
18 21
         }

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

@@ -43,17 +43,6 @@ var XMPPEvents = {
43 43
     FOCUS_DISCONNECTED: 'xmpp.focus_disconnected',
44 44
     FOCUS_LEFT: "xmpp.focus_left",
45 45
     GRACEFUL_SHUTDOWN: "xmpp.graceful_shutdown",
46
-    /* Event fired when XMPP error is returned to any request, it is meant to be
47
-     * used to report 'signaling' errors to CallStats
48
-     *
49
-     * {
50
-     *   code: {XMPP error code}
51
-     *   reason: {XMPP error condition}
52
-     *   source = request.tree()
53
-     *   session = {JingleSession instance}
54
-     * }
55
-     */
56
-    JINGLE_ERROR: 'xmpp.jingle_error',
57 46
     // Event fired when we have failed to set initial offer
58 47
     JINGLE_FATAL_ERROR: 'xmpp.jingle_fatal_error',
59 48
     // Designates an event indicating that we were kicked from the XMPP MUC.

Loading…
取消
儲存