quickblox 2.23.0-beta.2 → 2.23.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/quickblox.js +175 -14
- package/quickblox.min.js +1 -1
- package/src/modules/chat/qbChat.js +173 -12
- package/src/qbConfig.js +2 -2
package/package.json
CHANGED
package/quickblox.js
CHANGED
|
@@ -30597,6 +30597,19 @@ function ChatProxy(service) {
|
|
|
30597
30597
|
this._checkExpiredSessionTimer = undefined;
|
|
30598
30598
|
this._sessionHasExpired = false;
|
|
30599
30599
|
this._pings = {};
|
|
30600
|
+
|
|
30601
|
+
// [QC-1550] XMPP connection is considered "verified" only after the first
|
|
30602
|
+
// successful pong response. Strophe emits Status.CONNECTED at the transport
|
|
30603
|
+
// layer (TCP/WebSocket handshake completed) before XMPP-level traffic is
|
|
30604
|
+
// actually flowing — this creates a race window where the application thinks
|
|
30605
|
+
// chat is alive but pings can still time out. Gates onReconnectListener and
|
|
30606
|
+
// onDisconnectedListener to avoid firing them based on an unverified state.
|
|
30607
|
+
this._isConnectionVerified = false;
|
|
30608
|
+
// [QC-1550] On reconnect, onReconnectListener is deferred until the first
|
|
30609
|
+
// successful pong. This flag marks that a reconnect is awaiting verification:
|
|
30610
|
+
// the ping success callback reads it to decide whether to fire the deferred
|
|
30611
|
+
// listener. Reset on listener fire, on ping failure, and on logout.
|
|
30612
|
+
this._isReconnectListenerPending = false;
|
|
30600
30613
|
//
|
|
30601
30614
|
this.helpers = new Helpers();
|
|
30602
30615
|
//
|
|
@@ -31400,12 +31413,35 @@ ChatProxy.prototype = {
|
|
|
31400
31413
|
' error: ', error);
|
|
31401
31414
|
self._chatPingFailedCounter += 1;
|
|
31402
31415
|
if (self._chatPingFailedCounter >= config.chatPingMissLimit) {
|
|
31403
|
-
|
|
31416
|
+
// [QC-1550] onDisconnectedListener should only fire when the
|
|
31417
|
+
// previous connection was actually verified. If the ping miss
|
|
31418
|
+
// limit is reached while we were still waiting for the first
|
|
31419
|
+
// pong after reconnect (verification never succeeded), the
|
|
31420
|
+
// application was never told the chat was "alive" — so we
|
|
31421
|
+
// don't fire a misleading "disconnected" event for a state
|
|
31422
|
+
// the consumer never observed.
|
|
31423
|
+
if (self.isConnected && self._isConnectionVerified &&
|
|
31424
|
+
typeof self.onDisconnectedListener === 'function') {
|
|
31404
31425
|
Utils.safeCallbackCall(self.onDisconnectedListener);
|
|
31405
31426
|
}
|
|
31427
|
+
// [QC-1550] Reset verification state and clear any pending
|
|
31428
|
+
// reconnect listener — the connection has failed; the next
|
|
31429
|
+
// CONNECTED + pong cycle will rebuild verification from
|
|
31430
|
+
// scratch.
|
|
31431
|
+
self._isConnectionVerified = false;
|
|
31432
|
+
self._isReconnectListenerPending = false;
|
|
31406
31433
|
self.isConnected = false;
|
|
31407
31434
|
self._isConnecting = false;
|
|
31408
31435
|
self._chatPingFailedCounter = 0;
|
|
31436
|
+
// [QC-1550] Stop this ping interval — it belongs to the dead
|
|
31437
|
+
// connection. Without this, the timer keeps firing pings on
|
|
31438
|
+
// the old XMPP session and racing with the new connection's
|
|
31439
|
+
// ping cycle, which produced spurious pong success/failure
|
|
31440
|
+
// interleaving in the field logs.
|
|
31441
|
+
if (self._checkConnectionPingTimer !== undefined) {
|
|
31442
|
+
clearInterval(self._checkConnectionPingTimer);
|
|
31443
|
+
self._checkConnectionPingTimer = undefined;
|
|
31444
|
+
}
|
|
31409
31445
|
self._establishConnection(params,'CONNECTED have SDK ping failed');
|
|
31410
31446
|
}
|
|
31411
31447
|
} else {
|
|
@@ -31414,6 +31450,32 @@ ChatProxy.prototype = {
|
|
|
31414
31450
|
'ok, at ', Utils.getCurrentTime(),
|
|
31415
31451
|
'_chatPingFailedCounter: ', self._chatPingFailedCounter);
|
|
31416
31452
|
self._chatPingFailedCounter = 0;
|
|
31453
|
+
|
|
31454
|
+
// [QC-1550] First pong after reconnect verifies XMPP is live.
|
|
31455
|
+
// Fire the deferred onReconnectListener now (was postponed in
|
|
31456
|
+
// _postConnectActions). Skip if logout was triggered between
|
|
31457
|
+
// CONNECTED and pong — listener fire would leak past logout.
|
|
31458
|
+
if (self._isReconnectListenerPending && !self._isLogout) {
|
|
31459
|
+
self._isConnectionVerified = true;
|
|
31460
|
+
self._isReconnectListenerPending = false;
|
|
31461
|
+
Utils.QBLog('[QBChat]',
|
|
31462
|
+
'[QC-1550] First pong success, firing deferred onReconnectListener at ',
|
|
31463
|
+
Utils.getCurrentTime());
|
|
31464
|
+
if (typeof self.onLogListener === 'function') {
|
|
31465
|
+
Utils.safeCallbackCall(self.onLogListener,
|
|
31466
|
+
'[QBChat] [QC-1550] First pong success, firing deferred onReconnectListener at ' +
|
|
31467
|
+
chatUtils.getLocalTime());
|
|
31468
|
+
}
|
|
31469
|
+
if (typeof self.onReconnectListener === 'function') {
|
|
31470
|
+
Utils.safeCallbackCall(self.onReconnectListener);
|
|
31471
|
+
}
|
|
31472
|
+
} else if (!self._isConnectionVerified && !self._isLogout) {
|
|
31473
|
+
// Edge case: pong succeeded but pending flag was cleared
|
|
31474
|
+
// (e.g. by ping failure path racing with this success).
|
|
31475
|
+
// Mark verified anyway so onDisconnectedListener gating
|
|
31476
|
+
// in SDK-4 works correctly going forward.
|
|
31477
|
+
self._isConnectionVerified = true;
|
|
31478
|
+
}
|
|
31417
31479
|
}
|
|
31418
31480
|
});
|
|
31419
31481
|
} catch (err) {
|
|
@@ -31468,11 +31530,30 @@ ChatProxy.prototype = {
|
|
|
31468
31530
|
'[QBChat]' + '[SDK v'+config.version+']' +' Status.DISCONNECTED at ' +
|
|
31469
31531
|
chatUtils.getLocalTime()+ ' DISCONNECTED CONDITION: ' + condition);
|
|
31470
31532
|
}
|
|
31471
|
-
// fire 'onDisconnectedListener' only once
|
|
31472
|
-
|
|
31533
|
+
// [QC-1550] fire 'onDisconnectedListener' only once AND only when the
|
|
31534
|
+
// previous connection was actually verified (first pong succeeded).
|
|
31535
|
+
// See onDisconnectedListener gating in SDK-4 for full reasoning — this
|
|
31536
|
+
// is the same rule applied to transport-level disconnects.
|
|
31537
|
+
if (self.isConnected && self._isConnectionVerified &&
|
|
31538
|
+
typeof self.onDisconnectedListener === 'function') {
|
|
31473
31539
|
Utils.safeCallbackCall(self.onDisconnectedListener);
|
|
31474
31540
|
}
|
|
31475
31541
|
|
|
31542
|
+
// [QC-1550] Reset verification state. The next CONNECTED + pong cycle
|
|
31543
|
+
// will rebuild it. Pending reconnect listener (if any) is cancelled —
|
|
31544
|
+
// the new cycle will set a fresh one in _postConnectActions.
|
|
31545
|
+
self._isConnectionVerified = false;
|
|
31546
|
+
self._isReconnectListenerPending = false;
|
|
31547
|
+
|
|
31548
|
+
// [QC-1550] Stop ping timer of the dead connection. Without this, the
|
|
31549
|
+
// interval keeps invoking self.pingchat() on a stale Strophe connection
|
|
31550
|
+
// until the new CONNECTED arrives, producing spurious failure logs and
|
|
31551
|
+
// racing with the new connection's freshly-started ping cycle.
|
|
31552
|
+
if (self._checkConnectionPingTimer !== undefined) {
|
|
31553
|
+
clearInterval(self._checkConnectionPingTimer);
|
|
31554
|
+
self._checkConnectionPingTimer = undefined;
|
|
31555
|
+
}
|
|
31556
|
+
|
|
31476
31557
|
self.isConnected = false;
|
|
31477
31558
|
self._isConnecting = false;
|
|
31478
31559
|
self.connection.reset();
|
|
@@ -31630,8 +31711,21 @@ ChatProxy.prototype = {
|
|
|
31630
31711
|
* - save user's JID;
|
|
31631
31712
|
* - enable carbons;
|
|
31632
31713
|
* - get and storage the user's roster (if the initial connect);
|
|
31633
|
-
* - recover the joined rooms and
|
|
31714
|
+
* - recover the joined rooms and defer 'onReconnectListener' until the first
|
|
31715
|
+
* pong confirms XMPP-level traffic (if the reconnect);
|
|
31634
31716
|
* - send initial presence to the chat server.
|
|
31717
|
+
*
|
|
31718
|
+
* [QC-1550] On reconnect, Strophe emits Status.CONNECTED as soon as the
|
|
31719
|
+
* transport handshake completes (WebSocket/BOSH), but the XMPP layer may not
|
|
31720
|
+
* yet be processing traffic — pings can still time out for several seconds.
|
|
31721
|
+
* Firing onReconnectListener at this moment leads consumers (e.g. UI overlays)
|
|
31722
|
+
* to believe chat is fully restored, then a subsequent ping miss triggers a
|
|
31723
|
+
* false "Lost connection" state. The fix defers the listener until the first
|
|
31724
|
+
* pong succeeds (see ping success branch in Strophe.Status.CONNECTED handler).
|
|
31725
|
+
*
|
|
31726
|
+
* Fallback: when ping is disabled (config.pingLocalhostTimeInterval === 0)
|
|
31727
|
+
* there is no pong to wait for, so we fire onReconnectListener immediately
|
|
31728
|
+
* to preserve backward compatibility for consumers who opted out of pings.
|
|
31635
31729
|
*/
|
|
31636
31730
|
_postConnectActions: function (callback, isInitialConnect) {
|
|
31637
31731
|
Utils.QBLog('[QBChat]', 'Status.CONNECTED at ' + chatUtils.getLocalTime());
|
|
@@ -31657,6 +31751,13 @@ ChatProxy.prototype = {
|
|
|
31657
31751
|
self._enableCarbons();
|
|
31658
31752
|
|
|
31659
31753
|
if (isInitialConnect) {
|
|
31754
|
+
// [QC-1550] Initial connect: no reconnect overlay race possible
|
|
31755
|
+
// (user just logged in), so we mark the connection as verified
|
|
31756
|
+
// immediately. This also enables onDisconnectedListener gating in
|
|
31757
|
+
// the DISCONNECTED handler from this point on.
|
|
31758
|
+
self._isConnectionVerified = true;
|
|
31759
|
+
self._isReconnectListenerPending = false;
|
|
31760
|
+
|
|
31660
31761
|
self.roster.get(function (contacts) {
|
|
31661
31762
|
xmppClient.send(presence);
|
|
31662
31763
|
|
|
@@ -31691,8 +31792,30 @@ ChatProxy.prototype = {
|
|
|
31691
31792
|
Utils.QBLog('[QBChat]', '[MUC_REJOIN] All ' + rooms.length +
|
|
31692
31793
|
' join presences sent. Awaiting server confirmations...');
|
|
31693
31794
|
|
|
31694
|
-
|
|
31695
|
-
|
|
31795
|
+
// [QC-1550] Defer onReconnectListener until first successful pong.
|
|
31796
|
+
// The ping success callback (in Strophe.Status.CONNECTED handler)
|
|
31797
|
+
// reads _isReconnectListenerPending and fires the listener once XMPP
|
|
31798
|
+
// is verified. Connection remains unverified until that point.
|
|
31799
|
+
self._isConnectionVerified = false;
|
|
31800
|
+
|
|
31801
|
+
if (config.pingLocalhostTimeInterval === 0) {
|
|
31802
|
+
// Ping disabled — no pong to wait for; preserve legacy behavior.
|
|
31803
|
+
Utils.QBLog('[QBChat]',
|
|
31804
|
+
'[QC-1550] pingLocalhostTimeInterval=0, firing onReconnectListener immediately (ping disabled)');
|
|
31805
|
+
self._isConnectionVerified = true;
|
|
31806
|
+
self._isReconnectListenerPending = false;
|
|
31807
|
+
if (typeof self.onReconnectListener === 'function') {
|
|
31808
|
+
Utils.safeCallbackCall(self.onReconnectListener);
|
|
31809
|
+
}
|
|
31810
|
+
} else {
|
|
31811
|
+
self._isReconnectListenerPending = true;
|
|
31812
|
+
Utils.QBLog('[QBChat]',
|
|
31813
|
+
'[QC-1550] onReconnectListener deferred until first pong success');
|
|
31814
|
+
if (typeof self.onLogListener === 'function') {
|
|
31815
|
+
Utils.safeCallbackCall(self.onLogListener,
|
|
31816
|
+
'[QBChat] [QC-1550] onReconnectListener deferred at ' +
|
|
31817
|
+
chatUtils.getLocalTime() + ' — awaiting first pong');
|
|
31818
|
+
}
|
|
31696
31819
|
}
|
|
31697
31820
|
}
|
|
31698
31821
|
},
|
|
@@ -31741,7 +31864,9 @@ ChatProxy.prototype = {
|
|
|
31741
31864
|
' _isLogout=' + self._isLogout +
|
|
31742
31865
|
' timerExists=' + Boolean(self._checkConnectionTimer) +
|
|
31743
31866
|
' _isConnecting=' + self._isConnecting +
|
|
31744
|
-
' isConnected=' + self.isConnected
|
|
31867
|
+
' isConnected=' + self.isConnected +
|
|
31868
|
+
' verified=' + self._isConnectionVerified +
|
|
31869
|
+
' pending=' + self._isReconnectListenerPending);
|
|
31745
31870
|
if (typeof self.onLogListener === 'function') {
|
|
31746
31871
|
Utils.safeCallbackCall(self.onLogListener,
|
|
31747
31872
|
'[QBChat] [RECONNECT] _establishConnection called at ' +
|
|
@@ -31749,7 +31874,9 @@ ChatProxy.prototype = {
|
|
|
31749
31874
|
' _isLogout=' + self._isLogout +
|
|
31750
31875
|
' timerExists=' + Boolean(self._checkConnectionTimer) +
|
|
31751
31876
|
' _isConnecting=' + self._isConnecting +
|
|
31752
|
-
' isConnected=' + self.isConnected
|
|
31877
|
+
' isConnected=' + self.isConnected +
|
|
31878
|
+
' verified=' + self._isConnectionVerified +
|
|
31879
|
+
' pending=' + self._isReconnectListenerPending);
|
|
31753
31880
|
}
|
|
31754
31881
|
if (self._isLogout || self._checkConnectionTimer) {
|
|
31755
31882
|
Utils.QBLog('[QBChat]', '[RECONNECT] _establishConnection SKIPPED at ' +
|
|
@@ -31768,13 +31895,17 @@ ChatProxy.prototype = {
|
|
|
31768
31895
|
Utils.QBLog('[QBChat]', '[RECONNECT] _connect() at ' + chatUtils.getLocalTime() +
|
|
31769
31896
|
' isConnected=' + self.isConnected +
|
|
31770
31897
|
' _isConnecting=' + self._isConnecting +
|
|
31771
|
-
' _sessionHasExpired=' + self._sessionHasExpired
|
|
31898
|
+
' _sessionHasExpired=' + self._sessionHasExpired +
|
|
31899
|
+
' verified=' + self._isConnectionVerified +
|
|
31900
|
+
' pending=' + self._isReconnectListenerPending);
|
|
31772
31901
|
if (typeof self.onLogListener === 'function') {
|
|
31773
31902
|
Utils.safeCallbackCall(self.onLogListener,
|
|
31774
31903
|
'[QBChat] [RECONNECT] _connect() at ' + chatUtils.getLocalTime() +
|
|
31775
31904
|
' isConnected=' + self.isConnected +
|
|
31776
31905
|
' _isConnecting=' + self._isConnecting +
|
|
31777
|
-
' _sessionHasExpired=' + self._sessionHasExpired
|
|
31906
|
+
' _sessionHasExpired=' + self._sessionHasExpired +
|
|
31907
|
+
' verified=' + self._isConnectionVerified +
|
|
31908
|
+
' pending=' + self._isReconnectListenerPending);
|
|
31778
31909
|
}
|
|
31779
31910
|
if (!self.isConnected && !self._isConnecting && !self._sessionHasExpired) {
|
|
31780
31911
|
Utils.QBLog('[QBChat]', '[RECONNECT] executing connect() at ' + chatUtils.getLocalTime());
|
|
@@ -31788,16 +31919,24 @@ ChatProxy.prototype = {
|
|
|
31788
31919
|
// Stop retry timer only when actually connected or session expired (no point retrying).
|
|
31789
31920
|
// Do NOT stop timer when _isConnecting — the in-flight attempt may fail,
|
|
31790
31921
|
// and we need the timer to keep ticking for the next retry.
|
|
31922
|
+
// [QC-1550] Note: timer is stopped on isConnected, BUT verification
|
|
31923
|
+
// (_isConnectionVerified) may still be pending — the first pong has
|
|
31924
|
+
// not yet arrived. The retry loop terminates here; from this point
|
|
31925
|
+
// it is the ping interval that drives verification.
|
|
31791
31926
|
Utils.QBLog('[QBChat]', '[RECONNECT] timer stopped at ' + chatUtils.getLocalTime() +
|
|
31792
31927
|
' — isConnected=' + self.isConnected +
|
|
31793
|
-
' _sessionHasExpired=' + self._sessionHasExpired
|
|
31928
|
+
' _sessionHasExpired=' + self._sessionHasExpired +
|
|
31929
|
+
' verified=' + self._isConnectionVerified +
|
|
31930
|
+
' pending=' + self._isReconnectListenerPending);
|
|
31794
31931
|
clearInterval(self._checkConnectionTimer);
|
|
31795
31932
|
self._checkConnectionTimer = undefined;
|
|
31796
31933
|
if (typeof self.onLogListener === 'function') {
|
|
31797
31934
|
Utils.safeCallbackCall(self.onLogListener,
|
|
31798
31935
|
'[QBChat] [RECONNECT] timer stopped at ' + chatUtils.getLocalTime() +
|
|
31799
31936
|
' — isConnected=' + self.isConnected +
|
|
31800
|
-
' _sessionHasExpired=' + self._sessionHasExpired
|
|
31937
|
+
' _sessionHasExpired=' + self._sessionHasExpired +
|
|
31938
|
+
' verified=' + self._isConnectionVerified +
|
|
31939
|
+
' pending=' + self._isReconnectListenerPending);
|
|
31801
31940
|
}
|
|
31802
31941
|
} else {
|
|
31803
31942
|
// _isConnecting === true — another attempt is in flight, skip this tick
|
|
@@ -31834,6 +31973,21 @@ ChatProxy.prototype = {
|
|
|
31834
31973
|
}
|
|
31835
31974
|
clearInterval(this._checkConnectionTimer);
|
|
31836
31975
|
this._checkConnectionTimer = undefined;
|
|
31976
|
+
// [QC-1550] Stop ping timer of the previous connection. Without this,
|
|
31977
|
+
// the interval continues to invoke pingchat() on a stale Strophe
|
|
31978
|
+
// connection across the reconnect cycle, racing with the new
|
|
31979
|
+
// connection's freshly-started ping cycle once Status.CONNECTED arrives.
|
|
31980
|
+
if (this._checkConnectionPingTimer !== undefined) {
|
|
31981
|
+
clearInterval(this._checkConnectionPingTimer);
|
|
31982
|
+
this._checkConnectionPingTimer = undefined;
|
|
31983
|
+
}
|
|
31984
|
+
// [QC-1550] Reset XMPP verification state — the new CONNECTED + pong
|
|
31985
|
+
// cycle from _postConnectActions will rebuild it. Without this reset, a
|
|
31986
|
+
// stale _isConnectionVerified=true from the previous session would let
|
|
31987
|
+
// onDisconnectedListener fire on the next ping miss before the new
|
|
31988
|
+
// connection had a chance to verify itself.
|
|
31989
|
+
this._isConnectionVerified = false;
|
|
31990
|
+
this._isReconnectListenerPending = false;
|
|
31837
31991
|
this.muc.joinedRooms = {};
|
|
31838
31992
|
this.helpers.setUserCurrentJid('');
|
|
31839
31993
|
|
|
@@ -32227,6 +32381,13 @@ ChatProxy.prototype = {
|
|
|
32227
32381
|
this._checkConnectionTimer = undefined;
|
|
32228
32382
|
this._checkExpiredSessionTimer = undefined;
|
|
32229
32383
|
this.muc.joinedRooms = {};
|
|
32384
|
+
// [QC-1550] Reset XMPP verification state on explicit disconnect so the
|
|
32385
|
+
// next connect() starts from a clean slate. _isLogout guard below also
|
|
32386
|
+
// prevents firing of deferred listeners if a pong arrives in flight,
|
|
32387
|
+
// but resetting here keeps state consistent for consumers that call
|
|
32388
|
+
// disconnect() + connect() in sequence.
|
|
32389
|
+
this._isConnectionVerified = false;
|
|
32390
|
+
this._isReconnectListenerPending = false;
|
|
32230
32391
|
this._isLogout = true;
|
|
32231
32392
|
this.helpers.setUserCurrentJid('');
|
|
32232
32393
|
|
|
@@ -39541,8 +39702,8 @@ module.exports = StreamManagement;
|
|
|
39541
39702
|
*/
|
|
39542
39703
|
|
|
39543
39704
|
var config = {
|
|
39544
|
-
version: '2.23.
|
|
39545
|
-
buildNumber: '
|
|
39705
|
+
version: '2.23.1-beta.3',
|
|
39706
|
+
buildNumber: '1179',
|
|
39546
39707
|
creds: {
|
|
39547
39708
|
'appId': 0,
|
|
39548
39709
|
'authKey': '',
|