@mtkruto/node 0.67.2 → 0.68.0
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/esm/0_errors.js +2 -6
- package/esm/3_errors.js +2 -12
- package/esm/3_types.d.ts +1 -0
- package/esm/3_types.d.ts.map +1 -1
- package/esm/3_types.js +1 -0
- package/esm/4_errors.js +2 -12
- package/esm/_dnt.polyfills.d.ts +99 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -1
- package/esm/_dnt.polyfills.js +127 -1
- package/esm/_dnt.test_polyfills.d.ts.map +1 -0
- package/esm/client/0_filters_test.d.ts.map +1 -1
- package/esm/client/0_markdown_test.d.ts.map +1 -1
- package/esm/client/0_params.d.ts +2 -0
- package/esm/client/0_params.d.ts.map +1 -1
- package/esm/client/0_password.d.ts +5 -5
- package/esm/client/0_password.d.ts.map +1 -1
- package/esm/client/0_password_test.d.ts.map +1 -1
- package/esm/client/0_storage_operations.js +143 -155
- package/esm/client/0_storage_operations_test.d.ts.map +1 -1
- package/esm/client/0_utilities.d.ts +1 -1
- package/esm/client/0_utilities_test.d.ts.map +1 -1
- package/esm/client/1_client_plain.js +4 -22
- package/esm/client/1_composer.js +8 -21
- package/esm/client/2_account_manager.js +85 -97
- package/esm/client/2_bot_info_manager.js +26 -38
- package/esm/client/2_business_connection_manager.js +10 -23
- package/esm/client/2_client_encrypted.js +194 -211
- package/esm/client/2_file_manager.d.ts +4 -3
- package/esm/client/2_file_manager.d.ts.map +1 -1
- package/esm/client/2_file_manager.js +268 -224
- package/esm/client/2_file_manager_test.d.ts.map +1 -1
- package/esm/client/2_network_statistics_manager.js +8 -21
- package/esm/client/2_payment_manager.js +7 -20
- package/esm/client/2_reaction_manager.js +7 -20
- package/esm/client/2_translations_manager.js +97 -107
- package/esm/client/2_update_manager.js +764 -759
- package/esm/client/3_client_encrypted_pool.js +10 -26
- package/esm/client/3_client_encrypted_pool_test.d.ts.map +1 -1
- package/esm/client/3_message_manager.d.ts +1 -1
- package/esm/client/3_message_manager.js +441 -448
- package/esm/client/3_message_manager_test.d.ts.map +1 -1
- package/esm/client/3_video_chat_manager.d.ts +1 -1
- package/esm/client/3_video_chat_manager.js +57 -68
- package/esm/client/4_callback_query_manager.js +18 -30
- package/esm/client/4_chat_list_manager.js +322 -318
- package/esm/client/4_chat_manager.js +118 -131
- package/esm/client/4_forum_manager.js +67 -73
- package/esm/client/4_gift_manager.js +16 -29
- package/esm/client/4_inline_query_manager.js +16 -28
- package/esm/client/4_link_preview_manager.js +6 -19
- package/esm/client/4_poll_manager.js +44 -57
- package/esm/client/4_story_manager.js +41 -53
- package/esm/client/5_client.d.ts +7 -0
- package/esm/client/5_client.d.ts.map +1 -1
- package/esm/client/5_client.js +1269 -1288
- package/esm/connection/1_connection_tcp.node.js +48 -65
- package/esm/connection/1_connection_web_socket.js +75 -91
- package/esm/deps/jsr.io/@roj/tgcrypto/1.0.1/dist/tgcrypto.js +3 -11
- package/esm/deps/jsr.io/@std/async/1.0.13/mux_async_iterator.js +31 -47
- package/esm/deps/jsr.io/@std/async/1.0.13/tee.js +11 -34
- package/esm/deps/jsr.io/@std/datetime/0.225.5/_date_time_formatter.js +4 -17
- package/esm/mod.js +2 -12
- package/esm/session/0_session_state.js +12 -38
- package/esm/session/1_session.js +49 -72
- package/esm/session/2_session_encrypted.js +324 -320
- package/esm/storage/1_utilities_test.d.ts.map +1 -1
- package/esm/storage/2_storage_indexed_db.js +26 -44
- package/esm/storage/2_storage_local_storage.node.js +12 -25
- package/esm/storage/2_storage_memory.js +24 -41
- package/esm/storage/2_storage_session_storage.js +3 -16
- package/esm/tl/0_utilities_test.d.ts.map +1 -1
- package/esm/tl/1_tl_reader.js +80 -88
- package/esm/tl/1_tl_reader_test.d.ts.map +1 -1
- package/esm/tl/1_tl_writer.js +155 -164
- package/esm/tl/1_tl_writer_test.d.ts.map +1 -1
- package/esm/transport/0_transport.js +1 -8
- package/esm/transport/1_transport_abridged.js +11 -24
- package/esm/transport/1_transport_intermediate.js +10 -23
- package/esm/transport/2_transport_provider_web_socket.d.ts.map +1 -1
- package/esm/types/0_upload_progress.d.ts +29 -0
- package/esm/types/0_upload_progress.d.ts.map +1 -0
- package/esm/types/0_upload_progress.js +20 -0
- package/esm/types/1_sticker.d.ts +1 -1
- package/esm/types/1_sticker.d.ts.map +1 -1
- package/esm/types/2_poll_answer.d.ts +19 -0
- package/esm/types/2_poll_answer.d.ts.map +1 -1
- package/esm/types/2_poll_answer.js +19 -0
- package/esm/types/7_update.d.ts +21 -2
- package/esm/types/7_update.d.ts.map +1 -1
- package/esm/utilities/0_bigint_test.d.ts.map +1 -1
- package/esm/utilities/0_buffer.d.ts +1 -1
- package/esm/utilities/0_buffer.d.ts.map +1 -1
- package/esm/utilities/0_buffer_test.d.ts.map +1 -1
- package/esm/utilities/0_hash.d.ts +2 -2
- package/esm/utilities/0_hash.d.ts.map +1 -1
- package/esm/utilities/0_mutex.js +4 -19
- package/esm/utilities/0_part_stream.js +11 -25
- package/esm/utilities/0_part_stream_test.d.ts.map +1 -1
- package/esm/utilities/0_rle.d.ts +2 -2
- package/esm/utilities/0_rle.d.ts.map +1 -1
- package/esm/utilities/0_rle_test.d.ts.map +1 -1
- package/esm/utilities/0_text.d.ts +20 -1
- package/esm/utilities/0_text.d.ts.map +1 -1
- package/esm/utilities/0_text.js +19 -0
- package/esm/utilities/1_auth.d.ts +1 -1
- package/esm/utilities/1_auth.d.ts.map +1 -1
- package/esm/utilities/1_base64.d.ts +1 -1
- package/esm/utilities/1_base64.d.ts.map +1 -1
- package/esm/utilities/1_base64_test.d.ts.map +1 -1
- package/esm/utilities/1_crypto.js +42 -53
- package/esm/utilities/1_crypto_test.d.ts.map +1 -1
- package/esm/utilities/1_logger.d.ts +2 -2
- package/esm/utilities/1_math_test.d.ts.map +1 -1
- package/esm/utilities/2_queue.js +29 -47
- package/package.json +1 -1
- package/script/0_errors.js +2 -6
- package/script/2_tl.js +17 -7
- package/script/3_errors.js +2 -12
- package/script/3_types.d.ts +1 -0
- package/script/3_types.d.ts.map +1 -1
- package/script/3_types.js +1 -0
- package/script/4_constants.js +17 -7
- package/script/4_errors.js +2 -12
- package/script/_dnt.polyfills.d.ts +99 -0
- package/script/_dnt.polyfills.d.ts.map +1 -1
- package/script/_dnt.polyfills.js +128 -0
- package/script/_dnt.test_polyfills.d.ts.map +1 -0
- package/script/client/0_filters_test.d.ts.map +1 -1
- package/script/client/0_markdown_test.d.ts.map +1 -1
- package/script/client/0_params.d.ts +2 -0
- package/script/client/0_params.d.ts.map +1 -1
- package/script/client/0_password.d.ts +5 -5
- package/script/client/0_password.d.ts.map +1 -1
- package/script/client/0_password.js +17 -7
- package/script/client/0_password_test.d.ts.map +1 -1
- package/script/client/0_storage_operations.js +143 -155
- package/script/client/0_storage_operations_test.d.ts.map +1 -1
- package/script/client/0_utilities.d.ts +1 -1
- package/script/client/0_utilities_test.d.ts.map +1 -1
- package/script/client/1_client_plain.js +4 -22
- package/script/client/1_composer.js +8 -21
- package/script/client/2_account_manager.js +85 -97
- package/script/client/2_bot_info_manager.js +26 -38
- package/script/client/2_business_connection_manager.js +10 -23
- package/script/client/2_client_encrypted.js +195 -212
- package/script/client/2_file_manager.d.ts +4 -3
- package/script/client/2_file_manager.d.ts.map +1 -1
- package/script/client/2_file_manager.js +285 -231
- package/script/client/2_file_manager_test.d.ts.map +1 -1
- package/script/client/2_network_statistics_manager.js +8 -21
- package/script/client/2_payment_manager.js +7 -20
- package/script/client/2_reaction_manager.js +7 -20
- package/script/client/2_translations_manager.js +98 -108
- package/script/client/2_update_manager.js +764 -759
- package/script/client/3_client_encrypted_pool.js +10 -26
- package/script/client/3_client_encrypted_pool_test.d.ts.map +1 -1
- package/script/client/3_message_manager.d.ts +1 -1
- package/script/client/3_message_manager.js +441 -448
- package/script/client/3_message_manager_test.d.ts.map +1 -1
- package/script/client/3_video_chat_manager.d.ts +1 -1
- package/script/client/3_video_chat_manager.js +57 -68
- package/script/client/4_callback_query_manager.js +18 -30
- package/script/client/4_chat_list_manager.js +322 -318
- package/script/client/4_chat_manager.js +118 -131
- package/script/client/4_forum_manager.js +67 -73
- package/script/client/4_gift_manager.js +16 -29
- package/script/client/4_inline_query_manager.js +16 -28
- package/script/client/4_link_preview_manager.js +6 -19
- package/script/client/4_poll_manager.js +44 -57
- package/script/client/4_story_manager.js +41 -53
- package/script/client/5_client.d.ts +7 -0
- package/script/client/5_client.d.ts.map +1 -1
- package/script/client/5_client.js +1269 -1288
- package/script/connection/1_connection_tcp.node.js +48 -65
- package/script/connection/1_connection_web_socket.js +92 -98
- package/script/deps/jsr.io/@roj/tgcrypto/1.0.1/dist/tgcrypto.js +3 -11
- package/script/deps/jsr.io/@std/assert/1.0.13/equal.js +17 -7
- package/script/deps/jsr.io/@std/async/1.0.13/delay.js +17 -7
- package/script/deps/jsr.io/@std/async/1.0.13/mux_async_iterator.js +31 -47
- package/script/deps/jsr.io/@std/async/1.0.13/tee.js +11 -34
- package/script/deps/jsr.io/@std/datetime/0.225.5/_date_time_formatter.js +4 -17
- package/script/deps/jsr.io/@std/internal/1.0.10/format.js +17 -7
- package/script/deps/jsr.io/@std/internal/1.0.10/styles.js +17 -7
- package/script/deps/jsr.io/@std/path/1.1.0/_os.js +17 -7
- package/script/mod.js +19 -19
- package/script/session/0_session_state.js +12 -38
- package/script/session/1_session.js +66 -79
- package/script/session/2_session_encrypted.js +325 -321
- package/script/storage/1_utilities_test.d.ts.map +1 -1
- package/script/storage/2_storage_indexed_db.js +26 -44
- package/script/storage/2_storage_local_storage.node.js +12 -25
- package/script/storage/2_storage_memory.js +24 -41
- package/script/storage/2_storage_session_storage.js +3 -16
- package/script/tl/0_utilities_test.d.ts.map +1 -1
- package/script/tl/1_tl_reader.js +81 -89
- package/script/tl/1_tl_reader_test.d.ts.map +1 -1
- package/script/tl/1_tl_writer.js +156 -165
- package/script/tl/1_tl_writer_test.d.ts.map +1 -1
- package/script/tl/2_telegram.js +17 -7
- package/script/transport/0_obfuscation.js +17 -7
- package/script/transport/0_transport.js +1 -8
- package/script/transport/1_transport_abridged.js +11 -24
- package/script/transport/1_transport_intermediate.js +10 -23
- package/script/transport/2_transport_provider_web_socket.d.ts.map +1 -1
- package/script/types/0_upload_progress.d.ts +29 -0
- package/script/types/0_upload_progress.d.ts.map +1 -0
- package/script/types/0_upload_progress.js +21 -0
- package/script/types/1_sticker.d.ts +1 -1
- package/script/types/1_sticker.d.ts.map +1 -1
- package/script/types/2_poll_answer.d.ts +19 -0
- package/script/types/2_poll_answer.d.ts.map +1 -1
- package/script/types/2_poll_answer.js +19 -0
- package/script/types/7_update.d.ts +21 -2
- package/script/types/7_update.d.ts.map +1 -1
- package/script/utilities/0_bigint.js +17 -7
- package/script/utilities/0_bigint_test.d.ts.map +1 -1
- package/script/utilities/0_buffer.d.ts +1 -1
- package/script/utilities/0_buffer.d.ts.map +1 -1
- package/script/utilities/0_buffer_test.d.ts.map +1 -1
- package/script/utilities/0_env.js +17 -7
- package/script/utilities/0_hash.d.ts +2 -2
- package/script/utilities/0_hash.d.ts.map +1 -1
- package/script/utilities/0_hash.js +17 -7
- package/script/utilities/0_misc.js +17 -7
- package/script/utilities/0_mutex.js +4 -19
- package/script/utilities/0_part_stream.js +11 -25
- package/script/utilities/0_part_stream_test.d.ts.map +1 -1
- package/script/utilities/0_rle.d.ts +2 -2
- package/script/utilities/0_rle.d.ts.map +1 -1
- package/script/utilities/0_rle_test.d.ts.map +1 -1
- package/script/utilities/0_text.d.ts +20 -1
- package/script/utilities/0_text.d.ts.map +1 -1
- package/script/utilities/0_text.js +19 -0
- package/script/utilities/1_auth.d.ts +1 -1
- package/script/utilities/1_auth.d.ts.map +1 -1
- package/script/utilities/1_auth.js +17 -7
- package/script/utilities/1_base64.d.ts +1 -1
- package/script/utilities/1_base64.d.ts.map +1 -1
- package/script/utilities/1_base64_test.d.ts.map +1 -1
- package/script/utilities/1_crypto.js +60 -61
- package/script/utilities/1_crypto_test.d.ts.map +1 -1
- package/script/utilities/1_logger.d.ts +2 -2
- package/script/utilities/1_math_test.d.ts.map +1 -1
- package/script/utilities/2_queue.js +30 -48
|
@@ -17,18 +17,6 @@
|
|
|
17
17
|
* You should have received a copy of the GNU Lesser General Public License
|
|
18
18
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
19
19
|
*/
|
|
20
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
21
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
22
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
23
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
24
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
25
|
-
};
|
|
26
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
27
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
28
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
29
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
30
|
-
};
|
|
31
|
-
var _SessionEncrypted_instances, _a, _SessionEncrypted_id, _SessionEncrypted_authKey, _SessionEncrypted_authKeyId, _SessionEncrypted_toAcknowledge, _SessionEncrypted_pendingMessages, _SessionEncrypted_pendingPings, _SessionEncrypted_L, _SessionEncrypted_TGCRYPTO_INITED, _SessionEncrypted_assertNotDisconnected, _SessionEncrypted_invalidateSession, _SessionEncrypted_rejectAllPending, _SessionEncrypted_onMessageFailed, _SessionEncrypted_setServerSalt, _SessionEncrypted_receive, _SessionEncrypted_encryptMessage, _SessionEncrypted_decryptMessage, _SessionEncrypted_startReceiveLoop, _SessionEncrypted_receiveLoopActive, _SessionEncrypted_receiveLoop, _SessionEncrypted_onMessage, _SessionEncrypted_onRpcResult, _SessionEncrypted_onMsgDetailedInfo, _SessionEncrypted_onMsgNewDetailedInfo, _SessionEncrypted_onBadMsgNotification, _SessionEncrypted_onBadServerSalt, _SessionEncrypted_onPong, _SessionEncrypted_onNewSessionCreated, _SessionEncrypted_onMessageContainer, _SessionEncrypted_pingInterval, _SessionEncrypted_startPingLoop, _SessionEncrypted_pingLoopAbortController, _SessionEncrypted_LpingLoop, _SessionEncrypted_pingLoop, _SessionEncrypted_sendPingDelayDisconnect, _SessionEncrypted_resendPendingPing;
|
|
32
20
|
import { assertEquals, concat, delay, ige256Decrypt, ige256Encrypt, initTgCrypto, SECOND } from "../0_deps.js";
|
|
33
21
|
import { ConnectionError, TransportError } from "../0_errors.js";
|
|
34
22
|
import { bigIntFromBuffer, bufferFromBigInt, drop, getLogger, getRandomId, gunzip, mod, sha1, sha256, toUnixTimestamp } from "../1_utilities.js";
|
|
@@ -42,62 +30,96 @@ const GZIP_PACKED = 0x3072CFA1;
|
|
|
42
30
|
const RPC_RESULT = 0xF35C6D01;
|
|
43
31
|
const RPC_ERROR = Mtproto.schema.definitions["rpc_error"][0];
|
|
44
32
|
export class SessionEncrypted extends Session {
|
|
33
|
+
#id = getRandomId();
|
|
34
|
+
#authKey = new Uint8Array();
|
|
35
|
+
#authKeyId = 0n;
|
|
36
|
+
handlers = {};
|
|
37
|
+
#toAcknowledge = new Array();
|
|
38
|
+
#pendingMessages = new Set();
|
|
39
|
+
#pendingPings = new Map();
|
|
40
|
+
#L;
|
|
41
|
+
static #TGCRYPTO_INITED = false;
|
|
45
42
|
constructor(dc, params) {
|
|
46
43
|
super(dc, params);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
_SessionEncrypted_authKey.set(this, new Uint8Array());
|
|
50
|
-
_SessionEncrypted_authKeyId.set(this, 0n);
|
|
51
|
-
Object.defineProperty(this, "handlers", {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
configurable: true,
|
|
54
|
-
writable: true,
|
|
55
|
-
value: {}
|
|
56
|
-
});
|
|
57
|
-
_SessionEncrypted_toAcknowledge.set(this, new Array());
|
|
58
|
-
_SessionEncrypted_pendingMessages.set(this, new Set());
|
|
59
|
-
_SessionEncrypted_pendingPings.set(this, new Map());
|
|
60
|
-
_SessionEncrypted_L.set(this, void 0);
|
|
61
|
-
_SessionEncrypted_receiveLoopActive.set(this, false);
|
|
62
|
-
//// PING LOOP ////
|
|
63
|
-
_SessionEncrypted_pingInterval.set(this, 56 * SECOND);
|
|
64
|
-
_SessionEncrypted_pingLoopAbortController.set(this, void 0);
|
|
65
|
-
_SessionEncrypted_LpingLoop.set(this, void 0);
|
|
66
|
-
const L = __classPrivateFieldSet(this, _SessionEncrypted_L, getLogger("SessionEncrypted").client(id++), "f");
|
|
67
|
-
__classPrivateFieldSet(this, _SessionEncrypted_LpingLoop, L.branch("#pingLoop"), "f");
|
|
44
|
+
const L = this.#L = getLogger("SessionEncrypted").client(id++);
|
|
45
|
+
this.#LpingLoop = L.branch("#pingLoop");
|
|
68
46
|
}
|
|
69
47
|
async setAuthKey(key) {
|
|
70
48
|
const hash = await sha1(key);
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
this.#authKeyId = bigIntFromBuffer(hash.slice(-8), true, false);
|
|
50
|
+
this.#authKey = key;
|
|
73
51
|
}
|
|
74
52
|
get authKey() {
|
|
75
|
-
return
|
|
53
|
+
return this.#authKey;
|
|
76
54
|
}
|
|
77
55
|
async connect() {
|
|
78
56
|
if (!this.connected) {
|
|
79
|
-
|
|
57
|
+
this.#rejectAllPending(new ConnectionError("Not connected."));
|
|
80
58
|
}
|
|
81
59
|
await super.connect();
|
|
82
|
-
if (!
|
|
60
|
+
if (!SessionEncrypted.#TGCRYPTO_INITED) {
|
|
83
61
|
await initTgCrypto();
|
|
84
|
-
|
|
62
|
+
SessionEncrypted.#TGCRYPTO_INITED = true;
|
|
85
63
|
}
|
|
86
|
-
|
|
87
|
-
|
|
64
|
+
this.#startReceiveLoop();
|
|
65
|
+
this.#startPingLoop();
|
|
88
66
|
}
|
|
89
67
|
disconnect() {
|
|
90
68
|
super.disconnect();
|
|
91
69
|
this.state.reset();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
70
|
+
this.#id = getRandomId();
|
|
71
|
+
this.#pingLoopAbortController?.abort();
|
|
72
|
+
this.#rejectAllPending(new ConnectionError("Not connected."));
|
|
73
|
+
}
|
|
74
|
+
#assertNotDisconnected() {
|
|
75
|
+
if (this.disconnected) {
|
|
76
|
+
throw new ConnectionError("Not connected.");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async #invalidateSession(reason) {
|
|
80
|
+
this.#L.debug("invalidating session because of", reason);
|
|
81
|
+
this.#id = getRandomId();
|
|
82
|
+
this.state.reset();
|
|
83
|
+
this.disconnect();
|
|
84
|
+
await this.connect();
|
|
85
|
+
this.#rejectAllPending(new SessionError("Session invalidated."));
|
|
86
|
+
}
|
|
87
|
+
#rejectAllPending(reason) {
|
|
88
|
+
for (const id of this.#pendingMessages) {
|
|
89
|
+
this.#onMessageFailed(id, reason);
|
|
90
|
+
}
|
|
91
|
+
this.#pendingMessages.clear();
|
|
92
|
+
for (const pendingPing of this.#pendingPings.values()) {
|
|
93
|
+
pendingPing.reject(reason);
|
|
94
|
+
}
|
|
95
|
+
this.#pendingPings.clear();
|
|
96
|
+
}
|
|
97
|
+
#onMessageFailed(id, reason) {
|
|
98
|
+
this.#pendingMessages.delete(id);
|
|
99
|
+
const pendingPing = this.#pendingPings.get(id);
|
|
100
|
+
if (pendingPing) {
|
|
101
|
+
this.#pendingPings.delete(id);
|
|
102
|
+
if (reason instanceof SessionError) {
|
|
103
|
+
drop(this.#resendPendingPing(pendingPing));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
pendingPing.reject(reason);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// message was not sent by us
|
|
111
|
+
this.handlers.onMessageFailed?.(id, reason);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
#setServerSalt(newServerSalt) {
|
|
115
|
+
this.state.serverSalt = newServerSalt;
|
|
116
|
+
this.handlers.onNewServerSalt?.(newServerSalt);
|
|
95
117
|
}
|
|
96
118
|
async send(body) {
|
|
97
119
|
if (!this.disconnected && !this.connected) {
|
|
98
120
|
await super.waitUntilConnected();
|
|
99
121
|
}
|
|
100
|
-
|
|
122
|
+
this.#assertNotDisconnected();
|
|
101
123
|
const msg_id = this.state.nextMessageId();
|
|
102
124
|
const seqno = this.state.nextSeqNo(true);
|
|
103
125
|
let message = {
|
|
@@ -106,12 +128,12 @@ export class SessionEncrypted extends Session {
|
|
|
106
128
|
seqno,
|
|
107
129
|
body,
|
|
108
130
|
};
|
|
109
|
-
if (
|
|
131
|
+
if (this.#toAcknowledge.length) {
|
|
110
132
|
const ack = {
|
|
111
133
|
_: "message",
|
|
112
134
|
msg_id: this.state.nextMessageId(),
|
|
113
135
|
seqno: this.state.nextSeqNo(false),
|
|
114
|
-
body: Mtproto.serializeObject({ _: "msgs_ack", msg_ids:
|
|
136
|
+
body: Mtproto.serializeObject({ _: "msgs_ack", msg_ids: this.#toAcknowledge.splice(0, 8192) }),
|
|
115
137
|
};
|
|
116
138
|
message = {
|
|
117
139
|
_: "message",
|
|
@@ -123,308 +145,290 @@ export class SessionEncrypted extends Session {
|
|
|
123
145
|
},
|
|
124
146
|
};
|
|
125
147
|
}
|
|
126
|
-
|
|
127
|
-
const payload = await
|
|
148
|
+
this.#L.out(message);
|
|
149
|
+
const payload = await this.#encryptMessage(message);
|
|
128
150
|
await this.transport.transport.send(payload);
|
|
129
|
-
|
|
151
|
+
this.#pendingMessages.add(msg_id);
|
|
130
152
|
return msg_id;
|
|
131
153
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
async #receive() {
|
|
155
|
+
this.#assertNotDisconnected();
|
|
156
|
+
const buffer = await this.transport.transport.receive();
|
|
157
|
+
if (buffer.length == 4) {
|
|
158
|
+
const int = bigIntFromBuffer(buffer, true, true);
|
|
159
|
+
throw new TransportError(Number(int));
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const decrypted = await this.#decryptMessage(buffer);
|
|
163
|
+
this.#L.in(decrypted);
|
|
164
|
+
return decrypted;
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
await this.#invalidateSession("decryption error");
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
136
170
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
171
|
+
async #encryptMessage(message) {
|
|
172
|
+
const payloadWriter = new TLWriter();
|
|
173
|
+
payloadWriter.writeInt64(this.state.serverSalt);
|
|
174
|
+
payloadWriter.writeInt64(this.#id);
|
|
175
|
+
payloadWriter.write(await serializeMessage(message));
|
|
176
|
+
payloadWriter.write(new Uint8Array(mod(-(payloadWriter.buffer.length + 12), 16) + 12));
|
|
177
|
+
const payload = payloadWriter.buffer;
|
|
178
|
+
const messageKey = (await sha256(concat([this.#authKey.subarray(88, 120), payload]))).subarray(8, 24);
|
|
179
|
+
const a = await sha256(concat([messageKey, this.#authKey.subarray(0, 36)]));
|
|
180
|
+
const b = await sha256(concat([this.#authKey.subarray(40, 76), messageKey]));
|
|
181
|
+
const aesKey = concat([a.subarray(0, 8), b.subarray(8, 24), a.subarray(24, 32)]);
|
|
182
|
+
const aesIV = concat([b.subarray(0, 8), a.subarray(8, 24), b.subarray(24, 32)]);
|
|
183
|
+
const messageWriter = new TLWriter();
|
|
184
|
+
messageWriter.writeInt64(this.#authKeyId);
|
|
185
|
+
messageWriter.write(messageKey);
|
|
186
|
+
messageWriter.write(ige256Encrypt(payload, aesKey, aesIV));
|
|
187
|
+
return messageWriter.buffer;
|
|
188
|
+
}
|
|
189
|
+
async #decryptMessage(buffer) {
|
|
190
|
+
const reader = new TLReader(buffer);
|
|
191
|
+
assertEquals(reader.readInt64(false), this.#authKeyId);
|
|
192
|
+
const messageKey_ = reader.readInt128();
|
|
193
|
+
const messageKey = bufferFromBigInt(messageKey_, 16, true, true);
|
|
194
|
+
const a = await sha256(concat([messageKey, this.#authKey.subarray(8, 44)]));
|
|
195
|
+
const b = await sha256(concat([this.#authKey.subarray(48, 84), messageKey]));
|
|
196
|
+
const aesKey = concat([a.subarray(0, 8), b.subarray(8, 24), a.subarray(24, 32)]);
|
|
197
|
+
const aesIv = concat([b.subarray(0, 8), a.subarray(8, 24), b.subarray(24, 32)]);
|
|
198
|
+
const plaintext = ige256Decrypt(reader.buffer, aesKey, aesIv);
|
|
199
|
+
assertEquals(plaintext.buffer.byteLength % 4, 0);
|
|
200
|
+
const plainReader = new TLReader(plaintext);
|
|
201
|
+
const _salt = plainReader.readInt64();
|
|
202
|
+
const _sessionId_ = plainReader.readInt64(false);
|
|
203
|
+
return deserializeMessage(plainReader);
|
|
204
|
+
}
|
|
205
|
+
//// RECEIVE LOOP ////
|
|
206
|
+
#startReceiveLoop() {
|
|
207
|
+
if (!this.#receiveLoopActive) {
|
|
208
|
+
drop(this.#receiveLoop());
|
|
209
|
+
}
|
|
147
210
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
211
|
+
#receiveLoopActive = false;
|
|
212
|
+
async #receiveLoop() {
|
|
213
|
+
this.#receiveLoopActive = true;
|
|
214
|
+
try {
|
|
215
|
+
while (this.connected) {
|
|
216
|
+
let message;
|
|
217
|
+
try {
|
|
218
|
+
message = await this.#receive();
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
this.#L.error("failed to receive message:", err);
|
|
222
|
+
if (!this.connected) {
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
if (message.body instanceof Uint8Array) {
|
|
231
|
+
this.#onMessage(message.msg_id, message.body);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
this.#onMessageContainer(message.msg_id, message.body);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
this.#L.error("failed to handle message:", err);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
this.#receiveLoopActive = false;
|
|
244
|
+
}
|
|
151
245
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
246
|
+
//// RECEIVE LOOP HANDLERS ////
|
|
247
|
+
async #onMessage(msgId, body) {
|
|
248
|
+
let reader = new TLReader(body);
|
|
249
|
+
let id = reader.readInt32(false);
|
|
250
|
+
if (id == GZIP_PACKED) {
|
|
251
|
+
reader = new TLReader(await gunzip(reader.readBytes()));
|
|
252
|
+
id = reader.readInt32(false);
|
|
253
|
+
}
|
|
254
|
+
if (id == RPC_RESULT) {
|
|
255
|
+
this.#onRpcResult(msgId, reader.buffer);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (!Mtproto.schema.identifierToName[id]) {
|
|
259
|
+
reader.unreadInt32();
|
|
260
|
+
this.handlers.onUpdate?.(reader.buffer);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
let type;
|
|
264
|
+
try {
|
|
265
|
+
reader.unreadInt32();
|
|
266
|
+
type = await Mtproto.deserializeType(X, reader);
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
this.#L.error("failed to deserialize MTProto type:", err);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.#L.debug("received", repr(type));
|
|
273
|
+
if (Mtproto.is("new_session_created", type)) {
|
|
274
|
+
this.#onNewSessionCreated(msgId, type);
|
|
275
|
+
}
|
|
276
|
+
else if (Mtproto.is("pong", type)) {
|
|
277
|
+
this.#onPong(msgId, type);
|
|
278
|
+
}
|
|
279
|
+
else if (Mtproto.is("bad_server_salt", type)) {
|
|
280
|
+
this.#onBadServerSalt(type);
|
|
281
|
+
}
|
|
282
|
+
else if (Mtproto.is("bad_msg_notification", type)) {
|
|
283
|
+
await this.#onBadMsgNotification(msgId, type);
|
|
284
|
+
}
|
|
285
|
+
else if (Mtproto.is("msg_detailed_info", type)) {
|
|
286
|
+
this.#onMsgDetailedInfo(type);
|
|
287
|
+
}
|
|
288
|
+
else if (Mtproto.is("msg_new_detailed_info", type)) {
|
|
289
|
+
this.#onMsgNewDetailedInfo(type);
|
|
160
290
|
}
|
|
161
291
|
else {
|
|
162
|
-
|
|
292
|
+
this.#L.debug(`unhandled MTProto type: ${repr(type)}`);
|
|
163
293
|
}
|
|
164
294
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
295
|
+
async #onRpcResult(msgId, body) {
|
|
296
|
+
this.#toAcknowledge.push(msgId);
|
|
297
|
+
let reader = new TLReader(body);
|
|
298
|
+
const reqMsgId = reader.readInt64();
|
|
299
|
+
let id = reader.readInt32(false);
|
|
300
|
+
if (id == GZIP_PACKED) {
|
|
301
|
+
reader = new TLReader(await gunzip(reader.readBytes()));
|
|
302
|
+
id = reader.readInt32(false);
|
|
303
|
+
reader.unreadInt32();
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
reader.unreadInt32();
|
|
307
|
+
}
|
|
308
|
+
if (id == RPC_ERROR) {
|
|
309
|
+
const error = await Mtproto.deserializeType("rpc_error", reader);
|
|
310
|
+
this.handlers.onRpcError?.(reqMsgId, error);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
this.handlers.onRpcResult?.(reqMsgId, reader.buffer);
|
|
314
|
+
}
|
|
178
315
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
316
|
+
#onMsgDetailedInfo(msgDetailedInfo) {
|
|
317
|
+
this.#toAcknowledge.push(msgDetailedInfo.answer_msg_id);
|
|
318
|
+
}
|
|
319
|
+
#onMsgNewDetailedInfo(msgNewDetailedInfo) {
|
|
320
|
+
this.#toAcknowledge.push(msgNewDetailedInfo.answer_msg_id);
|
|
321
|
+
}
|
|
322
|
+
async #onBadMsgNotification(msgId, badMsgNotification) {
|
|
323
|
+
let low = false;
|
|
324
|
+
switch (badMsgNotification.error_code) {
|
|
325
|
+
case 16: // message ID too low
|
|
326
|
+
low = true;
|
|
327
|
+
/* falls through */
|
|
328
|
+
case 17: // message ID too high
|
|
329
|
+
this.state.timeDifference = Math.abs(toUnixTimestamp(new Date()) - Number(msgId >> 32n));
|
|
330
|
+
if (!low) {
|
|
331
|
+
this.state.timeDifference = -this.state.timeDifference;
|
|
332
|
+
await this.#invalidateSession("message ID too high");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
this.#L.debug("message ID too low, resending message");
|
|
337
|
+
}
|
|
338
|
+
break;
|
|
339
|
+
case 48: // bad server salt
|
|
340
|
+
// resend
|
|
341
|
+
this.#L.debug("resending message that caused bad_server_salt");
|
|
342
|
+
break;
|
|
343
|
+
default:
|
|
344
|
+
await this.#invalidateSession("unexpected bad_msg_notification");
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
this.#onMessageFailed(badMsgNotification.bad_msg_id, new SessionError(badMsgNotification._));
|
|
348
|
+
}
|
|
349
|
+
#onBadServerSalt(badServerSalt) {
|
|
350
|
+
this.#setServerSalt(badServerSalt.new_server_salt);
|
|
351
|
+
this.#onMessageFailed(badServerSalt.bad_msg_id, new SessionError(badServerSalt._));
|
|
352
|
+
}
|
|
353
|
+
#onPong(msgId, pong) {
|
|
354
|
+
this.#toAcknowledge.push(msgId);
|
|
355
|
+
const pendingPing = this.#pendingPings.get(pong.msg_id);
|
|
356
|
+
if (pendingPing) {
|
|
357
|
+
pendingPing.resolve(pong);
|
|
358
|
+
this.#pendingPings.delete(pong.msg_id);
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
// pong is not ours
|
|
362
|
+
this.handlers.onPong?.(pong);
|
|
363
|
+
}
|
|
183
364
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
365
|
+
#onNewSessionCreated(msgId, newSessionCreated) {
|
|
366
|
+
this.#setServerSalt(newSessionCreated.server_salt);
|
|
367
|
+
this.#toAcknowledge.push(msgId);
|
|
187
368
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const b = await sha256(concat([__classPrivateFieldGet(this, _SessionEncrypted_authKey, "f").subarray(40, 76), messageKey]));
|
|
198
|
-
const aesKey = concat([a.subarray(0, 8), b.subarray(8, 24), a.subarray(24, 32)]);
|
|
199
|
-
const aesIV = concat([b.subarray(0, 8), a.subarray(8, 24), b.subarray(24, 32)]);
|
|
200
|
-
const messageWriter = new TLWriter();
|
|
201
|
-
messageWriter.writeInt64(__classPrivateFieldGet(this, _SessionEncrypted_authKeyId, "f"));
|
|
202
|
-
messageWriter.write(messageKey);
|
|
203
|
-
messageWriter.write(ige256Encrypt(payload, aesKey, aesIV));
|
|
204
|
-
return messageWriter.buffer;
|
|
205
|
-
}, _SessionEncrypted_decryptMessage = async function _SessionEncrypted_decryptMessage(buffer) {
|
|
206
|
-
const reader = new TLReader(buffer);
|
|
207
|
-
assertEquals(reader.readInt64(false), __classPrivateFieldGet(this, _SessionEncrypted_authKeyId, "f"));
|
|
208
|
-
const messageKey_ = reader.readInt128();
|
|
209
|
-
const messageKey = bufferFromBigInt(messageKey_, 16, true, true);
|
|
210
|
-
const a = await sha256(concat([messageKey, __classPrivateFieldGet(this, _SessionEncrypted_authKey, "f").subarray(8, 44)]));
|
|
211
|
-
const b = await sha256(concat([__classPrivateFieldGet(this, _SessionEncrypted_authKey, "f").subarray(48, 84), messageKey]));
|
|
212
|
-
const aesKey = concat([a.subarray(0, 8), b.subarray(8, 24), a.subarray(24, 32)]);
|
|
213
|
-
const aesIv = concat([b.subarray(0, 8), a.subarray(8, 24), b.subarray(24, 32)]);
|
|
214
|
-
const plaintext = ige256Decrypt(reader.buffer, aesKey, aesIv);
|
|
215
|
-
assertEquals(plaintext.buffer.byteLength % 4, 0);
|
|
216
|
-
const plainReader = new TLReader(plaintext);
|
|
217
|
-
const _salt = plainReader.readInt64();
|
|
218
|
-
const _sessionId_ = plainReader.readInt64(false);
|
|
219
|
-
return deserializeMessage(plainReader);
|
|
220
|
-
}, _SessionEncrypted_startReceiveLoop = function _SessionEncrypted_startReceiveLoop() {
|
|
221
|
-
if (!__classPrivateFieldGet(this, _SessionEncrypted_receiveLoopActive, "f")) {
|
|
222
|
-
drop(__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_receiveLoop).call(this));
|
|
369
|
+
#onMessageContainer(msgId, msgContainer) {
|
|
370
|
+
for (const message of msgContainer.messages) {
|
|
371
|
+
if (message.body instanceof Uint8Array) {
|
|
372
|
+
this.#onMessage(message.msg_id, message.body);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
this.#onMessageContainer(msgId, message.body);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
223
378
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
379
|
+
//// PING LOOP ////
|
|
380
|
+
#pingInterval = 56 * SECOND;
|
|
381
|
+
#startPingLoop() {
|
|
382
|
+
drop(this.#pingLoop());
|
|
383
|
+
}
|
|
384
|
+
#pingLoopAbortController;
|
|
385
|
+
#LpingLoop;
|
|
386
|
+
async #pingLoop() {
|
|
387
|
+
this.#pingLoopAbortController?.abort();
|
|
388
|
+
const controller = this.#pingLoopAbortController = new AbortController();
|
|
389
|
+
let timeElapsed = 0;
|
|
227
390
|
while (this.connected) {
|
|
228
|
-
let message;
|
|
229
391
|
try {
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
__classPrivateFieldGet(this, _SessionEncrypted_L, "f").error("failed to receive message:", err);
|
|
392
|
+
await delay(Math.max(0, this.#pingInterval - timeElapsed), { signal: controller.signal });
|
|
234
393
|
if (!this.connected) {
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
394
|
continue;
|
|
239
395
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
396
|
+
controller.signal.throwIfAborted();
|
|
397
|
+
const then = Date.now();
|
|
398
|
+
try {
|
|
399
|
+
await this.#sendPingDelayDisconnect(this.#pingInterval / SECOND + 15);
|
|
244
400
|
}
|
|
245
|
-
|
|
246
|
-
|
|
401
|
+
finally {
|
|
402
|
+
timeElapsed = Date.now() - then;
|
|
247
403
|
}
|
|
404
|
+
controller.signal.throwIfAborted();
|
|
248
405
|
}
|
|
249
406
|
catch (err) {
|
|
250
|
-
|
|
407
|
+
if (err instanceof DOMException && err.name == "AbortError") {
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
else if (!this.connected) {
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
this.#LpingLoop.error(err);
|
|
251
414
|
}
|
|
252
415
|
}
|
|
253
416
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
let id = reader.readInt32(false);
|
|
262
|
-
if (id == GZIP_PACKED) {
|
|
263
|
-
reader = new TLReader(await gunzip(reader.readBytes()));
|
|
264
|
-
id = reader.readInt32(false);
|
|
265
|
-
}
|
|
266
|
-
if (id == RPC_RESULT) {
|
|
267
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onRpcResult).call(this, msgId, reader.buffer);
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
if (!Mtproto.schema.identifierToName[id]) {
|
|
271
|
-
reader.unreadInt32();
|
|
272
|
-
this.handlers.onUpdate?.(reader.buffer);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
let type;
|
|
276
|
-
try {
|
|
277
|
-
reader.unreadInt32();
|
|
278
|
-
type = await Mtproto.deserializeType(X, reader);
|
|
279
|
-
}
|
|
280
|
-
catch (err) {
|
|
281
|
-
__classPrivateFieldGet(this, _SessionEncrypted_L, "f").error("failed to deserialize MTProto type:", err);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
__classPrivateFieldGet(this, _SessionEncrypted_L, "f").debug("received", repr(type));
|
|
285
|
-
if (Mtproto.is("new_session_created", type)) {
|
|
286
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onNewSessionCreated).call(this, msgId, type);
|
|
287
|
-
}
|
|
288
|
-
else if (Mtproto.is("pong", type)) {
|
|
289
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onPong).call(this, msgId, type);
|
|
290
|
-
}
|
|
291
|
-
else if (Mtproto.is("bad_server_salt", type)) {
|
|
292
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onBadServerSalt).call(this, type);
|
|
293
|
-
}
|
|
294
|
-
else if (Mtproto.is("bad_msg_notification", type)) {
|
|
295
|
-
await __classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onBadMsgNotification).call(this, msgId, type);
|
|
296
|
-
}
|
|
297
|
-
else if (Mtproto.is("msg_detailed_info", type)) {
|
|
298
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onMsgDetailedInfo).call(this, type);
|
|
299
|
-
}
|
|
300
|
-
else if (Mtproto.is("msg_new_detailed_info", type)) {
|
|
301
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onMsgNewDetailedInfo).call(this, type);
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
__classPrivateFieldGet(this, _SessionEncrypted_L, "f").debug(`unhandled MTProto type: ${repr(type)}`);
|
|
305
|
-
}
|
|
306
|
-
}, _SessionEncrypted_onRpcResult = async function _SessionEncrypted_onRpcResult(msgId, body) {
|
|
307
|
-
__classPrivateFieldGet(this, _SessionEncrypted_toAcknowledge, "f").push(msgId);
|
|
308
|
-
let reader = new TLReader(body);
|
|
309
|
-
const reqMsgId = reader.readInt64();
|
|
310
|
-
let id = reader.readInt32(false);
|
|
311
|
-
if (id == GZIP_PACKED) {
|
|
312
|
-
reader = new TLReader(await gunzip(reader.readBytes()));
|
|
313
|
-
id = reader.readInt32(false);
|
|
314
|
-
reader.unreadInt32();
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
reader.unreadInt32();
|
|
318
|
-
}
|
|
319
|
-
if (id == RPC_ERROR) {
|
|
320
|
-
const error = await Mtproto.deserializeType("rpc_error", reader);
|
|
321
|
-
this.handlers.onRpcError?.(reqMsgId, error);
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
this.handlers.onRpcResult?.(reqMsgId, reader.buffer);
|
|
325
|
-
}
|
|
326
|
-
}, _SessionEncrypted_onMsgDetailedInfo = function _SessionEncrypted_onMsgDetailedInfo(msgDetailedInfo) {
|
|
327
|
-
__classPrivateFieldGet(this, _SessionEncrypted_toAcknowledge, "f").push(msgDetailedInfo.answer_msg_id);
|
|
328
|
-
}, _SessionEncrypted_onMsgNewDetailedInfo = function _SessionEncrypted_onMsgNewDetailedInfo(msgNewDetailedInfo) {
|
|
329
|
-
__classPrivateFieldGet(this, _SessionEncrypted_toAcknowledge, "f").push(msgNewDetailedInfo.answer_msg_id);
|
|
330
|
-
}, _SessionEncrypted_onBadMsgNotification = async function _SessionEncrypted_onBadMsgNotification(msgId, badMsgNotification) {
|
|
331
|
-
let low = false;
|
|
332
|
-
switch (badMsgNotification.error_code) {
|
|
333
|
-
case 16: // message ID too low
|
|
334
|
-
low = true;
|
|
335
|
-
/* falls through */
|
|
336
|
-
case 17: // message ID too high
|
|
337
|
-
this.state.timeDifference = Math.abs(toUnixTimestamp(new Date()) - Number(msgId >> 32n));
|
|
338
|
-
if (!low) {
|
|
339
|
-
this.state.timeDifference = -this.state.timeDifference;
|
|
340
|
-
await __classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_invalidateSession).call(this, "message ID too high");
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
__classPrivateFieldGet(this, _SessionEncrypted_L, "f").debug("message ID too low, resending message");
|
|
345
|
-
}
|
|
346
|
-
break;
|
|
347
|
-
case 48: // bad server salt
|
|
348
|
-
// resend
|
|
349
|
-
__classPrivateFieldGet(this, _SessionEncrypted_L, "f").debug("resending message that caused bad_server_salt");
|
|
350
|
-
break;
|
|
351
|
-
default:
|
|
352
|
-
await __classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_invalidateSession).call(this, "unexpected bad_msg_notification");
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onMessageFailed).call(this, badMsgNotification.bad_msg_id, new SessionError(badMsgNotification._));
|
|
356
|
-
}, _SessionEncrypted_onBadServerSalt = function _SessionEncrypted_onBadServerSalt(badServerSalt) {
|
|
357
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_setServerSalt).call(this, badServerSalt.new_server_salt);
|
|
358
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onMessageFailed).call(this, badServerSalt.bad_msg_id, new SessionError(badServerSalt._));
|
|
359
|
-
}, _SessionEncrypted_onPong = function _SessionEncrypted_onPong(msgId, pong) {
|
|
360
|
-
__classPrivateFieldGet(this, _SessionEncrypted_toAcknowledge, "f").push(msgId);
|
|
361
|
-
const pendingPing = __classPrivateFieldGet(this, _SessionEncrypted_pendingPings, "f").get(pong.msg_id);
|
|
362
|
-
if (pendingPing) {
|
|
363
|
-
pendingPing.resolve(pong);
|
|
364
|
-
__classPrivateFieldGet(this, _SessionEncrypted_pendingPings, "f").delete(pong.msg_id);
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
// pong is not ours
|
|
368
|
-
this.handlers.onPong?.(pong);
|
|
369
|
-
}
|
|
370
|
-
}, _SessionEncrypted_onNewSessionCreated = function _SessionEncrypted_onNewSessionCreated(msgId, newSessionCreated) {
|
|
371
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_setServerSalt).call(this, newSessionCreated.server_salt);
|
|
372
|
-
__classPrivateFieldGet(this, _SessionEncrypted_toAcknowledge, "f").push(msgId);
|
|
373
|
-
}, _SessionEncrypted_onMessageContainer = function _SessionEncrypted_onMessageContainer(msgId, msgContainer) {
|
|
374
|
-
for (const message of msgContainer.messages) {
|
|
375
|
-
if (message.body instanceof Uint8Array) {
|
|
376
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onMessage).call(this, message.msg_id, message.body);
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_onMessageContainer).call(this, msgId, message.body);
|
|
380
|
-
}
|
|
417
|
+
async #sendPingDelayDisconnect(disconnect_delay) {
|
|
418
|
+
const ping_id = getRandomId();
|
|
419
|
+
const call = { _: "ping_delay_disconnect", ping_id, disconnect_delay };
|
|
420
|
+
const messageId = await this.send(Mtproto.serializeObject(call));
|
|
421
|
+
await new Promise((resolve, reject) => {
|
|
422
|
+
this.#pendingPings.set(messageId, { call, resolve, reject });
|
|
423
|
+
});
|
|
381
424
|
}
|
|
382
|
-
|
|
383
|
-
drop(__classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_pingLoop).call(this));
|
|
384
|
-
}, _SessionEncrypted_pingLoop = async function _SessionEncrypted_pingLoop() {
|
|
385
|
-
__classPrivateFieldGet(this, _SessionEncrypted_pingLoopAbortController, "f")?.abort();
|
|
386
|
-
const controller = __classPrivateFieldSet(this, _SessionEncrypted_pingLoopAbortController, new AbortController(), "f");
|
|
387
|
-
let timeElapsed = 0;
|
|
388
|
-
while (this.connected) {
|
|
425
|
+
async #resendPendingPing(pendingPing) {
|
|
389
426
|
try {
|
|
390
|
-
await
|
|
391
|
-
|
|
392
|
-
continue;
|
|
393
|
-
}
|
|
394
|
-
controller.signal.throwIfAborted();
|
|
395
|
-
const then = Date.now();
|
|
396
|
-
try {
|
|
397
|
-
await __classPrivateFieldGet(this, _SessionEncrypted_instances, "m", _SessionEncrypted_sendPingDelayDisconnect).call(this, __classPrivateFieldGet(this, _SessionEncrypted_pingInterval, "f") / SECOND + 15);
|
|
398
|
-
}
|
|
399
|
-
finally {
|
|
400
|
-
timeElapsed = Date.now() - then;
|
|
401
|
-
}
|
|
402
|
-
controller.signal.throwIfAborted();
|
|
427
|
+
const messageId = await this.send(Mtproto.serializeObject(pendingPing.call));
|
|
428
|
+
this.#pendingPings.set(messageId, pendingPing);
|
|
403
429
|
}
|
|
404
430
|
catch (err) {
|
|
405
|
-
|
|
406
|
-
break;
|
|
407
|
-
}
|
|
408
|
-
else if (!this.connected) {
|
|
409
|
-
break;
|
|
410
|
-
}
|
|
411
|
-
__classPrivateFieldGet(this, _SessionEncrypted_LpingLoop, "f").error(err);
|
|
431
|
+
pendingPing.reject(err);
|
|
412
432
|
}
|
|
413
433
|
}
|
|
414
|
-
}
|
|
415
|
-
const ping_id = getRandomId();
|
|
416
|
-
const call = { _: "ping_delay_disconnect", ping_id, disconnect_delay };
|
|
417
|
-
const messageId = await this.send(Mtproto.serializeObject(call));
|
|
418
|
-
await new Promise((resolve, reject) => {
|
|
419
|
-
__classPrivateFieldGet(this, _SessionEncrypted_pendingPings, "f").set(messageId, { call, resolve, reject });
|
|
420
|
-
});
|
|
421
|
-
}, _SessionEncrypted_resendPendingPing = async function _SessionEncrypted_resendPendingPing(pendingPing) {
|
|
422
|
-
try {
|
|
423
|
-
const messageId = await this.send(Mtproto.serializeObject(pendingPing.call));
|
|
424
|
-
__classPrivateFieldGet(this, _SessionEncrypted_pendingPings, "f").set(messageId, pendingPing);
|
|
425
|
-
}
|
|
426
|
-
catch (err) {
|
|
427
|
-
pendingPing.reject(err);
|
|
428
|
-
}
|
|
429
|
-
};
|
|
430
|
-
_SessionEncrypted_TGCRYPTO_INITED = { value: false };
|
|
434
|
+
}
|