@mtcute/core 0.1.1 → 0.2.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/cjs/base-client.d.ts +3 -6
- package/cjs/base-client.js +12 -20
- package/cjs/base-client.js.map +1 -1
- package/cjs/network/auth-key.test.d.ts +1 -0
- package/cjs/network/auth-key.test.js +111 -0
- package/cjs/network/auth-key.test.js.map +1 -0
- package/cjs/network/config-manager.js +2 -1
- package/cjs/network/config-manager.js.map +1 -1
- package/cjs/network/config-manager.test.d.ts +1 -0
- package/cjs/network/config-manager.test.js +170 -0
- package/cjs/network/config-manager.test.js.map +1 -0
- package/cjs/network/index.d.ts +1 -1
- package/cjs/network/index.js.map +1 -1
- package/cjs/network/multi-session-connection.js +17 -4
- package/cjs/network/multi-session-connection.js.map +1 -1
- package/cjs/network/network-manager.d.ts +1 -1
- package/cjs/network/network-manager.js +12 -5
- package/cjs/network/network-manager.js.map +1 -1
- package/cjs/network/persistent-connection.test.d.ts +1 -0
- package/cjs/network/persistent-connection.test.js +157 -0
- package/cjs/network/persistent-connection.test.js.map +1 -0
- package/cjs/network/session-connection.js +3 -2
- package/cjs/network/session-connection.js.map +1 -1
- package/cjs/network/transports/intermediate.test.d.ts +1 -0
- package/cjs/network/transports/intermediate.test.js +84 -0
- package/cjs/network/transports/intermediate.test.js.map +1 -0
- package/cjs/network/transports/obfuscated.js +1 -1
- package/cjs/network/transports/obfuscated.js.map +1 -1
- package/cjs/network/transports/obfuscated.test.d.ts +1 -0
- package/cjs/network/transports/obfuscated.test.js +131 -0
- package/cjs/network/transports/obfuscated.test.js.map +1 -0
- package/cjs/network/transports/tcp.js +1 -1
- package/cjs/network/transports/tcp.js.map +1 -1
- package/cjs/network/transports/tcp.test.d.ts +1 -0
- package/cjs/network/transports/tcp.test.js +103 -0
- package/cjs/network/transports/tcp.test.js.map +1 -0
- package/cjs/network/transports/websocket.test.d.ts +1 -0
- package/cjs/network/transports/websocket.test.js +91 -0
- package/cjs/network/transports/websocket.test.js.map +1 -0
- package/cjs/storage/abstract.d.ts +18 -0
- package/cjs/storage/abstract.js.map +1 -1
- package/cjs/storage/idb.d.ts +101 -0
- package/cjs/storage/idb.js +458 -0
- package/cjs/storage/idb.js.map +1 -0
- package/cjs/storage/idb.test.d.ts +1 -0
- package/cjs/storage/idb.test.js +21 -0
- package/cjs/storage/idb.test.js.map +1 -0
- package/cjs/storage/index.d.ts +0 -4
- package/cjs/storage/index.js +0 -4
- package/cjs/storage/index.js.map +1 -1
- package/cjs/storage/json-file.d.ts +12 -0
- package/cjs/storage/json-file.js +12 -0
- package/cjs/storage/json-file.js.map +1 -1
- package/cjs/storage/json.js +3 -2
- package/cjs/storage/json.js.map +1 -1
- package/cjs/storage/json.test.d.ts +1 -0
- package/cjs/storage/json.test.js +36 -0
- package/cjs/storage/json.test.js.map +1 -0
- package/cjs/storage/localstorage.d.ts +12 -0
- package/cjs/storage/localstorage.js +12 -0
- package/cjs/storage/localstorage.js.map +1 -1
- package/cjs/storage/localstorage.test.d.ts +1 -0
- package/cjs/storage/localstorage.test.js +23 -0
- package/cjs/storage/localstorage.test.js.map +1 -0
- package/cjs/storage/memory.d.ts +12 -1
- package/cjs/storage/memory.js +65 -3
- package/cjs/storage/memory.js.map +1 -1
- package/cjs/storage/memory.test.d.ts +1 -0
- package/cjs/storage/memory.test.js +48 -0
- package/cjs/storage/memory.test.js.map +1 -0
- package/cjs/utils/async-lock.test.d.ts +1 -0
- package/cjs/utils/async-lock.test.js +25 -0
- package/cjs/utils/async-lock.test.js.map +1 -0
- package/cjs/utils/bigint-utils.test.d.ts +1 -0
- package/cjs/utils/bigint-utils.test.js +150 -0
- package/cjs/utils/bigint-utils.test.js.map +1 -0
- package/cjs/utils/buffer-utils.test.d.ts +1 -0
- package/cjs/utils/buffer-utils.test.js +69 -0
- package/cjs/utils/buffer-utils.test.js.map +1 -0
- package/cjs/utils/condition-variable.test.d.ts +1 -0
- package/cjs/utils/condition-variable.test.js +27 -0
- package/cjs/utils/condition-variable.test.js.map +1 -0
- package/cjs/utils/controllable-promise.d.ts +0 -5
- package/cjs/utils/controllable-promise.js +1 -7
- package/cjs/utils/controllable-promise.js.map +1 -1
- package/cjs/utils/controllable-promise.test.d.ts +1 -0
- package/cjs/utils/controllable-promise.test.js +17 -0
- package/cjs/utils/controllable-promise.test.js.map +1 -0
- package/cjs/utils/crypto/keys.test.d.ts +1 -0
- package/cjs/utils/crypto/keys.test.js +40 -0
- package/cjs/utils/crypto/keys.test.js.map +1 -0
- package/cjs/utils/crypto/miller-rabin.test.d.ts +1 -0
- package/cjs/utils/crypto/miller-rabin.test.js +60 -0
- package/cjs/utils/crypto/miller-rabin.test.js.map +1 -0
- package/cjs/utils/crypto/mtproto.test.d.ts +1 -0
- package/cjs/utils/crypto/mtproto.test.js +50 -0
- package/cjs/utils/crypto/mtproto.test.js.map +1 -0
- package/cjs/utils/crypto/node.test.d.ts +1 -0
- package/cjs/utils/crypto/node.test.js +14 -0
- package/cjs/utils/crypto/node.test.js.map +1 -0
- package/cjs/utils/crypto/password.test.d.ts +1 -0
- package/cjs/utils/crypto/password.test.js +95 -0
- package/cjs/utils/crypto/password.test.js.map +1 -0
- package/cjs/utils/crypto/utils.test.d.ts +1 -0
- package/cjs/utils/crypto/utils.test.js +49 -0
- package/cjs/utils/crypto/utils.test.js.map +1 -0
- package/cjs/utils/crypto/web.test.d.ts +1 -0
- package/cjs/utils/crypto/web.test.js +17 -0
- package/cjs/utils/crypto/web.test.js.map +1 -0
- package/cjs/utils/deque.test.d.ts +1 -0
- package/cjs/utils/deque.test.js +128 -0
- package/cjs/utils/deque.test.js.map +1 -0
- package/cjs/utils/function-utils.test.d.ts +1 -0
- package/cjs/utils/function-utils.test.js +23 -0
- package/cjs/utils/function-utils.test.js.map +1 -0
- package/cjs/utils/linked-list.test.d.ts +1 -0
- package/cjs/utils/linked-list.test.js +36 -0
- package/cjs/utils/linked-list.test.js.map +1 -0
- package/cjs/utils/links/bots.test.d.ts +1 -0
- package/cjs/utils/links/bots.test.js +152 -0
- package/cjs/utils/links/bots.test.js.map +1 -0
- package/cjs/utils/links/chat.test.d.ts +1 -0
- package/cjs/utils/links/chat.test.js +84 -0
- package/cjs/utils/links/chat.test.js.map +1 -0
- package/cjs/utils/links/misc.test.d.ts +1 -0
- package/cjs/utils/links/misc.test.js +153 -0
- package/cjs/utils/links/misc.test.js.map +1 -0
- package/cjs/utils/links/proxy.test.d.ts +1 -0
- package/cjs/utils/links/proxy.test.js +74 -0
- package/cjs/utils/links/proxy.test.js.map +1 -0
- package/cjs/utils/links/user.test.d.ts +1 -0
- package/cjs/utils/links/user.test.js +63 -0
- package/cjs/utils/links/user.test.js.map +1 -0
- package/cjs/utils/logger.test.d.ts +1 -0
- package/cjs/utils/logger.test.js +127 -0
- package/cjs/utils/logger.test.js.map +1 -0
- package/cjs/utils/long-utils.test.d.ts +1 -0
- package/cjs/utils/long-utils.test.js +158 -0
- package/cjs/utils/long-utils.test.js.map +1 -0
- package/cjs/utils/lru-map.test.d.ts +1 -0
- package/cjs/utils/lru-map.test.js +96 -0
- package/cjs/utils/lru-map.test.js.map +1 -0
- package/cjs/utils/lru-set.test.d.ts +1 -0
- package/cjs/utils/lru-set.test.js +77 -0
- package/cjs/utils/lru-set.test.js.map +1 -0
- package/cjs/utils/peer-utils.js +3 -1
- package/cjs/utils/peer-utils.js.map +1 -1
- package/cjs/utils/peer-utils.test.d.ts +1 -0
- package/cjs/utils/peer-utils.test.js +122 -0
- package/cjs/utils/peer-utils.test.js.map +1 -0
- package/cjs/utils/sorted-array.test.d.ts +1 -0
- package/cjs/utils/sorted-array.test.js +66 -0
- package/cjs/utils/sorted-array.test.js.map +1 -0
- package/cjs/utils/string-session.test.d.ts +1 -0
- package/cjs/utils/string-session.test.js +106 -0
- package/cjs/utils/string-session.test.js.map +1 -0
- package/cjs/utils/tl-json.test.d.ts +1 -0
- package/cjs/utils/tl-json.test.js +83 -0
- package/cjs/utils/tl-json.test.js.map +1 -0
- package/cjs/utils/type-assertions.test.d.ts +1 -0
- package/cjs/utils/type-assertions.test.js +67 -0
- package/cjs/utils/type-assertions.test.js.map +1 -0
- package/esm/base-client.d.ts +3 -6
- package/esm/base-client.js +2 -10
- package/esm/base-client.js.map +1 -1
- package/esm/network/auth-key.test.d.ts +1 -0
- package/esm/network/auth-key.test.js +106 -0
- package/esm/network/auth-key.test.js.map +1 -0
- package/esm/network/config-manager.js +2 -1
- package/esm/network/config-manager.js.map +1 -1
- package/esm/network/config-manager.test.d.ts +1 -0
- package/esm/network/config-manager.test.js +168 -0
- package/esm/network/config-manager.test.js.map +1 -0
- package/esm/network/index.d.ts +1 -1
- package/esm/network/index.js.map +1 -1
- package/esm/network/multi-session-connection.js +17 -4
- package/esm/network/multi-session-connection.js.map +1 -1
- package/esm/network/network-manager.d.ts +1 -1
- package/esm/network/network-manager.js +12 -5
- package/esm/network/network-manager.js.map +1 -1
- package/esm/network/persistent-connection.test.d.ts +1 -0
- package/esm/network/persistent-connection.test.js +155 -0
- package/esm/network/persistent-connection.test.js.map +1 -0
- package/esm/network/session-connection.js +3 -2
- package/esm/network/session-connection.js.map +1 -1
- package/esm/network/transports/intermediate.test.d.ts +1 -0
- package/esm/network/transports/intermediate.test.js +82 -0
- package/esm/network/transports/intermediate.test.js.map +1 -0
- package/esm/network/transports/obfuscated.js +1 -1
- package/esm/network/transports/obfuscated.js.map +1 -1
- package/esm/network/transports/obfuscated.test.d.ts +1 -0
- package/esm/network/transports/obfuscated.test.js +129 -0
- package/esm/network/transports/obfuscated.test.js.map +1 -0
- package/esm/network/transports/tcp.js +1 -1
- package/esm/network/transports/tcp.js.map +1 -1
- package/esm/network/transports/tcp.test.d.ts +1 -0
- package/esm/network/transports/tcp.test.js +101 -0
- package/esm/network/transports/tcp.test.js.map +1 -0
- package/esm/network/transports/websocket.test.d.ts +1 -0
- package/esm/network/transports/websocket.test.js +89 -0
- package/esm/network/transports/websocket.test.js.map +1 -0
- package/esm/storage/abstract.d.ts +18 -0
- package/esm/storage/abstract.js.map +1 -1
- package/esm/storage/idb.d.ts +101 -0
- package/esm/storage/idb.js +454 -0
- package/esm/storage/idb.js.map +1 -0
- package/esm/storage/idb.test.d.ts +1 -0
- package/esm/storage/idb.test.js +19 -0
- package/esm/storage/idb.test.js.map +1 -0
- package/esm/storage/index.d.ts +0 -4
- package/esm/storage/index.js +0 -4
- package/esm/storage/index.js.map +1 -1
- package/esm/storage/json-file.d.ts +12 -0
- package/esm/storage/json-file.js +12 -0
- package/esm/storage/json-file.js.map +1 -1
- package/esm/storage/json.js +3 -2
- package/esm/storage/json.js.map +1 -1
- package/esm/storage/json.test.d.ts +1 -0
- package/esm/storage/json.test.js +34 -0
- package/esm/storage/json.test.js.map +1 -0
- package/esm/storage/localstorage.d.ts +12 -0
- package/esm/storage/localstorage.js +12 -0
- package/esm/storage/localstorage.js.map +1 -1
- package/esm/storage/localstorage.test.d.ts +1 -0
- package/esm/storage/localstorage.test.js +21 -0
- package/esm/storage/localstorage.test.js.map +1 -0
- package/esm/storage/memory.d.ts +12 -1
- package/esm/storage/memory.js +65 -3
- package/esm/storage/memory.js.map +1 -1
- package/esm/storage/memory.test.d.ts +1 -0
- package/esm/storage/memory.test.js +46 -0
- package/esm/storage/memory.test.js.map +1 -0
- package/esm/utils/async-lock.test.d.ts +1 -0
- package/esm/utils/async-lock.test.js +23 -0
- package/esm/utils/async-lock.test.js.map +1 -0
- package/esm/utils/bigint-utils.test.d.ts +1 -0
- package/esm/utils/bigint-utils.test.js +148 -0
- package/esm/utils/bigint-utils.test.js.map +1 -0
- package/esm/utils/buffer-utils.test.d.ts +1 -0
- package/esm/utils/buffer-utils.test.js +67 -0
- package/esm/utils/buffer-utils.test.js.map +1 -0
- package/esm/utils/condition-variable.test.d.ts +1 -0
- package/esm/utils/condition-variable.test.js +25 -0
- package/esm/utils/condition-variable.test.js.map +1 -0
- package/esm/utils/controllable-promise.d.ts +0 -5
- package/esm/utils/controllable-promise.js +0 -5
- package/esm/utils/controllable-promise.js.map +1 -1
- package/esm/utils/controllable-promise.test.d.ts +1 -0
- package/esm/utils/controllable-promise.test.js +15 -0
- package/esm/utils/controllable-promise.test.js.map +1 -0
- package/esm/utils/crypto/keys.test.d.ts +1 -0
- package/esm/utils/crypto/keys.test.js +38 -0
- package/esm/utils/crypto/keys.test.js.map +1 -0
- package/esm/utils/crypto/miller-rabin.test.d.ts +1 -0
- package/esm/utils/crypto/miller-rabin.test.js +58 -0
- package/esm/utils/crypto/miller-rabin.test.js.map +1 -0
- package/esm/utils/crypto/mtproto.test.d.ts +1 -0
- package/esm/utils/crypto/mtproto.test.js +48 -0
- package/esm/utils/crypto/mtproto.test.js.map +1 -0
- package/esm/utils/crypto/node.test.d.ts +1 -0
- package/esm/utils/crypto/node.test.js +12 -0
- package/esm/utils/crypto/node.test.js.map +1 -0
- package/esm/utils/crypto/password.test.d.ts +1 -0
- package/esm/utils/crypto/password.test.js +90 -0
- package/esm/utils/crypto/password.test.js.map +1 -0
- package/esm/utils/crypto/utils.test.d.ts +1 -0
- package/esm/utils/crypto/utils.test.js +47 -0
- package/esm/utils/crypto/utils.test.js.map +1 -0
- package/esm/utils/crypto/web.test.d.ts +1 -0
- package/esm/utils/crypto/web.test.js +15 -0
- package/esm/utils/crypto/web.test.js.map +1 -0
- package/esm/utils/deque.test.d.ts +1 -0
- package/esm/utils/deque.test.js +126 -0
- package/esm/utils/deque.test.js.map +1 -0
- package/esm/utils/function-utils.test.d.ts +1 -0
- package/esm/utils/function-utils.test.js +21 -0
- package/esm/utils/function-utils.test.js.map +1 -0
- package/esm/utils/linked-list.test.d.ts +1 -0
- package/esm/utils/linked-list.test.js +34 -0
- package/esm/utils/linked-list.test.js.map +1 -0
- package/esm/utils/links/bots.test.d.ts +1 -0
- package/esm/utils/links/bots.test.js +150 -0
- package/esm/utils/links/bots.test.js.map +1 -0
- package/esm/utils/links/chat.test.d.ts +1 -0
- package/esm/utils/links/chat.test.js +82 -0
- package/esm/utils/links/chat.test.js.map +1 -0
- package/esm/utils/links/misc.test.d.ts +1 -0
- package/esm/utils/links/misc.test.js +151 -0
- package/esm/utils/links/misc.test.js.map +1 -0
- package/esm/utils/links/proxy.test.d.ts +1 -0
- package/esm/utils/links/proxy.test.js +72 -0
- package/esm/utils/links/proxy.test.js.map +1 -0
- package/esm/utils/links/user.test.d.ts +1 -0
- package/esm/utils/links/user.test.js +61 -0
- package/esm/utils/links/user.test.js.map +1 -0
- package/esm/utils/logger.test.d.ts +1 -0
- package/esm/utils/logger.test.js +122 -0
- package/esm/utils/logger.test.js.map +1 -0
- package/esm/utils/long-utils.test.d.ts +1 -0
- package/esm/utils/long-utils.test.js +153 -0
- package/esm/utils/long-utils.test.js.map +1 -0
- package/esm/utils/lru-map.test.d.ts +1 -0
- package/esm/utils/lru-map.test.js +94 -0
- package/esm/utils/lru-map.test.js.map +1 -0
- package/esm/utils/lru-set.test.d.ts +1 -0
- package/esm/utils/lru-set.test.js +72 -0
- package/esm/utils/lru-set.test.js.map +1 -0
- package/esm/utils/peer-utils.js +3 -1
- package/esm/utils/peer-utils.js.map +1 -1
- package/esm/utils/peer-utils.test.d.ts +1 -0
- package/esm/utils/peer-utils.test.js +117 -0
- package/esm/utils/peer-utils.test.js.map +1 -0
- package/esm/utils/sorted-array.test.d.ts +1 -0
- package/esm/utils/sorted-array.test.js +64 -0
- package/esm/utils/sorted-array.test.js.map +1 -0
- package/esm/utils/string-session.test.d.ts +1 -0
- package/esm/utils/string-session.test.js +104 -0
- package/esm/utils/string-session.test.js.map +1 -0
- package/esm/utils/tl-json.test.d.ts +1 -0
- package/esm/utils/tl-json.test.js +81 -0
- package/esm/utils/tl-json.test.js.map +1 -0
- package/esm/utils/type-assertions.test.d.ts +1 -0
- package/esm/utils/type-assertions.test.js +65 -0
- package/esm/utils/type-assertions.test.js.map +1 -0
- package/package.json +20 -16
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import Long from 'long';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { defaultTestCryptoProvider } from '@mtcute/test';
|
|
4
|
+
import { hexDecode, hexDecodeToBuffer, hexEncode, utf8Decode, utf8EncodeToBuffer, } from '@mtcute/tl-runtime';
|
|
5
|
+
import { LogManager } from '../utils/index.js';
|
|
6
|
+
import { AuthKey } from './auth-key.js';
|
|
7
|
+
const authKey = new Uint8Array(256);
|
|
8
|
+
for (let i = 0; i < 256; i += 32) {
|
|
9
|
+
hexDecode(authKey.subarray(i, i + 32), '98cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4bf73c3622dec230e0');
|
|
10
|
+
}
|
|
11
|
+
describe('AuthKey', () => {
|
|
12
|
+
async function create() {
|
|
13
|
+
const logger = new LogManager();
|
|
14
|
+
const readerMap = {};
|
|
15
|
+
const crypto = await defaultTestCryptoProvider();
|
|
16
|
+
const key = new AuthKey(crypto, logger, readerMap);
|
|
17
|
+
key.setup(authKey);
|
|
18
|
+
return key;
|
|
19
|
+
}
|
|
20
|
+
const msgId = Long.fromBits(0xbeef1234, 0x1234beef, true);
|
|
21
|
+
const seqNo = 777;
|
|
22
|
+
const serverSalt = Long.fromBits(0xdeadbeef, 0xbeefdead);
|
|
23
|
+
const sessionId = Long.fromBits(0xfeedbeef, 0xbeeffeed);
|
|
24
|
+
function writeMessage(body) {
|
|
25
|
+
const buf = new Uint8Array(16 + body.length);
|
|
26
|
+
const dv = new DataView(buf.buffer);
|
|
27
|
+
dv.setInt32(0, msgId.low, true);
|
|
28
|
+
dv.setInt32(4, msgId.high, true);
|
|
29
|
+
dv.setInt32(8, seqNo, true);
|
|
30
|
+
dv.setInt32(12, body.length, true);
|
|
31
|
+
buf.set(body, 16);
|
|
32
|
+
return buf;
|
|
33
|
+
}
|
|
34
|
+
it('should calculate derivatives', async () => {
|
|
35
|
+
const key = await create();
|
|
36
|
+
expect(hexEncode(key.key)).toEqual(hexEncode(authKey));
|
|
37
|
+
expect(hexEncode(key.clientSalt)).toEqual('f73c3622dec230e098cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4b');
|
|
38
|
+
expect(hexEncode(key.serverSalt)).toEqual('98cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4bf73c3622dec230e0');
|
|
39
|
+
expect(hexEncode(key.id)).toEqual('40fa5bb7cb56a895');
|
|
40
|
+
});
|
|
41
|
+
it('should encrypt a message', async () => {
|
|
42
|
+
const message = writeMessage(utf8EncodeToBuffer('hello, world!!!!'));
|
|
43
|
+
const key = await create();
|
|
44
|
+
const msg = key.encryptMessage(message, serverSalt, sessionId);
|
|
45
|
+
expect(hexEncode(msg)).toEqual('40fa5bb7cb56a895f6f5a88914892aadf87c68031cc953ba29d68e118021f329' +
|
|
46
|
+
'be386a620d49f3ad3a50c60dcef3733f214e8cefa3e403c11d193637d4971dc1' +
|
|
47
|
+
'5db7f74b26fd16cb0e8fee30bf7e3f68858fe82927e2cd06');
|
|
48
|
+
});
|
|
49
|
+
describe('decrypt', () => {
|
|
50
|
+
async function decrypt(message) {
|
|
51
|
+
const key = await create();
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
// in this method, errors are not thrown but rather logged
|
|
54
|
+
vi.spyOn(key.log, 'warn').mockImplementation((msg, ...fmt) => reject(`${msg} : ${fmt.map((it) => JSON.stringify(it)).join(' ')}`));
|
|
55
|
+
key.decryptMessage(message, sessionId, (...args) => resolve(args));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
it('should decrypt a message', async () => {
|
|
59
|
+
const message = hexDecodeToBuffer('40fa5bb7cb56a8950c394b884f1529efc42fea22d972fea650a714ce6d2d1bdb' +
|
|
60
|
+
'3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +
|
|
61
|
+
'07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35');
|
|
62
|
+
const [decMsgId, decSeqNo, data] = await decrypt(message);
|
|
63
|
+
expect(decMsgId).toEqual(msgId);
|
|
64
|
+
expect(decSeqNo).toEqual(seqNo);
|
|
65
|
+
expect(utf8Decode(data.raw(16))).toEqual('hello, world!!!!');
|
|
66
|
+
});
|
|
67
|
+
it('should decrypt a message with padding', async () => {
|
|
68
|
+
const message = hexDecodeToBuffer('40fa5bb7cb56a8950c394b884f1529efc42fea22d972fea650a714ce6d2d1bdb' +
|
|
69
|
+
'3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +
|
|
70
|
+
'07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35' +
|
|
71
|
+
'deadbeef');
|
|
72
|
+
const [decMsgId, decSeqNo, data] = await decrypt(message);
|
|
73
|
+
expect(decMsgId).toEqual(msgId);
|
|
74
|
+
expect(decSeqNo).toEqual(seqNo);
|
|
75
|
+
expect(utf8Decode(data.raw(16))).toEqual('hello, world!!!!');
|
|
76
|
+
});
|
|
77
|
+
it('should ignore messages with invalid message key', async () => {
|
|
78
|
+
const message = hexDecodeToBuffer('40fa5bb7cb56a8950000000000000000000000000000000050a714ce6d2d1bdb' +
|
|
79
|
+
'3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +
|
|
80
|
+
'07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35');
|
|
81
|
+
await expect(() => decrypt(message)).rejects.toThrow('message with invalid messageKey');
|
|
82
|
+
});
|
|
83
|
+
it('should ignore messages with invalid session_id', async () => {
|
|
84
|
+
const message = hexDecodeToBuffer('40fa5bb7cb56a895a986a7e97f4e90aa2769b5e702c6e86f5e1e82c6ff0c6829' +
|
|
85
|
+
'2521a2ba9704fa37fb341d895cf32662c6cf47ba31cbf27c30d5c03f6c2930f4' +
|
|
86
|
+
'30fd8858b836b73fe32d4a95b8ebcdbc9ca8908f7964c40a');
|
|
87
|
+
await expect(() => decrypt(message)).rejects.toThrow('message with invalid sessionId');
|
|
88
|
+
});
|
|
89
|
+
it('should ignore messages with invalid length', async () => {
|
|
90
|
+
const messageTooLong = hexDecodeToBuffer('40fa5bb7cb56a8950d19412233dd5d24be697c73274e08fbe515cf65e0c5f70c' +
|
|
91
|
+
'ad75fd2badc18c9f999f287351144eeb1cfcaa9bea33ef5058999ad96a498306' +
|
|
92
|
+
'08d2859425685a55b21fab413bfabc42ec5da283853b28c0');
|
|
93
|
+
const messageUnaligned = hexDecodeToBuffer('40fa5bb7cb56a8957b4e4bec561eee4a5a1025bc8a35d3d0c79a3685d2b90ff0' +
|
|
94
|
+
'5f638e9c42c9fd9448b0ce8e7d49e7ea1ce458e47b825b5c7fd8ddf5b4fded46' +
|
|
95
|
+
'2a4bcc02f3ff2e89de6764d6d219f575e457fdcf8c163cdf');
|
|
96
|
+
await expect(() => decrypt(messageTooLong)).rejects.toThrow('message with invalid length: %d > %d');
|
|
97
|
+
await expect(() => decrypt(messageUnaligned)).rejects.toThrow('message with invalid length: %d is not a multiple of 4');
|
|
98
|
+
});
|
|
99
|
+
it('should ignore messages with invalid padding', async () => {
|
|
100
|
+
const message = hexDecodeToBuffer('40fa5bb7cb56a895133671d1c637a9836e2c64b4d1a0521d8a25a6416fd4dc9e' +
|
|
101
|
+
'79f9478fb837703cc9efa0a19d12143c2a26e57cb4bc64d7bc972dd8f19c53c590cc258162f44afc');
|
|
102
|
+
await expect(() => decrypt(message)).rejects.toThrow('message with invalid padding size');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=auth-key.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-key.test.js","sourceRoot":"","sources":["../../../src/network/auth-key.test.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\nimport { describe, expect, it, vi } from 'vitest'\n\nimport { defaultTestCryptoProvider } from '@mtcute/test'\nimport {\n hexDecode,\n hexDecodeToBuffer,\n hexEncode,\n TlBinaryReader,\n TlReaderMap,\n utf8Decode,\n utf8EncodeToBuffer,\n} from '@mtcute/tl-runtime'\n\nimport { LogManager } from '../utils/index.js'\nimport { AuthKey } from './auth-key.js'\n\nconst authKey = new Uint8Array(256)\n\nfor (let i = 0; i < 256; i += 32) {\n hexDecode(authKey.subarray(i, i + 32), '98cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4bf73c3622dec230e0')\n}\n\ndescribe('AuthKey', () => {\n async function create() {\n const logger = new LogManager()\n const readerMap: TlReaderMap = {}\n const crypto = await defaultTestCryptoProvider()\n\n const key = new AuthKey(crypto, logger, readerMap)\n key.setup(authKey)\n\n return key\n }\n\n const msgId = Long.fromBits(0xbeef1234, 0x1234beef, true)\n const seqNo = 777\n const serverSalt = Long.fromBits(0xdeadbeef, 0xbeefdead)\n const sessionId = Long.fromBits(0xfeedbeef, 0xbeeffeed)\n\n function writeMessage(body: Uint8Array) {\n const buf = new Uint8Array(16 + body.length)\n const dv = new DataView(buf.buffer)\n\n dv.setInt32(0, msgId.low, true)\n dv.setInt32(4, msgId.high, true)\n dv.setInt32(8, seqNo, true)\n dv.setInt32(12, body.length, true)\n buf.set(body, 16)\n\n return buf\n }\n\n it('should calculate derivatives', async () => {\n const key = await create()\n\n expect(hexEncode(key.key)).toEqual(hexEncode(authKey))\n expect(hexEncode(key.clientSalt)).toEqual('f73c3622dec230e098cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4b')\n expect(hexEncode(key.serverSalt)).toEqual('98cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4bf73c3622dec230e0')\n expect(hexEncode(key.id)).toEqual('40fa5bb7cb56a895')\n })\n\n it('should encrypt a message', async () => {\n const message = writeMessage(utf8EncodeToBuffer('hello, world!!!!'))\n\n const key = await create()\n const msg = key.encryptMessage(message, serverSalt, sessionId)\n\n expect(hexEncode(msg)).toEqual(\n '40fa5bb7cb56a895f6f5a88914892aadf87c68031cc953ba29d68e118021f329' +\n 'be386a620d49f3ad3a50c60dcef3733f214e8cefa3e403c11d193637d4971dc1' +\n '5db7f74b26fd16cb0e8fee30bf7e3f68858fe82927e2cd06',\n )\n })\n\n describe('decrypt', () => {\n async function decrypt(message: Uint8Array) {\n const key = await create()\n\n return new Promise<[Long, number, TlBinaryReader]>((resolve, reject) => {\n // in this method, errors are not thrown but rather logged\n vi.spyOn(key.log, 'warn').mockImplementation((msg, ...fmt) =>\n reject(`${msg} : ${fmt.map((it) => JSON.stringify(it)).join(' ')}`),\n )\n\n key.decryptMessage(message, sessionId, (...args) => resolve(args))\n })\n }\n\n it('should decrypt a message', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a8950c394b884f1529efc42fea22d972fea650a714ce6d2d1bdb' +\n '3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +\n '07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35',\n )\n\n const [decMsgId, decSeqNo, data] = await decrypt(message)\n\n expect(decMsgId).toEqual(msgId)\n expect(decSeqNo).toEqual(seqNo)\n expect(utf8Decode(data.raw(16))).toEqual('hello, world!!!!')\n })\n\n it('should decrypt a message with padding', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a8950c394b884f1529efc42fea22d972fea650a714ce6d2d1bdb' +\n '3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +\n '07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35' +\n 'deadbeef', // some padding (e.g. from padded transport),\n )\n\n const [decMsgId, decSeqNo, data] = await decrypt(message)\n\n expect(decMsgId).toEqual(msgId)\n expect(decSeqNo).toEqual(seqNo)\n expect(utf8Decode(data.raw(16))).toEqual('hello, world!!!!')\n })\n\n it('should ignore messages with invalid message key', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a8950000000000000000000000000000000050a714ce6d2d1bdb' +\n '3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +\n '07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35',\n )\n\n await expect(() => decrypt(message)).rejects.toThrow('message with invalid messageKey')\n })\n\n it('should ignore messages with invalid session_id', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a895a986a7e97f4e90aa2769b5e702c6e86f5e1e82c6ff0c6829' +\n '2521a2ba9704fa37fb341d895cf32662c6cf47ba31cbf27c30d5c03f6c2930f4' +\n '30fd8858b836b73fe32d4a95b8ebcdbc9ca8908f7964c40a',\n )\n\n await expect(() => decrypt(message)).rejects.toThrow('message with invalid sessionId')\n })\n\n it('should ignore messages with invalid length', async () => {\n const messageTooLong = hexDecodeToBuffer(\n '40fa5bb7cb56a8950d19412233dd5d24be697c73274e08fbe515cf65e0c5f70c' +\n 'ad75fd2badc18c9f999f287351144eeb1cfcaa9bea33ef5058999ad96a498306' +\n '08d2859425685a55b21fab413bfabc42ec5da283853b28c0',\n )\n const messageUnaligned = hexDecodeToBuffer(\n '40fa5bb7cb56a8957b4e4bec561eee4a5a1025bc8a35d3d0c79a3685d2b90ff0' +\n '5f638e9c42c9fd9448b0ce8e7d49e7ea1ce458e47b825b5c7fd8ddf5b4fded46' +\n '2a4bcc02f3ff2e89de6764d6d219f575e457fdcf8c163cdf',\n )\n\n await expect(() => decrypt(messageTooLong)).rejects.toThrow('message with invalid length: %d > %d')\n await expect(() => decrypt(messageUnaligned)).rejects.toThrow(\n 'message with invalid length: %d is not a multiple of 4',\n )\n })\n\n it('should ignore messages with invalid padding', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a895133671d1c637a9836e2c64b4d1a0521d8a25a6416fd4dc9e' +\n '79f9478fb837703cc9efa0a19d12143c2a26e57cb4bc64d7bc972dd8f19c53c590cc258162f44afc',\n )\n\n await expect(() => decrypt(message)).rejects.toThrow('message with invalid padding size')\n })\n })\n})\n"]}
|
|
@@ -11,7 +11,7 @@ export class ConfigManager {
|
|
|
11
11
|
this._listeners = [];
|
|
12
12
|
}
|
|
13
13
|
get isStale() {
|
|
14
|
-
return !this._config || this._config.expires
|
|
14
|
+
return !this._config || this._config.expires <= Date.now() / 1000;
|
|
15
15
|
}
|
|
16
16
|
update(force = false) {
|
|
17
17
|
if (!force && !this.isStale)
|
|
@@ -21,6 +21,7 @@ export class ConfigManager {
|
|
|
21
21
|
return (this._updatingPromise = this._update().then((config) => {
|
|
22
22
|
if (this._destroyed)
|
|
23
23
|
return;
|
|
24
|
+
this._updatingPromise = undefined;
|
|
24
25
|
this.setConfig(config);
|
|
25
26
|
}));
|
|
26
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../../src/network/config-manager.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACtB,YAAoB,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;QAEhD,eAAU,GAAG,KAAK,CAAA;QAOlB,eAAU,GAAuC,EAAE,CAAA;IATA,CAAC;IAW5D,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../../src/network/config-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { tl } from '@mtcute/tl'\n\n/**\n * Config manager is responsible for keeping\n * the current server configuration up-to-date\n * and providing methods to find the best DC\n * option for the current session.\n */\nexport class ConfigManager {\n constructor(private _update: () => Promise<tl.RawConfig>) {}\n\n private _destroyed = false\n private _config?: tl.RawConfig\n private _cdnConfig?: tl.RawCdnConfig\n\n private _updateTimeout?: NodeJS.Timeout\n private _updatingPromise?: Promise<void>\n\n private _listeners: ((config: tl.RawConfig) => void)[] = []\n\n get isStale(): boolean {\n return !this._config || this._config.expires <= Date.now() / 1000\n }\n\n update(force = false): Promise<void> {\n if (!force && !this.isStale) return Promise.resolve()\n if (this._updatingPromise) return this._updatingPromise\n\n return (this._updatingPromise = this._update().then((config) => {\n if (this._destroyed) return\n this._updatingPromise = undefined\n\n this.setConfig(config)\n }))\n }\n\n setConfig(config: tl.RawConfig): void {\n this._config = config\n\n if (this._updateTimeout) clearTimeout(this._updateTimeout)\n this._updateTimeout = setTimeout(\n () => void this.update().catch(() => {}),\n (config.expires - Date.now() / 1000) * 1000,\n )\n\n for (const cb of this._listeners) cb(config)\n }\n\n onConfigUpdate(cb: (config: tl.RawConfig) => void): void {\n this._listeners.push(cb)\n }\n\n offConfigUpdate(cb: (config: tl.RawConfig) => void): void {\n const idx = this._listeners.indexOf(cb)\n if (idx >= 0) this._listeners.splice(idx, 1)\n }\n\n getNow(): tl.RawConfig | undefined {\n return this._config\n }\n\n async get(): Promise<tl.RawConfig> {\n if (this.isStale) await this.update()\n\n return this._config!\n }\n\n destroy(): void {\n if (this._updateTimeout) clearTimeout(this._updateTimeout)\n this._listeners.length = 0\n this._destroyed = true\n }\n\n async findOption(params: {\n dcId: number\n allowIpv6?: boolean\n preferIpv6?: boolean\n allowMedia?: boolean\n preferMedia?: boolean\n cdn?: boolean\n }): Promise<tl.RawDcOption | undefined> {\n if (this.isStale) await this.update()\n\n const options = this._config!.dcOptions.filter((opt) => {\n if (opt.tcpoOnly) return false // unsupported\n if (opt.ipv6 && !params.allowIpv6) return false\n if (opt.mediaOnly && !params.allowMedia) return false\n if (opt.cdn && !params.cdn) return false\n\n return opt.id === params.dcId\n })\n\n if (params.preferMedia && params.preferIpv6) {\n const r = options.find((opt) => opt.mediaOnly && opt.ipv6)\n if (r) return r\n }\n\n if (params.preferMedia) {\n const r = options.find((opt) => opt.mediaOnly)\n if (r) return r\n }\n\n if (params.preferIpv6) {\n const r = options.find((opt) => opt.ipv6)\n if (r) return r\n }\n\n return options[0]\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { createStub } from '@mtcute/test';
|
|
3
|
+
import { ConfigManager } from './config-manager.js';
|
|
4
|
+
describe('ConfigManager', () => {
|
|
5
|
+
const config = createStub('config', {
|
|
6
|
+
expires: 300,
|
|
7
|
+
});
|
|
8
|
+
const getConfig = vi.fn();
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
vi.useFakeTimers();
|
|
11
|
+
vi.setSystemTime(0);
|
|
12
|
+
getConfig.mockClear().mockImplementation(() => Promise.resolve(config));
|
|
13
|
+
});
|
|
14
|
+
afterEach(() => void vi.useRealTimers());
|
|
15
|
+
it('should fetch initial config', async () => {
|
|
16
|
+
const cm = new ConfigManager(getConfig);
|
|
17
|
+
const fetchedConfig = await cm.get();
|
|
18
|
+
expect(getConfig).toHaveBeenCalledTimes(1);
|
|
19
|
+
expect(fetchedConfig).toEqual(config);
|
|
20
|
+
expect(cm.getNow()).toEqual(config);
|
|
21
|
+
});
|
|
22
|
+
it('should automatically update config', async () => {
|
|
23
|
+
const cm = new ConfigManager(getConfig);
|
|
24
|
+
await cm.update();
|
|
25
|
+
getConfig.mockImplementation(() => Promise.resolve({
|
|
26
|
+
...config,
|
|
27
|
+
expires: 600,
|
|
28
|
+
}));
|
|
29
|
+
await vi.advanceTimersByTimeAsync(301000);
|
|
30
|
+
expect(getConfig).toHaveBeenCalledTimes(2);
|
|
31
|
+
});
|
|
32
|
+
it('should correctly determine stale config', () => {
|
|
33
|
+
const cm = new ConfigManager(getConfig);
|
|
34
|
+
expect(cm.isStale).toBe(true);
|
|
35
|
+
cm.setConfig(config);
|
|
36
|
+
expect(cm.isStale).toBe(false);
|
|
37
|
+
vi.setSystemTime(300000);
|
|
38
|
+
expect(cm.isStale).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it('should not update config if not stale', async () => {
|
|
41
|
+
const cm = new ConfigManager(getConfig);
|
|
42
|
+
await cm.update();
|
|
43
|
+
getConfig.mockClear();
|
|
44
|
+
await cm.update();
|
|
45
|
+
expect(getConfig).not.toHaveBeenCalled();
|
|
46
|
+
});
|
|
47
|
+
it('should not update config twice', async () => {
|
|
48
|
+
const cm = new ConfigManager(getConfig);
|
|
49
|
+
await cm.update();
|
|
50
|
+
vi.setSystemTime(300000);
|
|
51
|
+
getConfig.mockClear();
|
|
52
|
+
await Promise.all([cm.update(), cm.update()]);
|
|
53
|
+
expect(getConfig).toHaveBeenCalledOnce();
|
|
54
|
+
});
|
|
55
|
+
it('should call listeners on config update', async () => {
|
|
56
|
+
const cm = new ConfigManager(getConfig);
|
|
57
|
+
const listener = vi.fn();
|
|
58
|
+
cm.onConfigUpdate(listener);
|
|
59
|
+
await cm.update();
|
|
60
|
+
vi.setSystemTime(300000);
|
|
61
|
+
cm.offConfigUpdate(listener);
|
|
62
|
+
await cm.update();
|
|
63
|
+
expect(listener).toHaveBeenCalledOnce();
|
|
64
|
+
expect(listener).toHaveBeenCalledWith(config);
|
|
65
|
+
});
|
|
66
|
+
it('should correctly destroy', async () => {
|
|
67
|
+
const cm = new ConfigManager(getConfig);
|
|
68
|
+
await cm.update();
|
|
69
|
+
cm.destroy();
|
|
70
|
+
getConfig.mockClear();
|
|
71
|
+
await vi.advanceTimersByTimeAsync(301000);
|
|
72
|
+
expect(getConfig).not.toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
describe('findOption', () => {
|
|
75
|
+
const useDcOptions = (options) => {
|
|
76
|
+
getConfig.mockImplementation(() => Promise.resolve({
|
|
77
|
+
...config,
|
|
78
|
+
dcOptions: options,
|
|
79
|
+
}));
|
|
80
|
+
};
|
|
81
|
+
const findOption = async (params) => {
|
|
82
|
+
const cm = new ConfigManager(getConfig);
|
|
83
|
+
await cm.update();
|
|
84
|
+
return cm.findOption(params);
|
|
85
|
+
};
|
|
86
|
+
it('should find option by dc id', async () => {
|
|
87
|
+
useDcOptions([
|
|
88
|
+
createStub('dcOption', { id: 1, ipAddress: '1.1.1.1' }),
|
|
89
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.2' }),
|
|
90
|
+
]);
|
|
91
|
+
expect(await findOption({ dcId: 1 })).toMatchObject({
|
|
92
|
+
id: 1,
|
|
93
|
+
ipAddress: '1.1.1.1',
|
|
94
|
+
});
|
|
95
|
+
expect(await findOption({ dcId: 2 })).toMatchObject({
|
|
96
|
+
id: 2,
|
|
97
|
+
ipAddress: '2.2.2.2',
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
it('should ignore tcpoOnly options', async () => {
|
|
101
|
+
useDcOptions([
|
|
102
|
+
createStub('dcOption', { id: 1, ipAddress: '1.1.1.1', tcpoOnly: true }),
|
|
103
|
+
createStub('dcOption', { id: 1, ipAddress: '1.1.1.2' }),
|
|
104
|
+
]);
|
|
105
|
+
expect(await findOption({ dcId: 1 })).toMatchObject({
|
|
106
|
+
id: 1,
|
|
107
|
+
ipAddress: '1.1.1.2',
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
it('should respect allowMedia flag', async () => {
|
|
111
|
+
useDcOptions([
|
|
112
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.2', mediaOnly: true }),
|
|
113
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),
|
|
114
|
+
]);
|
|
115
|
+
expect(await findOption({ dcId: 2 })).toMatchObject({
|
|
116
|
+
id: 2,
|
|
117
|
+
ipAddress: '2.2.2.3',
|
|
118
|
+
});
|
|
119
|
+
expect(await findOption({ dcId: 2, allowMedia: true })).toMatchObject({
|
|
120
|
+
id: 2,
|
|
121
|
+
ipAddress: '2.2.2.2',
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
it('should respect preferMedia flag', async () => {
|
|
125
|
+
useDcOptions([
|
|
126
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),
|
|
127
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.2', mediaOnly: true }),
|
|
128
|
+
]);
|
|
129
|
+
expect(await findOption({ dcId: 2 })).toMatchObject({
|
|
130
|
+
id: 2,
|
|
131
|
+
ipAddress: '2.2.2.3',
|
|
132
|
+
});
|
|
133
|
+
expect(await findOption({ dcId: 2, allowMedia: true, preferMedia: true })).toMatchObject({
|
|
134
|
+
id: 2,
|
|
135
|
+
ipAddress: '2.2.2.2',
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
it('should respect allowIpv6 flag', async () => {
|
|
139
|
+
useDcOptions([
|
|
140
|
+
createStub('dcOption', { id: 2, ipAddress: '::1', ipv6: true }),
|
|
141
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),
|
|
142
|
+
]);
|
|
143
|
+
expect(await findOption({ dcId: 2 })).toMatchObject({
|
|
144
|
+
id: 2,
|
|
145
|
+
ipAddress: '2.2.2.3',
|
|
146
|
+
});
|
|
147
|
+
expect(await findOption({ dcId: 2, allowIpv6: true })).toMatchObject({
|
|
148
|
+
id: 2,
|
|
149
|
+
ipAddress: '::1',
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
it('should respect preferIpv6 flag', async () => {
|
|
153
|
+
useDcOptions([
|
|
154
|
+
createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),
|
|
155
|
+
createStub('dcOption', { id: 2, ipAddress: '::1', ipv6: true }),
|
|
156
|
+
]);
|
|
157
|
+
expect(await findOption({ dcId: 2 })).toMatchObject({
|
|
158
|
+
id: 2,
|
|
159
|
+
ipAddress: '2.2.2.3',
|
|
160
|
+
});
|
|
161
|
+
expect(await findOption({ dcId: 2, allowIpv6: true, preferIpv6: true })).toMatchObject({
|
|
162
|
+
id: 2,
|
|
163
|
+
ipAddress: '::1',
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=config-manager.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.test.js","sourceRoot":"","sources":["../../../src/network/config-manager.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { createStub } from '@mtcute/test'\nimport { tl } from '@mtcute/tl'\n\nimport { ConfigManager } from './config-manager.js'\n\ndescribe('ConfigManager', () => {\n const config = createStub('config', {\n expires: 300,\n })\n const getConfig = vi.fn()\n\n beforeEach(() => {\n vi.useFakeTimers()\n vi.setSystemTime(0)\n getConfig.mockClear().mockImplementation(() => Promise.resolve(config))\n })\n afterEach(() => void vi.useRealTimers())\n\n it('should fetch initial config', async () => {\n const cm = new ConfigManager(getConfig)\n\n const fetchedConfig = await cm.get()\n\n expect(getConfig).toHaveBeenCalledTimes(1)\n expect(fetchedConfig).toEqual(config)\n expect(cm.getNow()).toEqual(config)\n })\n\n it('should automatically update config', async () => {\n const cm = new ConfigManager(getConfig)\n await cm.update()\n\n getConfig.mockImplementation(() =>\n Promise.resolve({\n ...config,\n expires: 600,\n }),\n )\n\n await vi.advanceTimersByTimeAsync(301_000)\n\n expect(getConfig).toHaveBeenCalledTimes(2)\n })\n\n it('should correctly determine stale config', () => {\n const cm = new ConfigManager(getConfig)\n expect(cm.isStale).toBe(true)\n\n cm.setConfig(config)\n expect(cm.isStale).toBe(false)\n\n vi.setSystemTime(300_000)\n expect(cm.isStale).toBe(true)\n })\n\n it('should not update config if not stale', async () => {\n const cm = new ConfigManager(getConfig)\n await cm.update()\n\n getConfig.mockClear()\n await cm.update()\n\n expect(getConfig).not.toHaveBeenCalled()\n })\n\n it('should not update config twice', async () => {\n const cm = new ConfigManager(getConfig)\n await cm.update()\n\n vi.setSystemTime(300_000)\n getConfig.mockClear()\n await Promise.all([cm.update(), cm.update()])\n\n expect(getConfig).toHaveBeenCalledOnce()\n })\n\n it('should call listeners on config update', async () => {\n const cm = new ConfigManager(getConfig)\n const listener = vi.fn()\n cm.onConfigUpdate(listener)\n await cm.update()\n\n vi.setSystemTime(300_000)\n cm.offConfigUpdate(listener)\n await cm.update()\n\n expect(listener).toHaveBeenCalledOnce()\n expect(listener).toHaveBeenCalledWith(config)\n })\n\n it('should correctly destroy', async () => {\n const cm = new ConfigManager(getConfig)\n await cm.update()\n\n cm.destroy()\n\n getConfig.mockClear()\n await vi.advanceTimersByTimeAsync(301_000)\n\n expect(getConfig).not.toHaveBeenCalled()\n })\n\n describe('findOption', () => {\n const useDcOptions = (options: tl.RawDcOption[]) => {\n getConfig.mockImplementation(() =>\n Promise.resolve({\n ...config,\n dcOptions: options,\n }),\n )\n }\n\n const findOption = async (params: Parameters<ConfigManager['findOption']>[0]) => {\n const cm = new ConfigManager(getConfig)\n await cm.update()\n\n return cm.findOption(params)\n }\n\n it('should find option by dc id', async () => {\n useDcOptions([\n createStub('dcOption', { id: 1, ipAddress: '1.1.1.1' }),\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.2' }),\n ])\n\n expect(await findOption({ dcId: 1 })).toMatchObject({\n id: 1,\n ipAddress: '1.1.1.1',\n })\n expect(await findOption({ dcId: 2 })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.2',\n })\n })\n\n it('should ignore tcpoOnly options', async () => {\n useDcOptions([\n createStub('dcOption', { id: 1, ipAddress: '1.1.1.1', tcpoOnly: true }),\n createStub('dcOption', { id: 1, ipAddress: '1.1.1.2' }),\n ])\n\n expect(await findOption({ dcId: 1 })).toMatchObject({\n id: 1,\n ipAddress: '1.1.1.2',\n })\n })\n\n it('should respect allowMedia flag', async () => {\n useDcOptions([\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.2', mediaOnly: true }),\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),\n ])\n\n expect(await findOption({ dcId: 2 })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.3',\n })\n\n expect(await findOption({ dcId: 2, allowMedia: true })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.2',\n })\n })\n\n it('should respect preferMedia flag', async () => {\n useDcOptions([\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.2', mediaOnly: true }),\n ])\n\n expect(await findOption({ dcId: 2 })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.3',\n })\n\n expect(await findOption({ dcId: 2, allowMedia: true, preferMedia: true })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.2',\n })\n })\n\n it('should respect allowIpv6 flag', async () => {\n useDcOptions([\n createStub('dcOption', { id: 2, ipAddress: '::1', ipv6: true }),\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),\n ])\n\n expect(await findOption({ dcId: 2 })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.3',\n })\n\n expect(await findOption({ dcId: 2, allowIpv6: true })).toMatchObject({\n id: 2,\n ipAddress: '::1',\n })\n })\n\n it('should respect preferIpv6 flag', async () => {\n useDcOptions([\n createStub('dcOption', { id: 2, ipAddress: '2.2.2.3' }),\n createStub('dcOption', { id: 2, ipAddress: '::1', ipv6: true }),\n ])\n\n expect(await findOption({ dcId: 2 })).toMatchObject({\n id: 2,\n ipAddress: '2.2.2.3',\n })\n\n expect(await findOption({ dcId: 2, allowIpv6: true, preferIpv6: true })).toMatchObject({\n id: 2,\n ipAddress: '::1',\n })\n })\n })\n})\n"]}
|
package/esm/network/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ConnectionKind, NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js';
|
|
1
|
+
export type { ConnectionKind, NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js';
|
|
2
2
|
export * from './reconnection.js';
|
|
3
3
|
export * from './session-connection.js';
|
|
4
4
|
export * from './transports/index.js';
|
package/esm/network/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/network/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA","sourcesContent":["export { ConnectionKind, NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js'\nexport * from './reconnection.js'\nexport * from './session-connection.js'\nexport * from './transports/index.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/network/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA","sourcesContent":["export type { ConnectionKind, NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js'\nexport * from './reconnection.js'\nexport * from './session-connection.js'\nexport * from './transports/index.js'\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
|
+
import { createControllablePromise } from '../utils/index.js';
|
|
2
3
|
import { MtprotoSession } from './mtproto-session.js';
|
|
3
4
|
import { SessionConnection } from './session-connection.js';
|
|
4
5
|
export class MultiSessionConnection extends EventEmitter {
|
|
@@ -92,8 +93,19 @@ export class MultiSessionConnection extends EventEmitter {
|
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
95
|
if (enforcePfsChanged) {
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
// we need to fetch new auth keys first
|
|
97
|
+
const promise = createControllablePromise();
|
|
98
|
+
this.emit('request-keys', promise);
|
|
99
|
+
promise
|
|
100
|
+
.then(() => {
|
|
101
|
+
this._connections.forEach((conn) => {
|
|
102
|
+
conn.setUsePfs(this.params.usePfs || this._enforcePfs);
|
|
103
|
+
if (connect)
|
|
104
|
+
conn.connect();
|
|
105
|
+
});
|
|
106
|
+
})
|
|
107
|
+
.catch((err) => {
|
|
108
|
+
this.emit('error', err);
|
|
97
109
|
});
|
|
98
110
|
}
|
|
99
111
|
// create new connections
|
|
@@ -106,7 +118,7 @@ export class MultiSessionConnection extends EventEmitter {
|
|
|
106
118
|
isMainConnection: this.params.isMainConnection && i === 0,
|
|
107
119
|
withUpdates: this.params.isMainConnection && this.params.isMainDcConnection && !this.params.disableUpdates,
|
|
108
120
|
}, session);
|
|
109
|
-
if (this.params.isMainConnection) {
|
|
121
|
+
if (this.params.isMainConnection && this.params.isMainDcConnection) {
|
|
110
122
|
conn.on('update', (update) => this.emit('update', update));
|
|
111
123
|
}
|
|
112
124
|
conn.on('error', (err) => this.emit('error', err, conn));
|
|
@@ -137,7 +149,8 @@ export class MultiSessionConnection extends EventEmitter {
|
|
|
137
149
|
this._connections.forEach((it) => it.flushWhenIdle());
|
|
138
150
|
});
|
|
139
151
|
this._connections.push(conn);
|
|
140
|
-
if
|
|
152
|
+
// if enforcePfsChanged, we need to connect after setting the new auth key
|
|
153
|
+
if (connect && !enforcePfsChanged)
|
|
141
154
|
conn.connect();
|
|
142
155
|
}
|
|
143
156
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-session-connection.js","sourceRoot":"","sources":["../../../src/network/multi-session-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events'\n\nimport { tl } from '@mtcute/tl'\n\nimport { Logger } from '../utils/index.js'\nimport { MtprotoSession } from './mtproto-session.js'\nimport { SessionConnection, SessionConnectionParams } from './session-connection.js'\nimport { TransportFactory } from './transports/index.js'\n\nexport class MultiSessionConnection extends EventEmitter {\n private _log: Logger\n readonly _sessions: MtprotoSession[]\n private _enforcePfs = false\n\n constructor(\n readonly params: SessionConnectionParams,\n private _count: number,\n log: Logger,\n logPrefix = '',\n ) {\n super()\n this._log = log.create('multi')\n if (logPrefix) this._log.prefix = `[${logPrefix}] `\n this._enforcePfs = _count > 1 && params.isMainConnection\n\n this._sessions = []\n this._updateConnections()\n }\n\n protected _connections: SessionConnection[] = []\n\n setCount(count: number, connect = this.params.isMainConnection): void {\n this._count = count\n\n this._updateConnections(connect)\n }\n\n private _updateSessions(): void {\n // there are two cases\n // 1. this msc is main, in which case every connection should have its own session\n // 2. this msc is not main, in which case all connections should share the same session\n // if (!this.params.isMainConnection) {\n // // case 2\n // this._log.debug(\n // 'updating sessions count: %d -> 1',\n // this._sessions.length,\n // )\n //\n // if (this._sessions.length === 0) {\n // this._sessions.push(\n // new MtprotoSession(\n // this.params.crypto,\n // this._log.create('session'),\n // this.params.readerMap,\n // this.params.writerMap,\n // ),\n // )\n // }\n //\n // // shouldn't happen, but just in case\n // while (this._sessions.length > 1) {\n // this._sessions.pop()!.reset()\n // }\n //\n // return\n // }\n\n this._log.debug('updating sessions count: %d -> %d', this._sessions.length, this._count)\n\n // case 1\n if (this._sessions.length === this._count) return\n\n if (this._sessions.length > this._count) {\n // destroy extra sessions\n for (let i = this._sessions.length - 1; i >= this._count; i--) {\n this._sessions[i].reset()\n }\n\n this._sessions.splice(this._count)\n\n return\n }\n\n while (this._sessions.length < this._count) {\n const idx = this._sessions.length\n const session = new MtprotoSession(\n this.params.crypto,\n this._log.create('session'),\n this.params.readerMap,\n this.params.writerMap,\n )\n\n // brvh\n if (idx !== 0) session._authKey = this._sessions[0]._authKey\n\n this._sessions.push(session)\n }\n }\n\n private _updateConnections(connect = false): void {\n this._updateSessions()\n if (this._connections.length === this._count) return\n\n this._log.debug('updating connections count: %d -> %d', this._connections.length, this._count)\n\n const newEnforcePfs = this._count > 1 && this.params.isMainConnection\n const enforcePfsChanged = newEnforcePfs !== this._enforcePfs\n\n if (enforcePfsChanged) {\n this._log.debug('enforcePfs changed: %s -> %s', this._enforcePfs, newEnforcePfs)\n this._enforcePfs = newEnforcePfs\n }\n\n if (this._connections.length > this._count) {\n // destroy extra connections\n for (let i = this._connections.length - 1; i >= this._count; i--) {\n this._connections[i].removeAllListeners()\n this._connections[i].destroy()\n }\n\n this._connections.splice(this._count)\n\n return\n }\n\n if (enforcePfsChanged) {\n this._connections.forEach((conn) => {\n conn.setUsePfs(this.params.usePfs || this._enforcePfs)\n })\n }\n\n // create new connections\n for (let i = this._connections.length; i < this._count; i++) {\n const session = this._sessions[i] // this.params.isMainConnection ? // :\n // this._sessions[0]\n const conn = new SessionConnection(\n {\n ...this.params,\n usePfs: this.params.usePfs || this._enforcePfs,\n isMainConnection: this.params.isMainConnection && i === 0,\n withUpdates:\n this.params.isMainConnection && this.params.isMainDcConnection && !this.params.disableUpdates,\n },\n session,\n )\n\n if (this.params.isMainConnection) {\n conn.on('update', (update) => this.emit('update', update))\n }\n conn.on('error', (err) => this.emit('error', err, conn))\n conn.on('key-change', (key) => {\n this.emit('key-change', i, key)\n\n // notify other connections\n for (const conn_ of this._connections) {\n if (conn_ === conn) continue\n conn_.onConnected()\n }\n })\n conn.on('tmp-key-change', (key, expires) => this.emit('tmp-key-change', i, key, expires))\n conn.on('auth-begin', () => {\n this._log.debug('received auth-begin from connection %d', i)\n this.emit('auth-begin', i)\n\n // we need to reset temp auth keys if there are any left\n\n this._connections.forEach((conn_) => {\n conn_._session._authKeyTemp.reset()\n if (conn_ !== conn) conn_.reconnect()\n })\n })\n conn.on('usable', () => this.emit('usable', i))\n conn.on('request-auth', () => this.emit('request-auth', i))\n conn.on('flood-done', () => {\n this._log.debug('received flood-done from connection %d', i)\n\n this._connections.forEach((it) => it.flushWhenIdle())\n })\n\n this._connections.push(conn)\n if (connect) conn.connect()\n }\n }\n\n _destroyed = false\n destroy(): void {\n this._connections.forEach((conn) => conn.destroy())\n this._sessions.forEach((sess) => sess.reset())\n this.removeAllListeners()\n\n this._destroyed = true\n }\n\n private _nextConnection = 0\n\n sendRpc<T extends tl.RpcMethod>(\n request: T,\n stack?: string,\n timeout?: number,\n abortSignal?: AbortSignal,\n ): Promise<tl.RpcCallReturn[T['_']]> {\n // if (this.params.isMainConnection) {\n // find the least loaded connection\n let min = Infinity\n let minIdx = 0\n\n for (let i = 0; i < this._connections.length; i++) {\n const conn = this._connections[i]\n const total = conn._session.queuedRpc.length + conn._session.pendingMessages.size()\n\n if (total < min) {\n min = total\n minIdx = i\n }\n }\n\n return this._connections[minIdx].sendRpc(request, stack, timeout, abortSignal)\n // }\n\n // round-robin connections\n // since they all share the same session, it doesn't matter which one we use\n // the connection chosen here will only affect the first attempt at sending\n // return this._connections[\n // this._nextConnection++ % this._connections.length\n // ].sendRpc(request, stack, timeout)\n }\n\n connect(): void {\n for (const conn of this._connections) {\n conn.connect()\n }\n }\n\n ensureConnected(): void {\n if (this._connections[0].isConnected) return\n\n this.connect()\n }\n\n setAuthKey(authKey: Uint8Array | null, temp = false, idx = 0): void {\n const session = this._sessions[idx]\n const key = temp ? session._authKeyTemp : session._authKey\n key.setup(authKey)\n }\n\n resetAuthKeys(): void {\n for (const session of this._sessions) {\n session.reset(true)\n }\n this.notifyKeyChange()\n }\n\n setInactivityTimeout(timeout?: number): void {\n this._log.debug('setting inactivity timeout to %s', timeout)\n\n // for future connections (if any)\n this.params.inactivityTimeout = timeout\n\n // for current connections\n for (const conn of this._connections) {\n conn.setInactivityTimeout(timeout)\n }\n }\n\n notifyKeyChange(): void {\n // only expected to be called on non-main connections\n const session = this._sessions[0]\n\n if (this.params.usePfs && !session._authKeyTemp.ready) {\n this._log.debug('temp auth key needed but not ready, ignoring key change')\n\n return\n }\n\n if (this._sessions[0].queuedRpc.length) {\n // there are pending requests, we need to reconnect.\n this._log.debug('notifying key change on the connection due to queued rpc')\n this._connections[0].onConnected()\n }\n\n // connection is idle, we don't need to notify it\n }\n\n requestAuth(): void {\n this._connections[0]._authorize()\n }\n\n resetSessions(): void {\n if (this.params.isMainConnection) {\n for (const conn of this._connections) {\n conn._resetSession()\n }\n } else {\n this._connections[0]._resetSession()\n }\n }\n\n changeTransport(factory: TransportFactory): void {\n this._connections.forEach((conn) => conn.changeTransport(factory))\n }\n\n getPoolSize(): number {\n return this._connections.length\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"multi-session-connection.js","sourceRoot":"","sources":["../../../src/network/multi-session-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events'\n\nimport { tl } from '@mtcute/tl'\n\nimport { createControllablePromise, Logger } from '../utils/index.js'\nimport { MtprotoSession } from './mtproto-session.js'\nimport { SessionConnection, SessionConnectionParams } from './session-connection.js'\nimport { TransportFactory } from './transports/index.js'\n\nexport class MultiSessionConnection extends EventEmitter {\n private _log: Logger\n readonly _sessions: MtprotoSession[]\n private _enforcePfs = false\n\n constructor(\n readonly params: SessionConnectionParams,\n private _count: number,\n log: Logger,\n logPrefix = '',\n ) {\n super()\n this._log = log.create('multi')\n if (logPrefix) this._log.prefix = `[${logPrefix}] `\n this._enforcePfs = _count > 1 && params.isMainConnection\n\n this._sessions = []\n this._updateConnections()\n }\n\n protected _connections: SessionConnection[] = []\n\n setCount(count: number, connect = this.params.isMainConnection): void {\n this._count = count\n\n this._updateConnections(connect)\n }\n\n private _updateSessions(): void {\n // there are two cases\n // 1. this msc is main, in which case every connection should have its own session\n // 2. this msc is not main, in which case all connections should share the same session\n // if (!this.params.isMainConnection) {\n // // case 2\n // this._log.debug(\n // 'updating sessions count: %d -> 1',\n // this._sessions.length,\n // )\n //\n // if (this._sessions.length === 0) {\n // this._sessions.push(\n // new MtprotoSession(\n // this.params.crypto,\n // this._log.create('session'),\n // this.params.readerMap,\n // this.params.writerMap,\n // ),\n // )\n // }\n //\n // // shouldn't happen, but just in case\n // while (this._sessions.length > 1) {\n // this._sessions.pop()!.reset()\n // }\n //\n // return\n // }\n\n this._log.debug('updating sessions count: %d -> %d', this._sessions.length, this._count)\n\n // case 1\n if (this._sessions.length === this._count) return\n\n if (this._sessions.length > this._count) {\n // destroy extra sessions\n for (let i = this._sessions.length - 1; i >= this._count; i--) {\n this._sessions[i].reset()\n }\n\n this._sessions.splice(this._count)\n\n return\n }\n\n while (this._sessions.length < this._count) {\n const idx = this._sessions.length\n const session = new MtprotoSession(\n this.params.crypto,\n this._log.create('session'),\n this.params.readerMap,\n this.params.writerMap,\n )\n\n // brvh\n if (idx !== 0) session._authKey = this._sessions[0]._authKey\n\n this._sessions.push(session)\n }\n }\n\n private _updateConnections(connect = false): void {\n this._updateSessions()\n if (this._connections.length === this._count) return\n\n this._log.debug('updating connections count: %d -> %d', this._connections.length, this._count)\n\n const newEnforcePfs = this._count > 1 && this.params.isMainConnection\n const enforcePfsChanged = newEnforcePfs !== this._enforcePfs\n\n if (enforcePfsChanged) {\n this._log.debug('enforcePfs changed: %s -> %s', this._enforcePfs, newEnforcePfs)\n this._enforcePfs = newEnforcePfs\n }\n\n if (this._connections.length > this._count) {\n // destroy extra connections\n for (let i = this._connections.length - 1; i >= this._count; i--) {\n this._connections[i].removeAllListeners()\n this._connections[i].destroy()\n }\n\n this._connections.splice(this._count)\n\n return\n }\n\n if (enforcePfsChanged) {\n // we need to fetch new auth keys first\n const promise = createControllablePromise<void>()\n this.emit('request-keys', promise)\n\n promise\n .then(() => {\n this._connections.forEach((conn) => {\n conn.setUsePfs(this.params.usePfs || this._enforcePfs)\n\n if (connect) conn.connect()\n })\n })\n .catch((err) => {\n this.emit('error', err)\n })\n }\n\n // create new connections\n for (let i = this._connections.length; i < this._count; i++) {\n const session = this._sessions[i] // this.params.isMainConnection ? // :\n // this._sessions[0]\n const conn = new SessionConnection(\n {\n ...this.params,\n usePfs: this.params.usePfs || this._enforcePfs,\n isMainConnection: this.params.isMainConnection && i === 0,\n withUpdates:\n this.params.isMainConnection && this.params.isMainDcConnection && !this.params.disableUpdates,\n },\n session,\n )\n\n if (this.params.isMainConnection && this.params.isMainDcConnection) {\n conn.on('update', (update) => this.emit('update', update))\n }\n conn.on('error', (err) => this.emit('error', err, conn))\n conn.on('key-change', (key) => {\n this.emit('key-change', i, key)\n\n // notify other connections\n for (const conn_ of this._connections) {\n if (conn_ === conn) continue\n conn_.onConnected()\n }\n })\n conn.on('tmp-key-change', (key, expires) => this.emit('tmp-key-change', i, key, expires))\n conn.on('auth-begin', () => {\n this._log.debug('received auth-begin from connection %d', i)\n this.emit('auth-begin', i)\n\n // we need to reset temp auth keys if there are any left\n\n this._connections.forEach((conn_) => {\n conn_._session._authKeyTemp.reset()\n if (conn_ !== conn) conn_.reconnect()\n })\n })\n conn.on('usable', () => this.emit('usable', i))\n conn.on('request-auth', () => this.emit('request-auth', i))\n conn.on('flood-done', () => {\n this._log.debug('received flood-done from connection %d', i)\n\n this._connections.forEach((it) => it.flushWhenIdle())\n })\n\n this._connections.push(conn)\n // if enforcePfsChanged, we need to connect after setting the new auth key\n if (connect && !enforcePfsChanged) conn.connect()\n }\n }\n\n _destroyed = false\n destroy(): void {\n this._connections.forEach((conn) => conn.destroy())\n this._sessions.forEach((sess) => sess.reset())\n this.removeAllListeners()\n\n this._destroyed = true\n }\n\n private _nextConnection = 0\n\n sendRpc<T extends tl.RpcMethod>(\n request: T,\n stack?: string,\n timeout?: number,\n abortSignal?: AbortSignal,\n ): Promise<tl.RpcCallReturn[T['_']]> {\n // if (this.params.isMainConnection) {\n // find the least loaded connection\n let min = Infinity\n let minIdx = 0\n\n for (let i = 0; i < this._connections.length; i++) {\n const conn = this._connections[i]\n const total = conn._session.queuedRpc.length + conn._session.pendingMessages.size()\n\n if (total < min) {\n min = total\n minIdx = i\n }\n }\n\n return this._connections[minIdx].sendRpc(request, stack, timeout, abortSignal)\n // }\n\n // round-robin connections\n // since they all share the same session, it doesn't matter which one we use\n // the connection chosen here will only affect the first attempt at sending\n // return this._connections[\n // this._nextConnection++ % this._connections.length\n // ].sendRpc(request, stack, timeout)\n }\n\n connect(): void {\n for (const conn of this._connections) {\n conn.connect()\n }\n }\n\n ensureConnected(): void {\n if (this._connections[0].isConnected) return\n\n this.connect()\n }\n\n setAuthKey(authKey: Uint8Array | null, temp = false, idx = 0): void {\n const session = this._sessions[idx]\n const key = temp ? session._authKeyTemp : session._authKey\n key.setup(authKey)\n }\n\n resetAuthKeys(): void {\n for (const session of this._sessions) {\n session.reset(true)\n }\n this.notifyKeyChange()\n }\n\n setInactivityTimeout(timeout?: number): void {\n this._log.debug('setting inactivity timeout to %s', timeout)\n\n // for future connections (if any)\n this.params.inactivityTimeout = timeout\n\n // for current connections\n for (const conn of this._connections) {\n conn.setInactivityTimeout(timeout)\n }\n }\n\n notifyKeyChange(): void {\n // only expected to be called on non-main connections\n const session = this._sessions[0]\n\n if (this.params.usePfs && !session._authKeyTemp.ready) {\n this._log.debug('temp auth key needed but not ready, ignoring key change')\n\n return\n }\n\n if (this._sessions[0].queuedRpc.length) {\n // there are pending requests, we need to reconnect.\n this._log.debug('notifying key change on the connection due to queued rpc')\n this._connections[0].onConnected()\n }\n\n // connection is idle, we don't need to notify it\n }\n\n requestAuth(): void {\n this._connections[0]._authorize()\n }\n\n resetSessions(): void {\n if (this.params.isMainConnection) {\n for (const conn of this._connections) {\n conn._resetSession()\n }\n } else {\n this._connections[0]._resetSession()\n }\n }\n\n changeTransport(factory: TransportFactory): void {\n this._connections.forEach((conn) => conn.changeTransport(factory))\n }\n\n getPoolSize(): number {\n return this._connections.length\n }\n}\n"]}
|
|
@@ -143,7 +143,7 @@ export declare class DcConnectionManager {
|
|
|
143
143
|
private _setupMulti;
|
|
144
144
|
setIsPrimary(isPrimary: boolean): void;
|
|
145
145
|
setIsPremium(isPremium: boolean): void;
|
|
146
|
-
loadKeys(): Promise<boolean>;
|
|
146
|
+
loadKeys(forcePfs?: boolean): Promise<boolean>;
|
|
147
147
|
}
|
|
148
148
|
/**
|
|
149
149
|
* Class that manages all connections to Telegram servers.
|
|
@@ -141,6 +141,12 @@ export class DcConnectionManager {
|
|
|
141
141
|
connection.on('request-auth', () => {
|
|
142
142
|
this.main.requestAuth();
|
|
143
143
|
});
|
|
144
|
+
// fucking awesome architecture, but whatever
|
|
145
|
+
connection.on('request-keys', (promise) => {
|
|
146
|
+
this.loadKeys(true)
|
|
147
|
+
.then(() => promise.resolve())
|
|
148
|
+
.catch((e) => promise.reject(e));
|
|
149
|
+
});
|
|
144
150
|
connection.on('error', (err, conn) => {
|
|
145
151
|
this.manager.params._emitError(err, conn);
|
|
146
152
|
});
|
|
@@ -149,6 +155,7 @@ export class DcConnectionManager {
|
|
|
149
155
|
if (this.isPrimary === isPrimary)
|
|
150
156
|
return;
|
|
151
157
|
this.isPrimary = isPrimary;
|
|
158
|
+
this.main.params.isMainDcConnection = isPrimary;
|
|
152
159
|
if (isPrimary) {
|
|
153
160
|
this.main.setInactivityTimeout(undefined);
|
|
154
161
|
}
|
|
@@ -161,7 +168,7 @@ export class DcConnectionManager {
|
|
|
161
168
|
this.download.setCount(this.manager._connectionCount('download', this.dcId, isPremium));
|
|
162
169
|
this.downloadSmall.setCount(this.manager._connectionCount('downloadSmall', this.dcId, isPremium));
|
|
163
170
|
}
|
|
164
|
-
async loadKeys() {
|
|
171
|
+
async loadKeys(forcePfs = false) {
|
|
165
172
|
const permanent = await this.manager._storage.getAuthKeyFor(this.dcId);
|
|
166
173
|
this.main.setAuthKey(permanent);
|
|
167
174
|
this.upload.setAuthKey(permanent);
|
|
@@ -170,7 +177,7 @@ export class DcConnectionManager {
|
|
|
170
177
|
if (!permanent) {
|
|
171
178
|
return false;
|
|
172
179
|
}
|
|
173
|
-
if (this.manager.params.usePfs) {
|
|
180
|
+
if (this.manager.params.usePfs || forcePfs) {
|
|
174
181
|
await Promise.all(this.main._sessions.map(async (_, i) => {
|
|
175
182
|
const temp = await this.manager._storage.getAuthKeyFor(this.dcId, i);
|
|
176
183
|
this.main.setAuthKey(temp, true, i);
|
|
@@ -215,7 +222,7 @@ export class NetworkManager {
|
|
|
215
222
|
_: 'initConnection',
|
|
216
223
|
deviceModel,
|
|
217
224
|
systemVersion: '1.0',
|
|
218
|
-
appVersion: '0.
|
|
225
|
+
appVersion: '0.2.0',
|
|
219
226
|
systemLangCode: 'en',
|
|
220
227
|
langPack: '',
|
|
221
228
|
langCode: 'en',
|
|
@@ -323,7 +330,7 @@ export class NetworkManager {
|
|
|
323
330
|
// shouldn't happen
|
|
324
331
|
throw new MtArgumentError('DC manager already exists');
|
|
325
332
|
}
|
|
326
|
-
const dc = new DcConnectionManager(this, defaultDcs.main.id, defaultDcs);
|
|
333
|
+
const dc = new DcConnectionManager(this, defaultDcs.main.id, defaultDcs, true);
|
|
327
334
|
this._dcConnections.set(defaultDcs.main.id, dc);
|
|
328
335
|
await this._switchPrimaryDc(dc);
|
|
329
336
|
}
|
|
@@ -390,7 +397,7 @@ export class NetworkManager {
|
|
|
390
397
|
return;
|
|
391
398
|
const options = await this._findDcOptions(newDc);
|
|
392
399
|
if (!this._dcConnections.has(newDc)) {
|
|
393
|
-
this._dcConnections.set(newDc, new DcConnectionManager(this, newDc, options));
|
|
400
|
+
this._dcConnections.set(newDc, new DcConnectionManager(this, newDc, options, true));
|
|
394
401
|
}
|
|
395
402
|
await this._storage.setDefaultDcs(options);
|
|
396
403
|
await this._switchPrimaryDc(this._dcConnections.get(newDc));
|