浏览代码

feat(JitsiConnectionErrors): implement 'SERVER_ERROR'

JitsiConnectionEvents.CONNECTION_FAILED with SERVER_ERROR will be
emitted when the XMPP connection is closed due too many 5xx HTTP errors.
dev1
paweldomas 8 年前
父节点
当前提交
ef62ccd330
共有 3 个文件被更改,包括 79 次插入5 次删除
  1. 5
    0
      JitsiConnectionErrors.js
  2. 60
    1
      modules/xmpp/strophe.util.js
  3. 14
    4
      modules/xmpp/xmpp.js

+ 5
- 0
JitsiConnectionErrors.js 查看文件

14
  * Indicates that a password is required in order to join the conference.
14
  * Indicates that a password is required in order to join the conference.
15
  */
15
  */
16
 export const PASSWORD_REQUIRED = "connection.passwordRequired";
16
 export const PASSWORD_REQUIRED = "connection.passwordRequired";
17
+/**
18
+ * Indicates that the connection was dropped, because of too many 5xx HTTP
19
+ * errors on BOSH requests.
20
+ */
21
+export const SERVER_ERROR = "connection.serverError";

+ 60
- 1
modules/xmpp/strophe.util.js 查看文件

1
-/* global Strophe */
1
+/* global __filename, Strophe */
2
 /**
2
 /**
3
  * Strophe logger implementation. Logs from level WARN and above.
3
  * Strophe logger implementation. Logs from level WARN and above.
4
  */
4
  */
6
 const logger = getLogger(__filename);
6
 const logger = getLogger(__filename);
7
 import GlobalOnErrorHandler from "../util/GlobalOnErrorHandler";
7
 import GlobalOnErrorHandler from "../util/GlobalOnErrorHandler";
8
 
8
 
9
+/**
10
+ * This is the last HTTP error status captured from Strophe debug logs.
11
+ * The purpose of storing it is to distinguish between the network and
12
+ * infrastructure reason for connection being dropped (see connectionHandler in
13
+ * xmpp.js). The value will be cleared (-1) if the subsequent request succeeds
14
+ * which means that the failure could be transient.
15
+ *
16
+ * FIXME in the latest Strophe (not released on npm) there is API to handle
17
+ * particular HTTP errors, but there is no way to learn if the subsequent
18
+ * request succeeded in order to tell if the error was one time incident or if
19
+ * it was the reason for dropping the connection by Strophe (the connection is
20
+ * dropped after 5 subsequent failures). Ideally Strophe should provide more
21
+ * details about the reason on why the connection stopped.
22
+ *
23
+ * @type {number}
24
+ */
25
+let lastErrorStatus = -1;
26
+
27
+/**
28
+ * A regular expression used to catch Strophe's log message indicating that the
29
+ * last BOSH request was successful. When there is such message seen the
30
+ * {@link lastErrorStatus} will be set back to '-1'.
31
+ * @type {RegExp}
32
+ */
33
+const resetLastErrorStatusRegExpr = /request id \d+.\d+ got 200/;
34
+
35
+/**
36
+ * A regular expression used to capture the current value of the BOSH request
37
+ * error status (HTTP error code or '0' or something else).
38
+ * @type {RegExp}
39
+ */
40
+const lastErrorStatusRegExpr
41
+    = /request errored, status: (\d+), number of errors: \d+/;
42
+
9
 export default function () {
43
 export default function () {
10
 
44
 
11
     Strophe.log = function (level, msg) {
45
     Strophe.log = function (level, msg) {
14
         // Strophe log entry about secondary request timeout does not mean that
48
         // Strophe log entry about secondary request timeout does not mean that
15
         // it's a final failure(the request will be restarted), so we lower it's
49
         // it's a final failure(the request will be restarted), so we lower it's
16
         // level here to a warning.
50
         // level here to a warning.
51
+        logger.trace("Strophe", level, msg);
17
         if (typeof msg === 'string' &&
52
         if (typeof msg === 'string' &&
18
                 msg.indexOf("Request ") !== -1 &&
53
                 msg.indexOf("Request ") !== -1 &&
19
                 msg.indexOf("timed out (secondary), restarting") !== -1) {
54
                 msg.indexOf("timed out (secondary), restarting") !== -1) {
20
             level = Strophe.LogLevel.WARN;
55
             level = Strophe.LogLevel.WARN;
21
         }
56
         }
57
+        /* eslint-disable no-case-declarations */
22
         switch (level) {
58
         switch (level) {
59
+            case Strophe.LogLevel.DEBUG:
60
+                if (resetLastErrorStatusRegExpr.test(msg)) {
61
+                    logger.debug("Reset lastErrorStatus");
62
+                    lastErrorStatus = -1;
63
+                }
64
+                break;
23
             case Strophe.LogLevel.WARN:
65
             case Strophe.LogLevel.WARN:
24
                 logger.warn("Strophe: " + msg);
66
                 logger.warn("Strophe: " + msg);
67
+                const errStatusCapture = lastErrorStatusRegExpr.exec(msg);
68
+                if (errStatusCapture && errStatusCapture.length === 2) {
69
+                    lastErrorStatus = parseInt(errStatusCapture[1]);
70
+                    logger.debug(
71
+                        "lastErrorStatus set to: " + lastErrorStatus);
72
+                }
25
                 break;
73
                 break;
26
             case Strophe.LogLevel.ERROR:
74
             case Strophe.LogLevel.ERROR:
27
             case Strophe.LogLevel.FATAL:
75
             case Strophe.LogLevel.FATAL:
30
                 logger.error(msg);
78
                 logger.error(msg);
31
                 break;
79
                 break;
32
         }
80
         }
81
+        /* eslint-enable no-case-declarations */
82
+    };
83
+
84
+    /**
85
+     * Returns error status (HTTP error code) of the last BOSH request.
86
+     *
87
+     * @return {number} HTTP error code, '0' for unknown or "god knows what"
88
+     * (this is a hack).
89
+     */
90
+    Strophe.getLastErrorStatus = function () {
91
+        return lastErrorStatus;
33
     };
92
     };
34
 
93
 
35
     Strophe.getStatusString = function (status) {
94
     Strophe.getStatusString = function (status) {

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

164
                 // more than 4 times. The connection is dropped without
164
                 // more than 4 times. The connection is dropped without
165
                 // supplying a reason(error message/event) through the API.
165
                 // supplying a reason(error message/event) through the API.
166
                 logger.error("XMPP connection dropped!");
166
                 logger.error("XMPP connection dropped!");
167
-                this.eventEmitter.emit(
168
-                    JitsiConnectionEvents.CONNECTION_FAILED,
169
-                    JitsiConnectionErrors.OTHER_ERROR,
170
-                    errMsg ? errMsg : 'connection-dropped-error');
167
+                // XXX if the last request error is within 5xx range it means it
168
+                // was a server failure
169
+                const lastErrorStatus = Strophe.getLastErrorStatus();
170
+                if (lastErrorStatus >= 500 && lastErrorStatus < 600) {
171
+                    this.eventEmitter.emit(
172
+                        JitsiConnectionEvents.CONNECTION_FAILED,
173
+                        JitsiConnectionErrors.SERVER_ERROR,
174
+                        errMsg ? errMsg : 'server-error');
175
+                } else {
176
+                    this.eventEmitter.emit(
177
+                        JitsiConnectionEvents.CONNECTION_FAILED,
178
+                        JitsiConnectionErrors.OTHER_ERROR,
179
+                        errMsg ? errMsg : 'connection-dropped-error');
180
+                }
171
             } else {
181
             } else {
172
                 this.eventEmitter.emit(
182
                 this.eventEmitter.emit(
173
                     JitsiConnectionEvents.CONNECTION_DISCONNECTED, errMsg);
183
                     JitsiConnectionEvents.CONNECTION_DISCONNECTED, errMsg);

正在加载...
取消
保存