Преглед изворни кода

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,3 +14,8 @@ export const OTHER_ERROR = "connection.otherError";
14 14
  * Indicates that a password is required in order to join the conference.
15 15
  */
16 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,4 +1,4 @@
1
-/* global Strophe */
1
+/* global __filename, Strophe */
2 2
 /**
3 3
  * Strophe logger implementation. Logs from level WARN and above.
4 4
  */
@@ -6,6 +6,40 @@ import {getLogger} from "jitsi-meet-logger";
6 6
 const logger = getLogger(__filename);
7 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 43
 export default function () {
10 44
 
11 45
     Strophe.log = function (level, msg) {
@@ -14,14 +48,28 @@ export default function () {
14 48
         // Strophe log entry about secondary request timeout does not mean that
15 49
         // it's a final failure(the request will be restarted), so we lower it's
16 50
         // level here to a warning.
51
+        logger.trace("Strophe", level, msg);
17 52
         if (typeof msg === 'string' &&
18 53
                 msg.indexOf("Request ") !== -1 &&
19 54
                 msg.indexOf("timed out (secondary), restarting") !== -1) {
20 55
             level = Strophe.LogLevel.WARN;
21 56
         }
57
+        /* eslint-disable no-case-declarations */
22 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 65
             case Strophe.LogLevel.WARN:
24 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 73
                 break;
26 74
             case Strophe.LogLevel.ERROR:
27 75
             case Strophe.LogLevel.FATAL:
@@ -30,6 +78,17 @@ export default function () {
30 78
                 logger.error(msg);
31 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 94
     Strophe.getStatusString = function (status) {

+ 14
- 4
modules/xmpp/xmpp.js Прегледај датотеку

@@ -164,10 +164,20 @@ export default class XMPP {
164 164
                 // more than 4 times. The connection is dropped without
165 165
                 // supplying a reason(error message/event) through the API.
166 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 181
             } else {
172 182
                 this.eventEmitter.emit(
173 183
                     JitsiConnectionEvents.CONNECTION_DISCONNECTED, errMsg);

Loading…
Откажи
Сачувај