@mtcute/core 0.30.0 → 0.30.2
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/client.cjs +8 -0
- package/client.js +8 -0
- package/highlevel/client.d.cts +63 -1
- package/highlevel/client.d.ts +63 -1
- package/highlevel/methods/files/download-iterable.cjs +80 -45
- package/highlevel/methods/files/download-iterable.js +80 -45
- package/highlevel/methods/files/normalize-input-media.cjs +9 -1
- package/highlevel/methods/files/normalize-input-media.js +10 -2
- package/highlevel/methods/files/upload-file.cjs +6 -1
- package/highlevel/methods/files/upload-file.js +6 -1
- package/highlevel/methods/messages/create-rich-streaming-draft.cjs +39 -0
- package/highlevel/methods/messages/create-rich-streaming-draft.d.cts +42 -0
- package/highlevel/methods/messages/create-rich-streaming-draft.d.ts +42 -0
- package/highlevel/methods/messages/create-rich-streaming-draft.js +34 -0
- package/highlevel/methods/messages/normalize-rich-message.cjs +168 -0
- package/highlevel/methods/messages/normalize-rich-message.d.cts +10 -0
- package/highlevel/methods/messages/normalize-rich-message.d.ts +10 -0
- package/highlevel/methods/messages/normalize-rich-message.js +163 -0
- package/highlevel/methods/messages/send-common.cjs +3 -2
- package/highlevel/methods/messages/send-common.d.cts +4 -1
- package/highlevel/methods/messages/send-common.d.ts +4 -1
- package/highlevel/methods/messages/send-common.js +3 -2
- package/highlevel/methods/messages/send-rich-message.cjs +49 -0
- package/highlevel/methods/messages/send-rich-message.d.cts +38 -0
- package/highlevel/methods/messages/send-rich-message.d.ts +38 -0
- package/highlevel/methods/messages/send-rich-message.js +44 -0
- package/highlevel/methods.d.cts +3 -0
- package/highlevel/methods.d.ts +3 -0
- package/highlevel/types/bots/inline-message/factories.cjs +14 -0
- package/highlevel/types/bots/inline-message/factories.d.cts +9 -1
- package/highlevel/types/bots/inline-message/factories.d.ts +9 -1
- package/highlevel/types/bots/inline-message/factories.js +14 -0
- package/highlevel/types/bots/inline-message/types.d.cts +17 -1
- package/highlevel/types/bots/inline-message/types.d.ts +17 -1
- package/highlevel/types/files/utils.d.cts +9 -0
- package/highlevel/types/files/utils.d.ts +9 -0
- package/highlevel/types/media/input-media/types.d.cts +1 -1
- package/highlevel/types/media/input-media/types.d.ts +1 -1
- package/highlevel/types/messages/index.d.cts +1 -1
- package/highlevel/types/messages/index.d.ts +1 -1
- package/highlevel/types/messages/message.cjs +1 -1
- package/highlevel/types/messages/message.d.cts +1 -1
- package/highlevel/types/messages/message.d.ts +1 -1
- package/highlevel/types/messages/message.js +1 -1
- package/highlevel/types/messages/rich/index.d.cts +4 -0
- package/highlevel/types/messages/rich/index.d.ts +4 -0
- package/highlevel/types/messages/rich/inner.cjs +219 -0
- package/highlevel/types/messages/rich/inner.d.cts +127 -0
- package/highlevel/types/messages/rich/inner.d.ts +127 -0
- package/highlevel/types/messages/rich/inner.js +214 -0
- package/highlevel/types/messages/{rich-message.cjs → rich/rich-message.cjs} +6 -6
- package/highlevel/types/messages/{rich-message.d.cts → rich/rich-message.d.cts} +5 -5
- package/highlevel/types/messages/{rich-message.d.ts → rich/rich-message.d.ts} +5 -5
- package/highlevel/types/messages/{rich-message.js → rich/rich-message.js} +6 -6
- package/highlevel/types/messages/rich/types.d.cts +76 -0
- package/highlevel/types/messages/rich/types.d.ts +76 -0
- package/highlevel/updates/manager.cjs +10 -169
- package/highlevel/updates/manager.js +10 -169
- package/highlevel/utils/entities.cjs +176 -0
- package/highlevel/utils/entities.d.cts +18 -0
- package/highlevel/utils/entities.d.ts +18 -0
- package/highlevel/utils/entities.js +177 -1
- package/highlevel/utils/index.d.cts +1 -0
- package/highlevel/utils/index.d.ts +1 -0
- package/highlevel/utils/walk-page-blocks.cjs +164 -0
- package/highlevel/utils/walk-page-blocks.d.cts +9 -0
- package/highlevel/utils/walk-page-blocks.d.ts +9 -0
- package/highlevel/utils/walk-page-blocks.js +159 -0
- package/index.cjs +3 -1
- package/index.js +3 -1
- package/methods.cjs +4 -0
- package/methods.js +4 -0
- package/network/authorization.cjs +1 -1
- package/network/authorization.js +1 -1
- package/network/delay-gate.cjs +29 -0
- package/network/delay-gate.d.cts +5 -0
- package/network/delay-gate.d.ts +5 -0
- package/network/delay-gate.js +24 -0
- package/network/delay-gate.test.d.cts +1 -0
- package/network/delay-gate.test.d.ts +1 -0
- package/network/message-id-store.cjs +30 -0
- package/network/message-id-store.d.cts +7 -0
- package/network/message-id-store.d.ts +7 -0
- package/network/message-id-store.js +25 -0
- package/network/message-id-store.test.d.cts +1 -0
- package/network/message-id-store.test.d.ts +1 -0
- package/network/middlewares/bundle.cjs +2 -0
- package/network/middlewares/bundle.d.cts +1 -0
- package/network/middlewares/bundle.d.ts +1 -0
- package/network/middlewares/bundle.js +2 -0
- package/network/middlewares/default.cjs +6 -1
- package/network/middlewares/default.js +6 -1
- package/network/middlewares/flood-waiter.test.d.cts +1 -0
- package/network/middlewares/flood-waiter.test.d.ts +1 -0
- package/network/middlewares/internal-errors.test.d.cts +1 -0
- package/network/middlewares/internal-errors.test.d.ts +1 -0
- package/network/middlewares/media-throttle.cjs +65 -0
- package/network/middlewares/media-throttle.d.cts +5 -0
- package/network/middlewares/media-throttle.d.ts +5 -0
- package/network/middlewares/media-throttle.js +60 -0
- package/network/middlewares/media-throttle.test.d.cts +1 -0
- package/network/middlewares/media-throttle.test.d.ts +1 -0
- package/network/middlewares/on-error.test.d.cts +1 -0
- package/network/middlewares/on-error.test.d.ts +1 -0
- package/network/middlewares/on-method.test.d.cts +1 -0
- package/network/middlewares/on-method.test.d.ts +1 -0
- package/network/mtproto-session.cjs +9 -2
- package/network/mtproto-session.d.cts +5 -2
- package/network/mtproto-session.d.ts +5 -2
- package/network/mtproto-session.js +9 -2
- package/network/mtproxy/_fake-tls.cjs +169 -107
- package/network/mtproxy/_fake-tls.js +169 -107
- package/network/mtproxy/_fake-tls.test.d.cts +1 -0
- package/network/mtproxy/_fake-tls.test.d.ts +1 -0
- package/network/multi-session-connection.cjs +7 -0
- package/network/multi-session-connection.d.cts +2 -0
- package/network/multi-session-connection.d.ts +2 -0
- package/network/multi-session-connection.js +7 -0
- package/network/network-manager.cjs +7 -1
- package/network/network-manager.js +7 -1
- package/network/resource-limiter.cjs +60 -0
- package/network/resource-limiter.d.cts +11 -0
- package/network/resource-limiter.d.ts +11 -0
- package/network/resource-limiter.js +55 -0
- package/network/resource-limiter.test.d.cts +1 -0
- package/network/resource-limiter.test.d.ts +1 -0
- package/network/server-salt.cjs +7 -3
- package/network/server-salt.d.cts +2 -0
- package/network/server-salt.d.ts +2 -0
- package/network/server-salt.js +7 -3
- package/network/session-connection.cjs +106 -20
- package/network/session-connection.d.cts +11 -0
- package/network/session-connection.d.ts +11 -0
- package/network/session-connection.js +106 -20
- package/package.json +1 -1
- package/tl/api-schema.json +1 -1
- package/tl/binary/reader.cjs +115 -109
- package/tl/binary/reader.js +115 -109
- package/tl/binary/writer.cjs +243 -245
- package/tl/binary/writer.js +243 -245
- package/tl/index.d.cts +227 -216
- package/tl/index.d.ts +227 -216
- package/tl/inner-tl.cjs +3 -1
- package/tl/inner-tl.js +3 -1
- package/types/utils.d.cts +4 -0
- package/types/utils.d.ts +4 -0
- package/utils.cjs +4 -0
- package/utils.js +5 -1
|
@@ -11,6 +11,7 @@ const Long = require("long");
|
|
|
11
11
|
const mtproto = require("../utils/crypto/mtproto.cjs");
|
|
12
12
|
const earlyTimer = require("../utils/early-timer.cjs");
|
|
13
13
|
const longUtils = require("../utils/long-utils.cjs");
|
|
14
|
+
const miscUtils = require("../utils/misc-utils.cjs");
|
|
14
15
|
const authorization = require("./authorization.cjs");
|
|
15
16
|
const mtprotoSession = require("./mtproto-session.cjs");
|
|
16
17
|
const persistentConnection = require("./persistent-connection.cjs");
|
|
@@ -18,6 +19,8 @@ const abstract = require("./transports/abstract.cjs");
|
|
|
18
19
|
const errors = require("../types/errors.cjs");
|
|
19
20
|
const innerTl = require("../tl/inner-tl.cjs");
|
|
20
21
|
const TEMP_AUTH_KEY_EXPIRY = 86400;
|
|
22
|
+
const TEMP_AUTH_KEY_REFRESH_MARGIN = 3600;
|
|
23
|
+
const TEMP_AUTH_KEY_REFRESH_JITTER = 600;
|
|
21
24
|
const GET_STATE_INTERVAL = 1500;
|
|
22
25
|
const GET_STATE_TIMEOUT = 2500;
|
|
23
26
|
const GZIP_PACKED_ID = 812830625;
|
|
@@ -29,6 +32,8 @@ const INVOKE_AFTER_MSG_SIZE = 12;
|
|
|
29
32
|
class SessionConnection extends persistentConnection.PersistentConnection {
|
|
30
33
|
_flushTimer = new earlyTimer.EarlyTimer();
|
|
31
34
|
_queuedDestroySession = [];
|
|
35
|
+
_needDestroyAuthKey = false;
|
|
36
|
+
_sentDestroyAuthKey = false;
|
|
32
37
|
// waitForMessage
|
|
33
38
|
_pendingWaitForUnencrypted = [];
|
|
34
39
|
_usePfs;
|
|
@@ -41,9 +46,8 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
41
46
|
_crypto;
|
|
42
47
|
_salts;
|
|
43
48
|
_session;
|
|
44
|
-
// todo: we should probably do adaptive ping interval based on rtt like tdlib:
|
|
45
|
-
// https://github.com/tdlib/td/blob/91aa6c9e4d0774eabf4f8d7f3aa51239032059a6/td/mtproto/SessionConnection.h
|
|
46
49
|
_pingInterval;
|
|
50
|
+
_randomDelay = miscUtils.getRandomInt(5e3);
|
|
47
51
|
// NB: dont forget to update .reset()
|
|
48
52
|
onDisconnect = new utils.Emitter();
|
|
49
53
|
onKeyChange = new utils.Emitter();
|
|
@@ -73,6 +77,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
73
77
|
this._online = params.platform.isOnline?.() ?? true;
|
|
74
78
|
}
|
|
75
79
|
_online;
|
|
80
|
+
_active = false;
|
|
76
81
|
getAuthKey(temp = false) {
|
|
77
82
|
const key = temp ? this._session._authKeyTemp : this._session._authKey;
|
|
78
83
|
if (!key.ready) return null;
|
|
@@ -98,6 +103,9 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
98
103
|
for (const msgId of this._session.pendingGetStateTimeouts.keys()) {
|
|
99
104
|
this._onMessageFailed(msgId, "connection loss", true);
|
|
100
105
|
}
|
|
106
|
+
for (const rpc of this._session.getStateSchedule.raw) {
|
|
107
|
+
rpc.getState = 0;
|
|
108
|
+
}
|
|
101
109
|
this.onDisconnect.emit();
|
|
102
110
|
this.reset();
|
|
103
111
|
}
|
|
@@ -105,6 +113,12 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
105
113
|
await super.destroy();
|
|
106
114
|
this.reset(true);
|
|
107
115
|
}
|
|
116
|
+
destroyAuthKey() {
|
|
117
|
+
if (!this._session._authKey.ready || this._needDestroyAuthKey) return;
|
|
118
|
+
this._needDestroyAuthKey = true;
|
|
119
|
+
this._sentDestroyAuthKey = false;
|
|
120
|
+
this._flushTimer.emitNow();
|
|
121
|
+
}
|
|
108
122
|
reset(forever = false) {
|
|
109
123
|
this._session.initConnectionCalled = false;
|
|
110
124
|
this._flushTimer.reset();
|
|
@@ -114,6 +128,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
114
128
|
utils.timers.clearTimeout(timeout);
|
|
115
129
|
}
|
|
116
130
|
this._session.pendingGetStateTimeouts.clear();
|
|
131
|
+
if (this._needDestroyAuthKey) this._sentDestroyAuthKey = false;
|
|
117
132
|
if (forever) {
|
|
118
133
|
utils.timers.clearTimeout(this._pfsUpdateTimeout);
|
|
119
134
|
this.onDisconnect.clear();
|
|
@@ -189,6 +204,8 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
189
204
|
this.onError.emit(error);
|
|
190
205
|
}
|
|
191
206
|
onConnectionUsable() {
|
|
207
|
+
this._session.lastActivityTime = performance.now();
|
|
208
|
+
this._active = false;
|
|
192
209
|
if (this.params.withUpdates) {
|
|
193
210
|
this.sendRpc({ _: "updates.getState" }).catch((err) => {
|
|
194
211
|
if (this._destroyed || innerTl.RpcError.is(err, "AUTH_KEY_UNREGISTERED")) return;
|
|
@@ -212,7 +229,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
212
229
|
authorization.doAuthorization(this, this._crypto).then(([authKey, serverSalt, timeOffset]) => {
|
|
213
230
|
this._session._authKey.setup(authKey);
|
|
214
231
|
this._salts.currentSalt = serverSalt;
|
|
215
|
-
this._session.updateTimeOffset(timeOffset);
|
|
232
|
+
this._session.updateTimeOffset(timeOffset, true);
|
|
216
233
|
this._session.authorizationPending = false;
|
|
217
234
|
this.onKeyChange.emit(authKey);
|
|
218
235
|
if (this._usePfs) {
|
|
@@ -328,7 +345,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
328
345
|
this.log.debug("temp key is expiring soon");
|
|
329
346
|
this._authorizePfs(true);
|
|
330
347
|
},
|
|
331
|
-
(TEMP_AUTH_KEY_EXPIRY -
|
|
348
|
+
(TEMP_AUTH_KEY_EXPIRY - TEMP_AUTH_KEY_REFRESH_MARGIN - miscUtils.getRandomInt(TEMP_AUTH_KEY_REFRESH_JITTER)) * 1e3
|
|
332
349
|
);
|
|
333
350
|
}).catch((err) => {
|
|
334
351
|
if (this._destroyed) return;
|
|
@@ -356,6 +373,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
356
373
|
}
|
|
357
374
|
_warnedAboutUpdates = false;
|
|
358
375
|
onMessage(data) {
|
|
376
|
+
this._session.lastActivityTime = performance.now();
|
|
359
377
|
if (this._pendingWaitForUnencrypted.length) {
|
|
360
378
|
const int32 = new Int32Array(data.buffer, data.byteOffset, 2);
|
|
361
379
|
if (int32[0] === 0 && int32[1] === 0) {
|
|
@@ -410,13 +428,12 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
410
428
|
this.log.warn("warn: ignoring message with invalid messageId = %s (is even)", messageId);
|
|
411
429
|
return;
|
|
412
430
|
}
|
|
413
|
-
if (this._session.recentIncomingMsgIds.
|
|
414
|
-
this.log.debug("ignoring duplicate message %s", messageId);
|
|
431
|
+
if (!this._session.recentIncomingMsgIds.add(messageId)) {
|
|
432
|
+
this.log.debug("ignoring duplicate or too old message %s", messageId);
|
|
415
433
|
return;
|
|
416
434
|
}
|
|
417
435
|
const message = message_;
|
|
418
436
|
this.log.debug("received %s (msg_id: %l)", message._, messageId);
|
|
419
|
-
this._session.recentIncomingMsgIds.add(messageId);
|
|
420
437
|
switch (message._) {
|
|
421
438
|
case "mt_msgs_ack":
|
|
422
439
|
case "mt_http_wait":
|
|
@@ -469,6 +486,16 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
469
486
|
case "mt_destroy_session_none":
|
|
470
487
|
this.log.debug("received %s (msg_id = %l): %j", message._, messageId, message);
|
|
471
488
|
break;
|
|
489
|
+
case "mt_destroy_auth_key_ok":
|
|
490
|
+
case "mt_destroy_auth_key_none":
|
|
491
|
+
this.log.info("auth key destroyed: %s", message._);
|
|
492
|
+
this._needDestroyAuthKey = false;
|
|
493
|
+
this._sentDestroyAuthKey = false;
|
|
494
|
+
break;
|
|
495
|
+
case "mt_destroy_auth_key_fail":
|
|
496
|
+
this.log.warn("auth key destruction failed");
|
|
497
|
+
this._sentDestroyAuthKey = false;
|
|
498
|
+
break;
|
|
472
499
|
default:
|
|
473
500
|
if (innerTl.isAnyUpdates(message)) {
|
|
474
501
|
if (this._usable && this.params.inactivityTimeout) {
|
|
@@ -791,6 +818,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
791
818
|
}
|
|
792
819
|
this.log.debug("received pong: msg_id %l, ping_id %l, rtt = %dms", msgId, pingId, rtt);
|
|
793
820
|
this._session.resetLastPing();
|
|
821
|
+
this._flushTimer.emitBefore(this._session.lastPingTime + this._pingMustDelay());
|
|
794
822
|
}
|
|
795
823
|
_onBadServerSalt(msg) {
|
|
796
824
|
this._salts.currentSalt = msg.newServerSalt;
|
|
@@ -798,8 +826,19 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
798
826
|
}
|
|
799
827
|
_onBadMsgNotification(msgId, msg) {
|
|
800
828
|
switch (msg.errorCode) {
|
|
829
|
+
case 17: {
|
|
830
|
+
const serverTime = msgId.high >>> 0;
|
|
831
|
+
const timeOffset = serverTime - Math.floor(performance.now() / 1e3);
|
|
832
|
+
this._session.updateTimeOffset(timeOffset, true);
|
|
833
|
+
this.log.warn(
|
|
834
|
+
"msg_id too high, server time: %d, corrected offset to %d, resetting session",
|
|
835
|
+
serverTime,
|
|
836
|
+
timeOffset
|
|
837
|
+
);
|
|
838
|
+
this._resetSession("msg_id too high");
|
|
839
|
+
break;
|
|
840
|
+
}
|
|
801
841
|
case 16:
|
|
802
|
-
case 17:
|
|
803
842
|
case 20: {
|
|
804
843
|
if (msg.errorCode !== 20) {
|
|
805
844
|
const serverTime = msgId.high >>> 0;
|
|
@@ -1120,6 +1159,41 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1120
1159
|
}
|
|
1121
1160
|
this._onMessageFailed(msgId, "timeout");
|
|
1122
1161
|
};
|
|
1162
|
+
// https://github.com/tdlib/td/blob/master/td/mtproto/SessionConnection.h
|
|
1163
|
+
_rtt() {
|
|
1164
|
+
const rtt = this._session.lastPingRtt;
|
|
1165
|
+
if (Number.isNaN(rtt)) return 2e3;
|
|
1166
|
+
return Math.max(2e3, rtt * 1.5 + 1e3);
|
|
1167
|
+
}
|
|
1168
|
+
_readDisconnectDelay() {
|
|
1169
|
+
return this._active ? this._rtt() * 3.5 : 135e3 + this._randomDelay;
|
|
1170
|
+
}
|
|
1171
|
+
_pingDisconnectDelay() {
|
|
1172
|
+
return this._active && this.params.isMainConnection ? this._rtt() * 2.5 : 135e3 + this._randomDelay;
|
|
1173
|
+
}
|
|
1174
|
+
_pingMustDelay() {
|
|
1175
|
+
return this._active ? this._rtt() : this._pingInterval + this._randomDelay;
|
|
1176
|
+
}
|
|
1177
|
+
_isActive() {
|
|
1178
|
+
if (this._session.queuedRpc.length > 0) return true;
|
|
1179
|
+
for (const msg of this._session.pendingMessages.values()) {
|
|
1180
|
+
if (msg._ === "rpc") return true;
|
|
1181
|
+
}
|
|
1182
|
+
return false;
|
|
1183
|
+
}
|
|
1184
|
+
_checkTimeouts(now) {
|
|
1185
|
+
if (!this._session.lastPingMsgId.isZero() && now - this._session.lastPingTime > this._pingDisconnectDelay()) {
|
|
1186
|
+
this.log.warn("ping timeout, no pong for %dms", Math.round(now - this._session.lastPingTime));
|
|
1187
|
+
this._resetSession("ping timeout");
|
|
1188
|
+
return true;
|
|
1189
|
+
}
|
|
1190
|
+
if (now - this._session.lastActivityTime > this._readDisconnectDelay()) {
|
|
1191
|
+
this.log.warn("read timeout, last read was %dms ago", Math.round(now - this._session.lastActivityTime));
|
|
1192
|
+
this._resetSession("read timeout");
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
return false;
|
|
1196
|
+
}
|
|
1123
1197
|
_flush() {
|
|
1124
1198
|
if (this._disconnectedManually || !this._session._authKey.ready || this._isPfsBindingPending) {
|
|
1125
1199
|
this.log.debug(
|
|
@@ -1130,6 +1204,14 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1130
1204
|
);
|
|
1131
1205
|
return;
|
|
1132
1206
|
}
|
|
1207
|
+
const now = performance.now();
|
|
1208
|
+
const active = this._online && this._isActive();
|
|
1209
|
+
if (active && !this._active) {
|
|
1210
|
+
this._session.lastActivityTime = now;
|
|
1211
|
+
this._session.resetLastPing(true);
|
|
1212
|
+
}
|
|
1213
|
+
this._active = active;
|
|
1214
|
+
if (this._checkTimeouts(now)) return;
|
|
1133
1215
|
try {
|
|
1134
1216
|
this._doFlush();
|
|
1135
1217
|
} catch (e) {
|
|
@@ -1140,9 +1222,11 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1140
1222
|
if (this._session.hasPendingMessages) {
|
|
1141
1223
|
this._flushTimer.emitWhenIdle();
|
|
1142
1224
|
} else {
|
|
1143
|
-
const nextPingTime = this._session.lastPingTime + this.
|
|
1225
|
+
const nextPingTime = this._session.lastPingMsgId.isZero() ? this._session.lastPingTime + this._pingMustDelay() : Infinity;
|
|
1144
1226
|
const nextGetScheduleTime = this._session.getStateSchedule.raw[0]?.getState || Infinity;
|
|
1145
|
-
this.
|
|
1227
|
+
const readDeadline = this._session.lastActivityTime + this._readDisconnectDelay();
|
|
1228
|
+
const pingDeadline = this._session.lastPingMsgId.isZero() ? Infinity : this._session.lastPingTime + this._pingDisconnectDelay();
|
|
1229
|
+
this._flushTimer.emitBefore(Math.min(nextPingTime, nextGetScheduleTime, readDeadline, pingDeadline));
|
|
1146
1230
|
}
|
|
1147
1231
|
}
|
|
1148
1232
|
_doFlush() {
|
|
@@ -1166,6 +1250,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1166
1250
|
let resendMsgIds = null;
|
|
1167
1251
|
let cancelRpcs = null;
|
|
1168
1252
|
let destroySessions = null;
|
|
1253
|
+
let destroyAuthKey = false;
|
|
1169
1254
|
let rootMsgId = null;
|
|
1170
1255
|
const now = performance.now();
|
|
1171
1256
|
if (this._session.queuedAcks.length) {
|
|
@@ -1185,20 +1270,12 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1185
1270
|
packetSize += ackRequest.length + 16;
|
|
1186
1271
|
messageCount += 1;
|
|
1187
1272
|
}
|
|
1188
|
-
if (now - this._session.lastPingTime > this.
|
|
1189
|
-
if (!this._session.lastPingMsgId.isZero()) {
|
|
1190
|
-
this.log.warn("didn't receive pong for previous ping (msg_id = %l). are we offline?", this._session.lastPingMsgId);
|
|
1191
|
-
if (!this._disconnectedManually) {
|
|
1192
|
-
this._resetSession("ping timeout");
|
|
1193
|
-
}
|
|
1194
|
-
return;
|
|
1195
|
-
}
|
|
1273
|
+
if (this._session.lastPingMsgId.isZero() && now - this._session.lastPingTime > this._pingMustDelay()) {
|
|
1196
1274
|
pingId = longUtils.randomLong();
|
|
1197
1275
|
const obj = {
|
|
1198
1276
|
_: "mt_ping_delay_disconnect",
|
|
1199
1277
|
pingId,
|
|
1200
|
-
|
|
1201
|
-
disconnectDelay: Math.round(this._pingInterval * 125e-5)
|
|
1278
|
+
disconnectDelay: Math.round(this._pingDisconnectDelay() / 1e3) + 2
|
|
1202
1279
|
};
|
|
1203
1280
|
this._session.lastPingTime = now;
|
|
1204
1281
|
pingRequest = tlRuntime.TlBinaryWriter.serializeObject(this._writerMap, obj);
|
|
@@ -1260,6 +1337,11 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1260
1337
|
destroySessions = this._queuedDestroySession;
|
|
1261
1338
|
this._queuedDestroySession = [];
|
|
1262
1339
|
}
|
|
1340
|
+
if (this._needDestroyAuthKey && !this._sentDestroyAuthKey) {
|
|
1341
|
+
destroyAuthKey = true;
|
|
1342
|
+
containerMessageCount += 1;
|
|
1343
|
+
containerSize += 20;
|
|
1344
|
+
}
|
|
1263
1345
|
if (this._salts.shouldFetchSalts()) {
|
|
1264
1346
|
const obj = {
|
|
1265
1347
|
_: "mt_get_future_salts",
|
|
@@ -1370,6 +1452,10 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1370
1452
|
otherPendings.push(pending);
|
|
1371
1453
|
});
|
|
1372
1454
|
}
|
|
1455
|
+
if (destroyAuthKey) {
|
|
1456
|
+
this._registerOutgoingMsgId(this._session.writeMessage(writer, { _: "mt_destroy_auth_key" }));
|
|
1457
|
+
this._sentDestroyAuthKey = true;
|
|
1458
|
+
}
|
|
1373
1459
|
if (getFutureSaltsRequest) {
|
|
1374
1460
|
getFutureSaltsMsgId = this._registerOutgoingMsgId(this._session.writeMessage(writer, getFutureSaltsRequest));
|
|
1375
1461
|
const pending = {
|
|
@@ -28,6 +28,8 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
28
28
|
readonly params: SessionConnectionParams;
|
|
29
29
|
private _flushTimer;
|
|
30
30
|
private _queuedDestroySession;
|
|
31
|
+
private _needDestroyAuthKey;
|
|
32
|
+
private _sentDestroyAuthKey;
|
|
31
33
|
private _pendingWaitForUnencrypted;
|
|
32
34
|
private _usePfs;
|
|
33
35
|
private _isPfsBindingPending;
|
|
@@ -40,6 +42,7 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
40
42
|
private _salts;
|
|
41
43
|
readonly _session: MtprotoSession;
|
|
42
44
|
private _pingInterval;
|
|
45
|
+
private _randomDelay;
|
|
43
46
|
readonly onDisconnect: Emitter<void>;
|
|
44
47
|
readonly onKeyChange: Emitter<Uint8Array | null>;
|
|
45
48
|
readonly onTmpKeyChange: Emitter<[Uint8Array, number] | null>;
|
|
@@ -50,10 +53,12 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
50
53
|
private _triedReconnectingOn404;
|
|
51
54
|
constructor(params: SessionConnectionParams, log: Logger);
|
|
52
55
|
private _online;
|
|
56
|
+
private _active;
|
|
53
57
|
getAuthKey(temp?: boolean): Uint8Array | null;
|
|
54
58
|
setUsePfs(usePfs: boolean): void;
|
|
55
59
|
onClosed(): void;
|
|
56
60
|
destroy(): Promise<void>;
|
|
61
|
+
destroyAuthKey(): void;
|
|
57
62
|
reset(forever?: boolean): void;
|
|
58
63
|
onConnected(): void;
|
|
59
64
|
protected handleError(error: Error): void;
|
|
@@ -87,6 +92,12 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
87
92
|
private _cancelRpc;
|
|
88
93
|
protected _onInactivityTimeout(): void;
|
|
89
94
|
private _handleGetStateTimeout;
|
|
95
|
+
private _rtt;
|
|
96
|
+
private _readDisconnectDelay;
|
|
97
|
+
private _pingDisconnectDelay;
|
|
98
|
+
private _pingMustDelay;
|
|
99
|
+
private _isActive;
|
|
100
|
+
private _checkTimeouts;
|
|
90
101
|
private _flush;
|
|
91
102
|
private _doFlush;
|
|
92
103
|
}
|
|
@@ -28,6 +28,8 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
28
28
|
readonly params: SessionConnectionParams;
|
|
29
29
|
private _flushTimer;
|
|
30
30
|
private _queuedDestroySession;
|
|
31
|
+
private _needDestroyAuthKey;
|
|
32
|
+
private _sentDestroyAuthKey;
|
|
31
33
|
private _pendingWaitForUnencrypted;
|
|
32
34
|
private _usePfs;
|
|
33
35
|
private _isPfsBindingPending;
|
|
@@ -40,6 +42,7 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
40
42
|
private _salts;
|
|
41
43
|
readonly _session: MtprotoSession;
|
|
42
44
|
private _pingInterval;
|
|
45
|
+
private _randomDelay;
|
|
43
46
|
readonly onDisconnect: Emitter<void>;
|
|
44
47
|
readonly onKeyChange: Emitter<Uint8Array | null>;
|
|
45
48
|
readonly onTmpKeyChange: Emitter<[Uint8Array, number] | null>;
|
|
@@ -50,10 +53,12 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
50
53
|
private _triedReconnectingOn404;
|
|
51
54
|
constructor(params: SessionConnectionParams, log: Logger);
|
|
52
55
|
private _online;
|
|
56
|
+
private _active;
|
|
53
57
|
getAuthKey(temp?: boolean): Uint8Array | null;
|
|
54
58
|
setUsePfs(usePfs: boolean): void;
|
|
55
59
|
onClosed(): void;
|
|
56
60
|
destroy(): Promise<void>;
|
|
61
|
+
destroyAuthKey(): void;
|
|
57
62
|
reset(forever?: boolean): void;
|
|
58
63
|
onConnected(): void;
|
|
59
64
|
protected handleError(error: Error): void;
|
|
@@ -87,6 +92,12 @@ export declare class SessionConnection extends PersistentConnection {
|
|
|
87
92
|
private _cancelRpc;
|
|
88
93
|
protected _onInactivityTimeout(): void;
|
|
89
94
|
private _handleGetStateTimeout;
|
|
95
|
+
private _rtt;
|
|
96
|
+
private _readDisconnectDelay;
|
|
97
|
+
private _pingDisconnectDelay;
|
|
98
|
+
private _pingMustDelay;
|
|
99
|
+
private _isActive;
|
|
100
|
+
private _checkTimeouts;
|
|
90
101
|
private _flush;
|
|
91
102
|
private _doFlush;
|
|
92
103
|
}
|
|
@@ -4,6 +4,7 @@ import Long from "long";
|
|
|
4
4
|
import { createAesIgeForMessageOld } from "../utils/crypto/mtproto.js";
|
|
5
5
|
import { EarlyTimer } from "../utils/early-timer.js";
|
|
6
6
|
import { longFromBuffer, randomLong, removeFromLongArray } from "../utils/long-utils.js";
|
|
7
|
+
import { getRandomInt } from "../utils/misc-utils.js";
|
|
7
8
|
import { doAuthorization } from "./authorization.js";
|
|
8
9
|
import { MtprotoSession } from "./mtproto-session.js";
|
|
9
10
|
import { PersistentConnection } from "./persistent-connection.js";
|
|
@@ -11,6 +12,8 @@ import { TransportError } from "./transports/abstract.js";
|
|
|
11
12
|
import { MtcuteError, MtTimeoutError, MtArgumentError } from "../types/errors.js";
|
|
12
13
|
import { RpcError, isAnyUpdates } from "../tl/inner-tl.js";
|
|
13
14
|
const TEMP_AUTH_KEY_EXPIRY = 86400;
|
|
15
|
+
const TEMP_AUTH_KEY_REFRESH_MARGIN = 3600;
|
|
16
|
+
const TEMP_AUTH_KEY_REFRESH_JITTER = 600;
|
|
14
17
|
const GET_STATE_INTERVAL = 1500;
|
|
15
18
|
const GET_STATE_TIMEOUT = 2500;
|
|
16
19
|
const GZIP_PACKED_ID = 812830625;
|
|
@@ -22,6 +25,8 @@ const INVOKE_AFTER_MSG_SIZE = 12;
|
|
|
22
25
|
class SessionConnection extends PersistentConnection {
|
|
23
26
|
_flushTimer = new EarlyTimer();
|
|
24
27
|
_queuedDestroySession = [];
|
|
28
|
+
_needDestroyAuthKey = false;
|
|
29
|
+
_sentDestroyAuthKey = false;
|
|
25
30
|
// waitForMessage
|
|
26
31
|
_pendingWaitForUnencrypted = [];
|
|
27
32
|
_usePfs;
|
|
@@ -34,9 +39,8 @@ class SessionConnection extends PersistentConnection {
|
|
|
34
39
|
_crypto;
|
|
35
40
|
_salts;
|
|
36
41
|
_session;
|
|
37
|
-
// todo: we should probably do adaptive ping interval based on rtt like tdlib:
|
|
38
|
-
// https://github.com/tdlib/td/blob/91aa6c9e4d0774eabf4f8d7f3aa51239032059a6/td/mtproto/SessionConnection.h
|
|
39
42
|
_pingInterval;
|
|
43
|
+
_randomDelay = getRandomInt(5e3);
|
|
40
44
|
// NB: dont forget to update .reset()
|
|
41
45
|
onDisconnect = new Emitter();
|
|
42
46
|
onKeyChange = new Emitter();
|
|
@@ -66,6 +70,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
66
70
|
this._online = params.platform.isOnline?.() ?? true;
|
|
67
71
|
}
|
|
68
72
|
_online;
|
|
73
|
+
_active = false;
|
|
69
74
|
getAuthKey(temp = false) {
|
|
70
75
|
const key = temp ? this._session._authKeyTemp : this._session._authKey;
|
|
71
76
|
if (!key.ready) return null;
|
|
@@ -91,6 +96,9 @@ class SessionConnection extends PersistentConnection {
|
|
|
91
96
|
for (const msgId of this._session.pendingGetStateTimeouts.keys()) {
|
|
92
97
|
this._onMessageFailed(msgId, "connection loss", true);
|
|
93
98
|
}
|
|
99
|
+
for (const rpc of this._session.getStateSchedule.raw) {
|
|
100
|
+
rpc.getState = 0;
|
|
101
|
+
}
|
|
94
102
|
this.onDisconnect.emit();
|
|
95
103
|
this.reset();
|
|
96
104
|
}
|
|
@@ -98,6 +106,12 @@ class SessionConnection extends PersistentConnection {
|
|
|
98
106
|
await super.destroy();
|
|
99
107
|
this.reset(true);
|
|
100
108
|
}
|
|
109
|
+
destroyAuthKey() {
|
|
110
|
+
if (!this._session._authKey.ready || this._needDestroyAuthKey) return;
|
|
111
|
+
this._needDestroyAuthKey = true;
|
|
112
|
+
this._sentDestroyAuthKey = false;
|
|
113
|
+
this._flushTimer.emitNow();
|
|
114
|
+
}
|
|
101
115
|
reset(forever = false) {
|
|
102
116
|
this._session.initConnectionCalled = false;
|
|
103
117
|
this._flushTimer.reset();
|
|
@@ -107,6 +121,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
107
121
|
timers.clearTimeout(timeout);
|
|
108
122
|
}
|
|
109
123
|
this._session.pendingGetStateTimeouts.clear();
|
|
124
|
+
if (this._needDestroyAuthKey) this._sentDestroyAuthKey = false;
|
|
110
125
|
if (forever) {
|
|
111
126
|
timers.clearTimeout(this._pfsUpdateTimeout);
|
|
112
127
|
this.onDisconnect.clear();
|
|
@@ -182,6 +197,8 @@ class SessionConnection extends PersistentConnection {
|
|
|
182
197
|
this.onError.emit(error);
|
|
183
198
|
}
|
|
184
199
|
onConnectionUsable() {
|
|
200
|
+
this._session.lastActivityTime = performance.now();
|
|
201
|
+
this._active = false;
|
|
185
202
|
if (this.params.withUpdates) {
|
|
186
203
|
this.sendRpc({ _: "updates.getState" }).catch((err) => {
|
|
187
204
|
if (this._destroyed || RpcError.is(err, "AUTH_KEY_UNREGISTERED")) return;
|
|
@@ -205,7 +222,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
205
222
|
doAuthorization(this, this._crypto).then(([authKey, serverSalt, timeOffset]) => {
|
|
206
223
|
this._session._authKey.setup(authKey);
|
|
207
224
|
this._salts.currentSalt = serverSalt;
|
|
208
|
-
this._session.updateTimeOffset(timeOffset);
|
|
225
|
+
this._session.updateTimeOffset(timeOffset, true);
|
|
209
226
|
this._session.authorizationPending = false;
|
|
210
227
|
this.onKeyChange.emit(authKey);
|
|
211
228
|
if (this._usePfs) {
|
|
@@ -321,7 +338,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
321
338
|
this.log.debug("temp key is expiring soon");
|
|
322
339
|
this._authorizePfs(true);
|
|
323
340
|
},
|
|
324
|
-
(TEMP_AUTH_KEY_EXPIRY -
|
|
341
|
+
(TEMP_AUTH_KEY_EXPIRY - TEMP_AUTH_KEY_REFRESH_MARGIN - getRandomInt(TEMP_AUTH_KEY_REFRESH_JITTER)) * 1e3
|
|
325
342
|
);
|
|
326
343
|
}).catch((err) => {
|
|
327
344
|
if (this._destroyed) return;
|
|
@@ -349,6 +366,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
349
366
|
}
|
|
350
367
|
_warnedAboutUpdates = false;
|
|
351
368
|
onMessage(data) {
|
|
369
|
+
this._session.lastActivityTime = performance.now();
|
|
352
370
|
if (this._pendingWaitForUnencrypted.length) {
|
|
353
371
|
const int32 = new Int32Array(data.buffer, data.byteOffset, 2);
|
|
354
372
|
if (int32[0] === 0 && int32[1] === 0) {
|
|
@@ -403,13 +421,12 @@ class SessionConnection extends PersistentConnection {
|
|
|
403
421
|
this.log.warn("warn: ignoring message with invalid messageId = %s (is even)", messageId);
|
|
404
422
|
return;
|
|
405
423
|
}
|
|
406
|
-
if (this._session.recentIncomingMsgIds.
|
|
407
|
-
this.log.debug("ignoring duplicate message %s", messageId);
|
|
424
|
+
if (!this._session.recentIncomingMsgIds.add(messageId)) {
|
|
425
|
+
this.log.debug("ignoring duplicate or too old message %s", messageId);
|
|
408
426
|
return;
|
|
409
427
|
}
|
|
410
428
|
const message = message_;
|
|
411
429
|
this.log.debug("received %s (msg_id: %l)", message._, messageId);
|
|
412
|
-
this._session.recentIncomingMsgIds.add(messageId);
|
|
413
430
|
switch (message._) {
|
|
414
431
|
case "mt_msgs_ack":
|
|
415
432
|
case "mt_http_wait":
|
|
@@ -462,6 +479,16 @@ class SessionConnection extends PersistentConnection {
|
|
|
462
479
|
case "mt_destroy_session_none":
|
|
463
480
|
this.log.debug("received %s (msg_id = %l): %j", message._, messageId, message);
|
|
464
481
|
break;
|
|
482
|
+
case "mt_destroy_auth_key_ok":
|
|
483
|
+
case "mt_destroy_auth_key_none":
|
|
484
|
+
this.log.info("auth key destroyed: %s", message._);
|
|
485
|
+
this._needDestroyAuthKey = false;
|
|
486
|
+
this._sentDestroyAuthKey = false;
|
|
487
|
+
break;
|
|
488
|
+
case "mt_destroy_auth_key_fail":
|
|
489
|
+
this.log.warn("auth key destruction failed");
|
|
490
|
+
this._sentDestroyAuthKey = false;
|
|
491
|
+
break;
|
|
465
492
|
default:
|
|
466
493
|
if (isAnyUpdates(message)) {
|
|
467
494
|
if (this._usable && this.params.inactivityTimeout) {
|
|
@@ -784,6 +811,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
784
811
|
}
|
|
785
812
|
this.log.debug("received pong: msg_id %l, ping_id %l, rtt = %dms", msgId, pingId, rtt);
|
|
786
813
|
this._session.resetLastPing();
|
|
814
|
+
this._flushTimer.emitBefore(this._session.lastPingTime + this._pingMustDelay());
|
|
787
815
|
}
|
|
788
816
|
_onBadServerSalt(msg) {
|
|
789
817
|
this._salts.currentSalt = msg.newServerSalt;
|
|
@@ -791,8 +819,19 @@ class SessionConnection extends PersistentConnection {
|
|
|
791
819
|
}
|
|
792
820
|
_onBadMsgNotification(msgId, msg) {
|
|
793
821
|
switch (msg.errorCode) {
|
|
822
|
+
case 17: {
|
|
823
|
+
const serverTime = msgId.high >>> 0;
|
|
824
|
+
const timeOffset = serverTime - Math.floor(performance.now() / 1e3);
|
|
825
|
+
this._session.updateTimeOffset(timeOffset, true);
|
|
826
|
+
this.log.warn(
|
|
827
|
+
"msg_id too high, server time: %d, corrected offset to %d, resetting session",
|
|
828
|
+
serverTime,
|
|
829
|
+
timeOffset
|
|
830
|
+
);
|
|
831
|
+
this._resetSession("msg_id too high");
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
794
834
|
case 16:
|
|
795
|
-
case 17:
|
|
796
835
|
case 20: {
|
|
797
836
|
if (msg.errorCode !== 20) {
|
|
798
837
|
const serverTime = msgId.high >>> 0;
|
|
@@ -1113,6 +1152,41 @@ class SessionConnection extends PersistentConnection {
|
|
|
1113
1152
|
}
|
|
1114
1153
|
this._onMessageFailed(msgId, "timeout");
|
|
1115
1154
|
};
|
|
1155
|
+
// https://github.com/tdlib/td/blob/master/td/mtproto/SessionConnection.h
|
|
1156
|
+
_rtt() {
|
|
1157
|
+
const rtt = this._session.lastPingRtt;
|
|
1158
|
+
if (Number.isNaN(rtt)) return 2e3;
|
|
1159
|
+
return Math.max(2e3, rtt * 1.5 + 1e3);
|
|
1160
|
+
}
|
|
1161
|
+
_readDisconnectDelay() {
|
|
1162
|
+
return this._active ? this._rtt() * 3.5 : 135e3 + this._randomDelay;
|
|
1163
|
+
}
|
|
1164
|
+
_pingDisconnectDelay() {
|
|
1165
|
+
return this._active && this.params.isMainConnection ? this._rtt() * 2.5 : 135e3 + this._randomDelay;
|
|
1166
|
+
}
|
|
1167
|
+
_pingMustDelay() {
|
|
1168
|
+
return this._active ? this._rtt() : this._pingInterval + this._randomDelay;
|
|
1169
|
+
}
|
|
1170
|
+
_isActive() {
|
|
1171
|
+
if (this._session.queuedRpc.length > 0) return true;
|
|
1172
|
+
for (const msg of this._session.pendingMessages.values()) {
|
|
1173
|
+
if (msg._ === "rpc") return true;
|
|
1174
|
+
}
|
|
1175
|
+
return false;
|
|
1176
|
+
}
|
|
1177
|
+
_checkTimeouts(now) {
|
|
1178
|
+
if (!this._session.lastPingMsgId.isZero() && now - this._session.lastPingTime > this._pingDisconnectDelay()) {
|
|
1179
|
+
this.log.warn("ping timeout, no pong for %dms", Math.round(now - this._session.lastPingTime));
|
|
1180
|
+
this._resetSession("ping timeout");
|
|
1181
|
+
return true;
|
|
1182
|
+
}
|
|
1183
|
+
if (now - this._session.lastActivityTime > this._readDisconnectDelay()) {
|
|
1184
|
+
this.log.warn("read timeout, last read was %dms ago", Math.round(now - this._session.lastActivityTime));
|
|
1185
|
+
this._resetSession("read timeout");
|
|
1186
|
+
return true;
|
|
1187
|
+
}
|
|
1188
|
+
return false;
|
|
1189
|
+
}
|
|
1116
1190
|
_flush() {
|
|
1117
1191
|
if (this._disconnectedManually || !this._session._authKey.ready || this._isPfsBindingPending) {
|
|
1118
1192
|
this.log.debug(
|
|
@@ -1123,6 +1197,14 @@ class SessionConnection extends PersistentConnection {
|
|
|
1123
1197
|
);
|
|
1124
1198
|
return;
|
|
1125
1199
|
}
|
|
1200
|
+
const now = performance.now();
|
|
1201
|
+
const active = this._online && this._isActive();
|
|
1202
|
+
if (active && !this._active) {
|
|
1203
|
+
this._session.lastActivityTime = now;
|
|
1204
|
+
this._session.resetLastPing(true);
|
|
1205
|
+
}
|
|
1206
|
+
this._active = active;
|
|
1207
|
+
if (this._checkTimeouts(now)) return;
|
|
1126
1208
|
try {
|
|
1127
1209
|
this._doFlush();
|
|
1128
1210
|
} catch (e) {
|
|
@@ -1133,9 +1215,11 @@ class SessionConnection extends PersistentConnection {
|
|
|
1133
1215
|
if (this._session.hasPendingMessages) {
|
|
1134
1216
|
this._flushTimer.emitWhenIdle();
|
|
1135
1217
|
} else {
|
|
1136
|
-
const nextPingTime = this._session.lastPingTime + this.
|
|
1218
|
+
const nextPingTime = this._session.lastPingMsgId.isZero() ? this._session.lastPingTime + this._pingMustDelay() : Infinity;
|
|
1137
1219
|
const nextGetScheduleTime = this._session.getStateSchedule.raw[0]?.getState || Infinity;
|
|
1138
|
-
this.
|
|
1220
|
+
const readDeadline = this._session.lastActivityTime + this._readDisconnectDelay();
|
|
1221
|
+
const pingDeadline = this._session.lastPingMsgId.isZero() ? Infinity : this._session.lastPingTime + this._pingDisconnectDelay();
|
|
1222
|
+
this._flushTimer.emitBefore(Math.min(nextPingTime, nextGetScheduleTime, readDeadline, pingDeadline));
|
|
1139
1223
|
}
|
|
1140
1224
|
}
|
|
1141
1225
|
_doFlush() {
|
|
@@ -1159,6 +1243,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
1159
1243
|
let resendMsgIds = null;
|
|
1160
1244
|
let cancelRpcs = null;
|
|
1161
1245
|
let destroySessions = null;
|
|
1246
|
+
let destroyAuthKey = false;
|
|
1162
1247
|
let rootMsgId = null;
|
|
1163
1248
|
const now = performance.now();
|
|
1164
1249
|
if (this._session.queuedAcks.length) {
|
|
@@ -1178,20 +1263,12 @@ class SessionConnection extends PersistentConnection {
|
|
|
1178
1263
|
packetSize += ackRequest.length + 16;
|
|
1179
1264
|
messageCount += 1;
|
|
1180
1265
|
}
|
|
1181
|
-
if (now - this._session.lastPingTime > this.
|
|
1182
|
-
if (!this._session.lastPingMsgId.isZero()) {
|
|
1183
|
-
this.log.warn("didn't receive pong for previous ping (msg_id = %l). are we offline?", this._session.lastPingMsgId);
|
|
1184
|
-
if (!this._disconnectedManually) {
|
|
1185
|
-
this._resetSession("ping timeout");
|
|
1186
|
-
}
|
|
1187
|
-
return;
|
|
1188
|
-
}
|
|
1266
|
+
if (this._session.lastPingMsgId.isZero() && now - this._session.lastPingTime > this._pingMustDelay()) {
|
|
1189
1267
|
pingId = randomLong();
|
|
1190
1268
|
const obj = {
|
|
1191
1269
|
_: "mt_ping_delay_disconnect",
|
|
1192
1270
|
pingId,
|
|
1193
|
-
|
|
1194
|
-
disconnectDelay: Math.round(this._pingInterval * 125e-5)
|
|
1271
|
+
disconnectDelay: Math.round(this._pingDisconnectDelay() / 1e3) + 2
|
|
1195
1272
|
};
|
|
1196
1273
|
this._session.lastPingTime = now;
|
|
1197
1274
|
pingRequest = TlBinaryWriter.serializeObject(this._writerMap, obj);
|
|
@@ -1253,6 +1330,11 @@ class SessionConnection extends PersistentConnection {
|
|
|
1253
1330
|
destroySessions = this._queuedDestroySession;
|
|
1254
1331
|
this._queuedDestroySession = [];
|
|
1255
1332
|
}
|
|
1333
|
+
if (this._needDestroyAuthKey && !this._sentDestroyAuthKey) {
|
|
1334
|
+
destroyAuthKey = true;
|
|
1335
|
+
containerMessageCount += 1;
|
|
1336
|
+
containerSize += 20;
|
|
1337
|
+
}
|
|
1256
1338
|
if (this._salts.shouldFetchSalts()) {
|
|
1257
1339
|
const obj = {
|
|
1258
1340
|
_: "mt_get_future_salts",
|
|
@@ -1363,6 +1445,10 @@ class SessionConnection extends PersistentConnection {
|
|
|
1363
1445
|
otherPendings.push(pending);
|
|
1364
1446
|
});
|
|
1365
1447
|
}
|
|
1448
|
+
if (destroyAuthKey) {
|
|
1449
|
+
this._registerOutgoingMsgId(this._session.writeMessage(writer, { _: "mt_destroy_auth_key" }));
|
|
1450
|
+
this._sentDestroyAuthKey = true;
|
|
1451
|
+
}
|
|
1366
1452
|
if (getFutureSaltsRequest) {
|
|
1367
1453
|
getFutureSaltsMsgId = this._registerOutgoingMsgId(this._session.writeMessage(writer, getFutureSaltsRequest));
|
|
1368
1454
|
const pending = {
|