|
@@ -9,76 +9,145 @@ var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
|
9
|
9
|
var RTCEvents = require("../../service/RTC/RTCEvents");
|
10
|
10
|
var UIEvents = require("../../service/UI/UIEvents");
|
11
|
11
|
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
|
12
|
+var retry = require('retry');
|
12
|
13
|
|
13
|
14
|
var eventEmitter = new EventEmitter();
|
14
|
15
|
var connection = null;
|
15
|
16
|
var authenticatedUser = false;
|
16
|
17
|
|
17
|
18
|
function connect(jid, password) {
|
18
|
|
- connection = XMPP.createConnection();
|
19
|
|
- Moderator.setConnection(connection);
|
20
|
19
|
|
21
|
|
- if (connection.disco) {
|
22
|
|
- // for chrome, add multistream cap
|
23
|
|
- }
|
24
|
|
- connection.jingle.pc_constraints = APP.RTC.getPCConstraints();
|
25
|
|
- if (config.useIPv6) {
|
26
|
|
- // https://code.google.com/p/webrtc/issues/detail?id=2828
|
27
|
|
- if (!connection.jingle.pc_constraints.optional)
|
28
|
|
- connection.jingle.pc_constraints.optional = [];
|
29
|
|
- connection.jingle.pc_constraints.optional.push({googIPv6: true});
|
30
|
|
- }
|
|
20
|
+ var faultTolerantConnect = retry.operation({
|
|
21
|
+ retries: 3
|
|
22
|
+ });
|
31
|
23
|
|
32
|
|
- // Include user info in MUC presence
|
33
|
|
- var settings = Settings.getSettings();
|
34
|
|
- if (settings.email) {
|
35
|
|
- connection.emuc.addEmailToPresence(settings.email);
|
36
|
|
- }
|
37
|
|
- if (settings.uid) {
|
38
|
|
- connection.emuc.addUserIdToPresence(settings.uid);
|
39
|
|
- }
|
40
|
|
- if (settings.displayName) {
|
41
|
|
- connection.emuc.addDisplayNameToPresence(settings.displayName);
|
42
|
|
- }
|
|
24
|
+ // fault tolerant connect
|
|
25
|
+ faultTolerantConnect.attempt(function () {
|
43
|
26
|
|
44
|
|
- var anonymousConnectionFailed = false;
|
45
|
|
- var wasConnected = false;
|
46
|
|
- var lastErrorMsg;
|
47
|
|
- connection.connect(jid, password, function (status, msg) {
|
48
|
|
- console.log('Strophe status changed to',
|
49
|
|
- Strophe.getStatusString(status), msg);
|
50
|
|
- if (status === Strophe.Status.CONNECTED) {
|
|
27
|
+ connection = XMPP.createConnection();
|
|
28
|
+ Moderator.setConnection(connection);
|
51
|
29
|
|
52
|
|
- wasConnected = true;
|
|
30
|
+ if (connection.disco) {
|
|
31
|
+ // for chrome, add multistream cap
|
|
32
|
+ }
|
|
33
|
+ connection.jingle.pc_constraints = APP.RTC.getPCConstraints();
|
|
34
|
+ if (config.useIPv6) {
|
|
35
|
+ // https://code.google.com/p/webrtc/issues/detail?id=2828
|
|
36
|
+ if (!connection.jingle.pc_constraints.optional)
|
|
37
|
+ connection.jingle.pc_constraints.optional = [];
|
|
38
|
+ connection.jingle.pc_constraints.optional.push({googIPv6: true});
|
|
39
|
+ }
|
53
|
40
|
|
54
|
|
- if (config.useStunTurn) {
|
55
|
|
- connection.jingle.getStunAndTurnCredentials();
|
56
|
|
- }
|
|
41
|
+ // Include user info in MUC presence
|
|
42
|
+ var settings = Settings.getSettings();
|
|
43
|
+ if (settings.email) {
|
|
44
|
+ connection.emuc.addEmailToPresence(settings.email);
|
|
45
|
+ }
|
|
46
|
+ if (settings.uid) {
|
|
47
|
+ connection.emuc.addUserIdToPresence(settings.uid);
|
|
48
|
+ }
|
|
49
|
+ if (settings.displayName) {
|
|
50
|
+ connection.emuc.addDisplayNameToPresence(settings.displayName);
|
|
51
|
+ }
|
57
|
52
|
|
58
|
|
- console.info("My Jabber ID: " + connection.jid);
|
59
|
53
|
|
60
|
|
- if (password)
|
61
|
|
- authenticatedUser = true;
|
62
|
|
- maybeDoJoin();
|
63
|
|
- } else if (status === Strophe.Status.CONNFAIL) {
|
64
|
|
- if (msg === 'x-strophe-bad-non-anon-jid') {
|
65
|
|
- anonymousConnectionFailed = true;
|
66
|
|
- }
|
67
|
|
- lastErrorMsg = msg;
|
68
|
|
- } else if (status === Strophe.Status.DISCONNECTED) {
|
69
|
|
- if (anonymousConnectionFailed) {
|
70
|
|
- // prompt user for username and password
|
|
54
|
+ // connection.connect() starts the connection process.
|
|
55
|
+ //
|
|
56
|
+ // As the connection process proceeds, the user supplied callback will
|
|
57
|
+ // be triggered multiple times with status updates. The callback should
|
|
58
|
+ // take two arguments - the status code and the error condition.
|
|
59
|
+ //
|
|
60
|
+ // The status code will be one of the values in the Strophe.Status
|
|
61
|
+ // constants. The error condition will be one of the conditions defined
|
|
62
|
+ // in RFC 3920 or the condition ‘strophe-parsererror’.
|
|
63
|
+ //
|
|
64
|
+ // The Parameters wait, hold and route are optional and only relevant
|
|
65
|
+ // for BOSH connections. Please see XEP 124 for a more detailed
|
|
66
|
+ // explanation of the optional parameters.
|
|
67
|
+ //
|
|
68
|
+ // Connection status constants for use by the connection handler
|
|
69
|
+ // callback.
|
|
70
|
+ //
|
|
71
|
+ // Status.ERROR - An error has occurred (websockets specific)
|
|
72
|
+ // Status.CONNECTING - The connection is currently being made
|
|
73
|
+ // Status.CONNFAIL - The connection attempt failed
|
|
74
|
+ // Status.AUTHENTICATING - The connection is authenticating
|
|
75
|
+ // Status.AUTHFAIL - The authentication attempt failed
|
|
76
|
+ // Status.CONNECTED - The connection has succeeded
|
|
77
|
+ // Status.DISCONNECTED - The connection has been terminated
|
|
78
|
+ // Status.DISCONNECTING - The connection is currently being terminated
|
|
79
|
+ // Status.ATTACHED - The connection has been attached
|
|
80
|
+
|
|
81
|
+ var anonymousConnectionFailed = false;
|
|
82
|
+ var connectionFailed = false;
|
|
83
|
+ var lastErrorMsg;
|
|
84
|
+ connection.connect(jid, password, function (status, msg) {
|
|
85
|
+ console.log('Strophe status changed to',
|
|
86
|
+ Strophe.getStatusString(status), msg);
|
|
87
|
+ if (status === Strophe.Status.CONNECTED) {
|
|
88
|
+ if (config.useStunTurn) {
|
|
89
|
+ connection.jingle.getStunAndTurnCredentials();
|
|
90
|
+ }
|
|
91
|
+
|
|
92
|
+ console.info("My Jabber ID: " + connection.jid);
|
|
93
|
+
|
|
94
|
+ if (password)
|
|
95
|
+ authenticatedUser = true;
|
|
96
|
+ maybeDoJoin();
|
|
97
|
+ } else if (status === Strophe.Status.CONNFAIL) {
|
|
98
|
+ if (msg === 'x-strophe-bad-non-anon-jid') {
|
|
99
|
+ anonymousConnectionFailed = true;
|
|
100
|
+ } else {
|
|
101
|
+ connectionFailed = true;
|
|
102
|
+ }
|
|
103
|
+ lastErrorMsg = msg;
|
|
104
|
+ } else if (status === Strophe.Status.DISCONNECTED) {
|
|
105
|
+ if (anonymousConnectionFailed) {
|
|
106
|
+ // prompt user for username and password
|
|
107
|
+ XMPP.promptLogin();
|
|
108
|
+ } else {
|
|
109
|
+
|
|
110
|
+ // Strophe already has built-in HTTP/BOSH error handling and
|
|
111
|
+ // request retry logic. Requests are resent automatically
|
|
112
|
+ // until their error count reaches 5. Strophe.js disconnects
|
|
113
|
+ // if the error count is > 5. We are not replicating this
|
|
114
|
+ // here.
|
|
115
|
+ //
|
|
116
|
+ // The "problem" is that failed HTTP/BOSH requests don't
|
|
117
|
+ // trigger a callback with a status update, so when a
|
|
118
|
+ // callback with status Strophe.Status.DISCONNECTED arrives,
|
|
119
|
+ // we can't be sure if it's a graceful disconnect or if it's
|
|
120
|
+ // triggered by some HTTP/BOSH error.
|
|
121
|
+ //
|
|
122
|
+ // But that's a minor issue in Jitsi Meet as we never
|
|
123
|
+ // disconnect anyway, not even when the user closes the
|
|
124
|
+ // browser window (which is kind of wrong, but the point is
|
|
125
|
+ // that we should never ever get disconnected).
|
|
126
|
+ //
|
|
127
|
+ // On the other hand, failed connections due to XMPP layer
|
|
128
|
+ // errors, trigger a callback with status Strophe.Status.CONNFAIL.
|
|
129
|
+ //
|
|
130
|
+ // Here we implement retry logic for failed connections due
|
|
131
|
+ // to XMPP layer errors and we display an error to the user
|
|
132
|
+ // if we get disconnected from the XMPP server permanently.
|
|
133
|
+
|
|
134
|
+ // If the connection failed, retry.
|
|
135
|
+ if (connectionFailed
|
|
136
|
+ && faultTolerantConnect.retry("connection-failed")) {
|
|
137
|
+ return;
|
|
138
|
+ }
|
|
139
|
+
|
|
140
|
+ // If we failed to connect to the XMPP server, fire an event
|
|
141
|
+ // to let all the interested module now about it.
|
|
142
|
+ eventEmitter.emit(XMPPEvents.CONNECTION_FAILED,
|
|
143
|
+ msg ? msg : lastErrorMsg);
|
|
144
|
+ }
|
|
145
|
+ } else if (status === Strophe.Status.AUTHFAIL) {
|
|
146
|
+ // wrong password or username, prompt user
|
71
|
147
|
XMPP.promptLogin();
|
72
|
|
- } else if (!wasConnected) {
|
73
|
|
- eventEmitter.emit(
|
74
|
|
- XMPPEvents.CONNECTION_FAILED,
|
75
|
|
- msg ? msg : lastErrorMsg);
|
76
|
|
- }
|
77
|
|
- } else if (status === Strophe.Status.AUTHFAIL) {
|
78
|
|
- // wrong password or username, prompt user
|
79
|
|
- XMPP.promptLogin();
|
80
|
148
|
|
81
|
|
- }
|
|
149
|
+ }
|
|
150
|
+ });
|
82
|
151
|
});
|
83
|
152
|
}
|
84
|
153
|
|