@mt-tl/server 0.1.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.
Potentially problematic release.
This version of @mt-tl/server might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/auth/handshake.d.ts +35 -0
- package/dist/auth/handshake.d.ts.map +1 -0
- package/dist/auth/handshake.js +208 -0
- package/dist/auth/handshake.js.map +1 -0
- package/dist/auth/nonce-store.d.ts +22 -0
- package/dist/auth/nonce-store.d.ts.map +1 -0
- package/dist/auth/nonce-store.js +23 -0
- package/dist/auth/nonce-store.js.map +1 -0
- package/dist/bootstrap.d.ts +36 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +82 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/config.d.ts +103 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -0
- package/dist/core/context.d.ts +57 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +27 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/errors.d.ts +33 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +47 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/rpc.d.ts +83 -0
- package/dist/core/rpc.d.ts.map +1 -0
- package/dist/core/rpc.js +102 -0
- package/dist/core/rpc.js.map +1 -0
- package/dist/core/updates.d.ts +56 -0
- package/dist/core/updates.d.ts.map +1 -0
- package/dist/core/updates.js +34 -0
- package/dist/core/updates.js.map +1 -0
- package/dist/create-server.d.ts +89 -0
- package/dist/create-server.d.ts.map +1 -0
- package/dist/create-server.js +109 -0
- package/dist/create-server.js.map +1 -0
- package/dist/crypto/aes-ige.d.ts +3 -0
- package/dist/crypto/aes-ige.d.ts.map +1 -0
- package/dist/crypto/aes-ige.js +55 -0
- package/dist/crypto/aes-ige.js.map +1 -0
- package/dist/crypto/dh.d.ts +21 -0
- package/dist/crypto/dh.d.ts.map +1 -0
- package/dist/crypto/dh.js +99 -0
- package/dist/crypto/dh.js.map +1 -0
- package/dist/crypto/hashes.d.ts +6 -0
- package/dist/crypto/hashes.d.ts.map +1 -0
- package/dist/crypto/hashes.js +14 -0
- package/dist/crypto/hashes.js.map +1 -0
- package/dist/crypto/msg-key.d.ts +15 -0
- package/dist/crypto/msg-key.d.ts.map +1 -0
- package/dist/crypto/msg-key.js +24 -0
- package/dist/crypto/msg-key.js.map +1 -0
- package/dist/crypto/rsa.d.ts +27 -0
- package/dist/crypto/rsa.d.ts.map +1 -0
- package/dist/crypto/rsa.js +50 -0
- package/dist/crypto/rsa.js.map +1 -0
- package/dist/dispatch/dispatcher.d.ts +72 -0
- package/dist/dispatch/dispatcher.d.ts.map +1 -0
- package/dist/dispatch/dispatcher.js +503 -0
- package/dist/dispatch/dispatcher.js.map +1 -0
- package/dist/dispatch/forwarders/in-process.d.ts +12 -0
- package/dist/dispatch/forwarders/in-process.d.ts.map +1 -0
- package/dist/dispatch/forwarders/in-process.js +15 -0
- package/dist/dispatch/forwarders/in-process.js.map +1 -0
- package/dist/dispatch/forwarders/print.d.ts +14 -0
- package/dist/dispatch/forwarders/print.d.ts.map +1 -0
- package/dist/dispatch/forwarders/print.js +23 -0
- package/dist/dispatch/forwarders/print.js.map +1 -0
- package/dist/dispatch/rpc-forwarder.d.ts +14 -0
- package/dist/dispatch/rpc-forwarder.d.ts.map +1 -0
- package/dist/dispatch/rpc-forwarder.js +2 -0
- package/dist/dispatch/rpc-forwarder.js.map +1 -0
- package/dist/dispatch/types.d.ts +32 -0
- package/dist/dispatch/types.d.ts.map +1 -0
- package/dist/dispatch/types.js +23 -0
- package/dist/dispatch/types.js.map +1 -0
- package/dist/gateway.d.ts +57 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +150 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +12 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +13 -0
- package/dist/lib.js.map +1 -0
- package/dist/server/message-pipeline.d.ts +57 -0
- package/dist/server/message-pipeline.d.ts.map +1 -0
- package/dist/server/message-pipeline.js +199 -0
- package/dist/server/message-pipeline.js.map +1 -0
- package/dist/session/inbound-tracker.d.ts +118 -0
- package/dist/session/inbound-tracker.d.ts.map +1 -0
- package/dist/session/inbound-tracker.js +170 -0
- package/dist/session/inbound-tracker.js.map +1 -0
- package/dist/session/message-id.d.ts +19 -0
- package/dist/session/message-id.d.ts.map +1 -0
- package/dist/session/message-id.js +30 -0
- package/dist/session/message-id.js.map +1 -0
- package/dist/session/salts.d.ts +51 -0
- package/dist/session/salts.d.ts.map +1 -0
- package/dist/session/salts.js +132 -0
- package/dist/session/salts.js.map +1 -0
- package/dist/session/session-manager.d.ts +18 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +43 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/storage/index.d.ts +14 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +16 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/memory.d.ts +3 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +91 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/mongo.d.ts +3 -0
- package/dist/storage/mongo.d.ts.map +1 -0
- package/dist/storage/mongo.js +175 -0
- package/dist/storage/mongo.js.map +1 -0
- package/dist/storage/types.d.ts +85 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +3 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/testkit.d.ts +11 -0
- package/dist/testkit.d.ts.map +1 -0
- package/dist/testkit.js +17 -0
- package/dist/testkit.js.map +1 -0
- package/dist/tl/codec.d.ts +37 -0
- package/dist/tl/codec.d.ts.map +1 -0
- package/dist/tl/codec.js +297 -0
- package/dist/tl/codec.js.map +1 -0
- package/dist/tl/layered-registry.d.ts +29 -0
- package/dist/tl/layered-registry.d.ts.map +1 -0
- package/dist/tl/layered-registry.js +118 -0
- package/dist/tl/layered-registry.js.map +1 -0
- package/dist/tl/protocol.d.ts +126 -0
- package/dist/tl/protocol.d.ts.map +1 -0
- package/dist/tl/protocol.js +22 -0
- package/dist/tl/protocol.js.map +1 -0
- package/dist/tl/reader.d.ts +30 -0
- package/dist/tl/reader.d.ts.map +1 -0
- package/dist/tl/reader.js +87 -0
- package/dist/tl/reader.js.map +1 -0
- package/dist/tl/registry.d.ts +39 -0
- package/dist/tl/registry.d.ts.map +1 -0
- package/dist/tl/registry.js +52 -0
- package/dist/tl/registry.js.map +1 -0
- package/dist/tl/writer.d.ts +24 -0
- package/dist/tl/writer.d.ts.map +1 -0
- package/dist/tl/writer.js +95 -0
- package/dist/tl/writer.js.map +1 -0
- package/dist/transport/connection-registry.d.ts +31 -0
- package/dist/transport/connection-registry.d.ts.map +1 -0
- package/dist/transport/connection-registry.js +84 -0
- package/dist/transport/connection-registry.js.map +1 -0
- package/dist/transport/connection.d.ts +62 -0
- package/dist/transport/connection.d.ts.map +1 -0
- package/dist/transport/connection.js +77 -0
- package/dist/transport/connection.js.map +1 -0
- package/dist/transport/framing.d.ts +39 -0
- package/dist/transport/framing.d.ts.map +1 -0
- package/dist/transport/framing.js +212 -0
- package/dist/transport/framing.js.map +1 -0
- package/dist/transport/proxy-protocol.d.ts +23 -0
- package/dist/transport/proxy-protocol.d.ts.map +1 -0
- package/dist/transport/proxy-protocol.js +108 -0
- package/dist/transport/proxy-protocol.js.map +1 -0
- package/dist/transport/server-common.d.ts +27 -0
- package/dist/transport/server-common.d.ts.map +1 -0
- package/dist/transport/server-common.js +27 -0
- package/dist/transport/server-common.js.map +1 -0
- package/dist/transport/tcp-server.d.ts +26 -0
- package/dist/transport/tcp-server.d.ts.map +1 -0
- package/dist/transport/tcp-server.js +91 -0
- package/dist/transport/tcp-server.js.map +1 -0
- package/dist/transport/ws-server.d.ts +19 -0
- package/dist/transport/ws-server.d.ts.map +1 -0
- package/dist/transport/ws-server.js +78 -0
- package/dist/transport/ws-server.js.map +1 -0
- package/dist/update-publisher.d.ts +34 -0
- package/dist/update-publisher.d.ts.map +1 -0
- package/dist/update-publisher.js +29 -0
- package/dist/update-publisher.js.map +1 -0
- package/dist/updates/mongo-update-log.d.ts +13 -0
- package/dist/updates/mongo-update-log.d.ts.map +1 -0
- package/dist/updates/mongo-update-log.js +39 -0
- package/dist/updates/mongo-update-log.js.map +1 -0
- package/dist/updates/presence-binder.d.ts +29 -0
- package/dist/updates/presence-binder.d.ts.map +1 -0
- package/dist/updates/presence-binder.js +36 -0
- package/dist/updates/presence-binder.js.map +1 -0
- package/dist/updates/presence.d.ts +31 -0
- package/dist/updates/presence.d.ts.map +1 -0
- package/dist/updates/presence.js +44 -0
- package/dist/updates/presence.js.map +1 -0
- package/dist/updates/push.d.ts +25 -0
- package/dist/updates/push.d.ts.map +1 -0
- package/dist/updates/push.js +72 -0
- package/dist/updates/push.js.map +1 -0
- package/dist/updates/redis-bus.d.ts +45 -0
- package/dist/updates/redis-bus.d.ts.map +1 -0
- package/dist/updates/redis-bus.js +59 -0
- package/dist/updates/redis-bus.js.map +1 -0
- package/dist/updates/redis-presence.d.ts +43 -0
- package/dist/updates/redis-presence.d.ts.map +1 -0
- package/dist/updates/redis-presence.js +65 -0
- package/dist/updates/redis-presence.js.map +1 -0
- package/dist/updates/render.d.ts +16 -0
- package/dist/updates/render.d.ts.map +1 -0
- package/dist/updates/render.js +46 -0
- package/dist/updates/render.js.map +1 -0
- package/dist/updates/router.d.ts +27 -0
- package/dist/updates/router.d.ts.map +1 -0
- package/dist/updates/router.js +36 -0
- package/dist/updates/router.js.map +1 -0
- package/dist/updates/types.d.ts +23 -0
- package/dist/updates/types.d.ts.map +1 -0
- package/dist/updates/types.js +2 -0
- package/dist/updates/types.js.map +1 -0
- package/dist/updates/update-bus.d.ts +29 -0
- package/dist/updates/update-bus.d.ts.map +1 -0
- package/dist/updates/update-bus.js +24 -0
- package/dist/updates/update-bus.js.map +1 -0
- package/dist/util/bytes.d.ts +12 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +46 -0
- package/dist/util/bytes.js.map +1 -0
- package/package.json +84 -0
- package/src/auth/handshake.ts +262 -0
- package/src/auth/nonce-store.ts +39 -0
- package/src/bootstrap.ts +114 -0
- package/src/config.ts +103 -0
- package/src/core/context.ts +94 -0
- package/src/core/errors.ts +52 -0
- package/src/core/index.ts +4 -0
- package/src/core/rpc.ts +165 -0
- package/src/core/updates.ts +69 -0
- package/src/create-server.ts +181 -0
- package/src/crypto/aes-ige.ts +57 -0
- package/src/crypto/dh.ts +101 -0
- package/src/crypto/hashes.ts +17 -0
- package/src/crypto/msg-key.ts +29 -0
- package/src/crypto/rsa.ts +70 -0
- package/src/dispatch/dispatcher.ts +586 -0
- package/src/dispatch/forwarders/in-process.ts +14 -0
- package/src/dispatch/forwarders/print.ts +22 -0
- package/src/dispatch/rpc-forwarder.ts +15 -0
- package/src/dispatch/types.ts +60 -0
- package/src/gateway.ts +214 -0
- package/src/index.ts +53 -0
- package/src/lib.ts +24 -0
- package/src/server/message-pipeline.ts +256 -0
- package/src/session/inbound-tracker.ts +221 -0
- package/src/session/message-id.ts +43 -0
- package/src/session/salts.ts +162 -0
- package/src/session/session-manager.ts +66 -0
- package/src/storage/index.ts +26 -0
- package/src/storage/memory.ts +101 -0
- package/src/storage/mongo.ts +215 -0
- package/src/storage/types.ts +92 -0
- package/src/testkit.ts +19 -0
- package/src/tl/codec.ts +292 -0
- package/src/tl/layered-registry.ts +132 -0
- package/src/tl/protocol.ts +146 -0
- package/src/tl/reader.ts +99 -0
- package/src/tl/registry.ts +78 -0
- package/src/tl/writer.ts +104 -0
- package/src/transport/connection-registry.ts +91 -0
- package/src/transport/connection.ts +113 -0
- package/src/transport/framing.ts +223 -0
- package/src/transport/proxy-protocol.ts +109 -0
- package/src/transport/server-common.ts +49 -0
- package/src/transport/tcp-server.ts +102 -0
- package/src/transport/ws-server.ts +94 -0
- package/src/update-publisher.ts +47 -0
- package/src/updates/mongo-update-log.ts +49 -0
- package/src/updates/presence-binder.ts +51 -0
- package/src/updates/presence.ts +61 -0
- package/src/updates/push.ts +90 -0
- package/src/updates/redis-bus.ts +86 -0
- package/src/updates/redis-presence.ts +87 -0
- package/src/updates/render.ts +53 -0
- package/src/updates/router.ts +52 -0
- package/src/updates/types.ts +24 -0
- package/src/updates/update-bus.ts +49 -0
- package/src/util/bytes.ts +49 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-pipeline.js","sourceRoot":"","sources":["../../src/server/message-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-connection inbound-message guard and state tracker.
|
|
3
|
+
*
|
|
4
|
+
* Implements the client→server half of the MTProto message-id / sequence-number
|
|
5
|
+
* rules (https://core.telegram.org/mtproto/description) and backs the
|
|
6
|
+
* `msgs_state_req` / `msgs_state_info` service messages
|
|
7
|
+
* (https://core.telegram.org/mtproto/service_messages_about_messages).
|
|
8
|
+
*
|
|
9
|
+
* A connection carries a single session's message stream, so one tracker per
|
|
10
|
+
* connection is sufficient. The tracker is purely in-memory: replay protection
|
|
11
|
+
* is per-connection-process, while the time-window check (codes 16/17) bounds
|
|
12
|
+
* cross-process replay since stale msg_ids are rejected everywhere.
|
|
13
|
+
*
|
|
14
|
+
* Sequence-number parity (34/35) and ordering (32) are enforced when `checkSeqNo`
|
|
15
|
+
* / `checkOrder` are set (gated by the `disableSeqNoCheck` config). Code 33 (seqno
|
|
16
|
+
* too high) is unreachable under serial in-order processing; code 64 (invalid
|
|
17
|
+
* container) is raised by the dispatcher. The outer envelope and each
|
|
18
|
+
* container-inner message both run through {@link InboundTracker.accept}. See
|
|
19
|
+
* docs/internals/protocol-compliance.md.
|
|
20
|
+
*/
|
|
21
|
+
/** `bad_msg_notification` error codes. 16–35 come from {@link InboundTracker.accept};
|
|
22
|
+
* 64 (invalid container) is raised by the dispatcher. */
|
|
23
|
+
export type BadMsgCode = 16 | 17 | 18 | 19 | 20 | 32 | 33 | 34 | 35 | 64;
|
|
24
|
+
/** The cached answer (`rpc_result`) to a request, for `msg_detailed_info`. */
|
|
25
|
+
export interface CachedAnswer {
|
|
26
|
+
answerMsgId: bigint;
|
|
27
|
+
bytes: number;
|
|
28
|
+
}
|
|
29
|
+
export type AcceptResult = {
|
|
30
|
+
ok: true;
|
|
31
|
+
}
|
|
32
|
+
/** Reject and reply `bad_msg_notification` with this code. */
|
|
33
|
+
| {
|
|
34
|
+
ok: false;
|
|
35
|
+
code: BadMsgCode;
|
|
36
|
+
}
|
|
37
|
+
/** Duplicate of an already-answered request — reply `msg_detailed_info`. */
|
|
38
|
+
| {
|
|
39
|
+
ok: false;
|
|
40
|
+
detailed: CachedAnswer;
|
|
41
|
+
}
|
|
42
|
+
/** Benign duplicate with no cached answer — drop silently, send no reply. */
|
|
43
|
+
| {
|
|
44
|
+
ok: false;
|
|
45
|
+
drop: true;
|
|
46
|
+
};
|
|
47
|
+
/** Classification of an inbound message, derived from its constructor id. */
|
|
48
|
+
export interface AcceptOptions {
|
|
49
|
+
/** The payload is a `msg_container` (a duplicate of one is a protocol error → 19). */
|
|
50
|
+
isContainer?: boolean;
|
|
51
|
+
/** The message requires acknowledgment (RPC queries); odd seqno expected. */
|
|
52
|
+
contentRelated?: boolean;
|
|
53
|
+
/** Enforce seqno parity (codes 34/35). */
|
|
54
|
+
checkSeqNo?: boolean;
|
|
55
|
+
/** Enforce content-seqno ordering (code 32). Only the top-level stream — inner
|
|
56
|
+
* container messages are skipped, since a resend container carries old seqnos. */
|
|
57
|
+
checkOrder?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Classify a raw payload by its leading constructor id (used to drive `accept`). */
|
|
60
|
+
export declare function messageClass(payload: Buffer): {
|
|
61
|
+
isContainer: boolean;
|
|
62
|
+
contentRelated: boolean;
|
|
63
|
+
};
|
|
64
|
+
export interface InboundTrackerOptions {
|
|
65
|
+
/** Clock in milliseconds (default `Date.now`); injectable for tests. */
|
|
66
|
+
nowMs?: () => number;
|
|
67
|
+
/** Reject msg_ids whose timestamp is more than this far in the future. */
|
|
68
|
+
futureToleranceSec?: number;
|
|
69
|
+
/** Reject msg_ids whose timestamp is more than this far in the past. */
|
|
70
|
+
pastToleranceSec?: number;
|
|
71
|
+
/** Size of the recent-msg_id window kept for dedup/state (FIFO eviction). */
|
|
72
|
+
maxTracked?: number;
|
|
73
|
+
}
|
|
74
|
+
export declare class InboundTracker {
|
|
75
|
+
private readonly received;
|
|
76
|
+
/** Insertion order, for FIFO eviction once the window is full. */
|
|
77
|
+
private readonly order;
|
|
78
|
+
/** Highest msg_id evicted from the window — anything ≤ this is "too old to verify". */
|
|
79
|
+
private evictedHigh;
|
|
80
|
+
/** Highest msg_id ever accepted (distinguishes "in range" from "too high"). */
|
|
81
|
+
private maxReceived;
|
|
82
|
+
/** Highest odd seqno of a content-related message seen (for ordering code 32). */
|
|
83
|
+
private lastContentSeqNo;
|
|
84
|
+
private readonly now;
|
|
85
|
+
private readonly futureTolerance;
|
|
86
|
+
private readonly pastTolerance;
|
|
87
|
+
private readonly maxTracked;
|
|
88
|
+
constructor(opts?: InboundTrackerOptions);
|
|
89
|
+
/**
|
|
90
|
+
* Validate and record an inbound message. Returns the `bad_msg_notification`
|
|
91
|
+
* error code if the message must be rejected, `{ drop: true }` for a benign
|
|
92
|
+
* duplicate to ignore silently, or `{ ok: true }` if it should be processed. A
|
|
93
|
+
* rejected message is NOT recorded, so the client may correct and resend it
|
|
94
|
+
* (e.g. after a `bad_server_salt`, which re-uses the same msg_id).
|
|
95
|
+
*/
|
|
96
|
+
accept(msgId: bigint, seqNo: number, opts?: AcceptOptions): AcceptResult;
|
|
97
|
+
/**
|
|
98
|
+
* Record the reply (`rpc_result`) generated for a request, so a later duplicate
|
|
99
|
+
* of that request can be answered with `msg_detailed_info` instead of dropped.
|
|
100
|
+
* No-op if the request id is no longer tracked.
|
|
101
|
+
*/
|
|
102
|
+
recordAnswer(reqMsgId: bigint, answerMsgId: bigint, bytes: number): void;
|
|
103
|
+
/**
|
|
104
|
+
* Record a received msg_id without validation. Used for messages observed
|
|
105
|
+
* inside a container (their ids are not individually validated), so that
|
|
106
|
+
* `msgs_state_req` can still report them as received.
|
|
107
|
+
*/
|
|
108
|
+
note(msgId: bigint, seqNo: number): void;
|
|
109
|
+
/**
|
|
110
|
+
* Per-id status bytes for `msgs_state_info.info` — one byte per requested id
|
|
111
|
+
* (see the spec's status-byte table). Reports received messages as state 4
|
|
112
|
+
* with the appropriate high bits, and unseen ids as 1/2/3 by position relative
|
|
113
|
+
* to the tracking window.
|
|
114
|
+
*/
|
|
115
|
+
stateOf(ids: bigint[]): Buffer;
|
|
116
|
+
private stateByte;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=inbound-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-tracker.d.ts","sourceRoot":"","sources":["../../src/session/inbound-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;0DAC0D;AAC1D,MAAM,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;AAExE,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,YAAY,GAClB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE;AACd,8DAA8D;GAC5D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE;AACjC,4EAA4E;GAC1E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE;AACvC,6EAA6E;GAC3E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAA;AAE/B,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC1B,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;uFACmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB;AAsBD,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,CAI/F;AAED,MAAM,WAAW,qBAAqB;IAClC,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;IACpB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAQD,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;IACzD,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,uFAAuF;IACvF,OAAO,CAAC,WAAW,CAAK;IACxB,+EAA+E;IAC/E,OAAO,CAAC,WAAW,CAAK;IACxB,kFAAkF;IAClF,OAAO,CAAC,gBAAgB,CAAK;IAE7B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;gBAEvB,IAAI,GAAE,qBAA0B;IAO5C;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,YAAY;IAyC5E;;;;OAIG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKxE;;;;OAIG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYxC;;;;;OAKG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM;IAK9B,OAAO,CAAC,SAAS;CAcpB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-connection inbound-message guard and state tracker.
|
|
3
|
+
*
|
|
4
|
+
* Implements the client→server half of the MTProto message-id / sequence-number
|
|
5
|
+
* rules (https://core.telegram.org/mtproto/description) and backs the
|
|
6
|
+
* `msgs_state_req` / `msgs_state_info` service messages
|
|
7
|
+
* (https://core.telegram.org/mtproto/service_messages_about_messages).
|
|
8
|
+
*
|
|
9
|
+
* A connection carries a single session's message stream, so one tracker per
|
|
10
|
+
* connection is sufficient. The tracker is purely in-memory: replay protection
|
|
11
|
+
* is per-connection-process, while the time-window check (codes 16/17) bounds
|
|
12
|
+
* cross-process replay since stale msg_ids are rejected everywhere.
|
|
13
|
+
*
|
|
14
|
+
* Sequence-number parity (34/35) and ordering (32) are enforced when `checkSeqNo`
|
|
15
|
+
* / `checkOrder` are set (gated by the `disableSeqNoCheck` config). Code 33 (seqno
|
|
16
|
+
* too high) is unreachable under serial in-order processing; code 64 (invalid
|
|
17
|
+
* container) is raised by the dispatcher. The outer envelope and each
|
|
18
|
+
* container-inner message both run through {@link InboundTracker.accept}. See
|
|
19
|
+
* docs/internals/protocol-compliance.md.
|
|
20
|
+
*/
|
|
21
|
+
// Constructor ids of client→server messages that do NOT require acknowledgment
|
|
22
|
+
// (carry an even seqno). Everything else is content-related (odd seqno).
|
|
23
|
+
const ID_MSG_CONTAINER = 0x73f1f8dc;
|
|
24
|
+
const NON_CONTENT_IDS = new Set([
|
|
25
|
+
ID_MSG_CONTAINER, // msg_container
|
|
26
|
+
0x62d6b459, // msgs_ack
|
|
27
|
+
0x7abe77ec, // ping
|
|
28
|
+
0xf3427b8c, // ping_delay_disconnect
|
|
29
|
+
0x9299359f, // http_wait
|
|
30
|
+
0x8cc0d131, // msgs_all_info
|
|
31
|
+
]);
|
|
32
|
+
/** Classify a raw payload by its leading constructor id (used to drive `accept`). */
|
|
33
|
+
export function messageClass(payload) {
|
|
34
|
+
if (payload.length < 4)
|
|
35
|
+
return { isContainer: false, contentRelated: true };
|
|
36
|
+
const id = payload.readUInt32LE(0);
|
|
37
|
+
return { isContainer: id === ID_MSG_CONTAINER, contentRelated: !NON_CONTENT_IDS.has(id) };
|
|
38
|
+
}
|
|
39
|
+
// Spec tolerances: a client msg_id encodes unix time in its high 32 bits and must
|
|
40
|
+
// be divisible by 4. Telegram ignores ids more than 30s ahead or 300s behind.
|
|
41
|
+
const FUTURE_TOLERANCE_SEC = 30;
|
|
42
|
+
const PAST_TOLERANCE_SEC = 300;
|
|
43
|
+
const MAX_TRACKED = 1024;
|
|
44
|
+
export class InboundTracker {
|
|
45
|
+
received = new Map();
|
|
46
|
+
/** Insertion order, for FIFO eviction once the window is full. */
|
|
47
|
+
order = [];
|
|
48
|
+
/** Highest msg_id evicted from the window — anything ≤ this is "too old to verify". */
|
|
49
|
+
evictedHigh = 0n;
|
|
50
|
+
/** Highest msg_id ever accepted (distinguishes "in range" from "too high"). */
|
|
51
|
+
maxReceived = 0n;
|
|
52
|
+
/** Highest odd seqno of a content-related message seen (for ordering code 32). */
|
|
53
|
+
lastContentSeqNo = -1;
|
|
54
|
+
now;
|
|
55
|
+
futureTolerance;
|
|
56
|
+
pastTolerance;
|
|
57
|
+
maxTracked;
|
|
58
|
+
constructor(opts = {}) {
|
|
59
|
+
this.now = opts.nowMs ?? (() => Date.now());
|
|
60
|
+
this.futureTolerance = opts.futureToleranceSec ?? FUTURE_TOLERANCE_SEC;
|
|
61
|
+
this.pastTolerance = opts.pastToleranceSec ?? PAST_TOLERANCE_SEC;
|
|
62
|
+
this.maxTracked = Math.max(1, opts.maxTracked ?? MAX_TRACKED);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate and record an inbound message. Returns the `bad_msg_notification`
|
|
66
|
+
* error code if the message must be rejected, `{ drop: true }` for a benign
|
|
67
|
+
* duplicate to ignore silently, or `{ ok: true }` if it should be processed. A
|
|
68
|
+
* rejected message is NOT recorded, so the client may correct and resend it
|
|
69
|
+
* (e.g. after a `bad_server_salt`, which re-uses the same msg_id).
|
|
70
|
+
*/
|
|
71
|
+
accept(msgId, seqNo, opts = {}) {
|
|
72
|
+
const { isContainer = false, contentRelated = true, checkSeqNo = false, checkOrder = false } = opts;
|
|
73
|
+
// 18: the two low bits of a client msg_id must be 0 (divisible by 4).
|
|
74
|
+
if ((msgId & 3n) !== 0n)
|
|
75
|
+
return { ok: false, code: 18 };
|
|
76
|
+
const nowSec = Math.floor(this.now() / 1000);
|
|
77
|
+
const msgSec = Number(msgId >> 32n);
|
|
78
|
+
// 16 / 17: client clock skew beyond tolerance.
|
|
79
|
+
if (msgSec < nowSec - this.pastTolerance)
|
|
80
|
+
return { ok: false, code: 16 };
|
|
81
|
+
if (msgSec > nowSec + this.futureTolerance)
|
|
82
|
+
return { ok: false, code: 17 };
|
|
83
|
+
const dup = this.received.get(msgId);
|
|
84
|
+
if (dup) {
|
|
85
|
+
// A duplicate container msg_id is a protocol error (19). For a duplicate
|
|
86
|
+
// regular message: reply `msg_detailed_info` if its answer is still cached,
|
|
87
|
+
// else drop silently — re-processing is unsafe and a bad_msg reply would
|
|
88
|
+
// wrongly make the client resync its clock/salt.
|
|
89
|
+
if (isContainer)
|
|
90
|
+
return { ok: false, code: 19 };
|
|
91
|
+
return dup.answer ? { ok: false, detailed: dup.answer } : { ok: false, drop: true };
|
|
92
|
+
}
|
|
93
|
+
// 20: older than anything we still remember — can't verify it's not a replay.
|
|
94
|
+
if (msgId <= this.evictedHigh)
|
|
95
|
+
return { ok: false, code: 20 };
|
|
96
|
+
if (checkSeqNo) {
|
|
97
|
+
const odd = seqNo % 2 === 1;
|
|
98
|
+
// 34/35: content-related messages carry an odd seqno, pure service ones even.
|
|
99
|
+
if (contentRelated && !odd)
|
|
100
|
+
return { ok: false, code: 35 };
|
|
101
|
+
if (!contentRelated && odd)
|
|
102
|
+
return { ok: false, code: 34 };
|
|
103
|
+
}
|
|
104
|
+
if (checkOrder && contentRelated) {
|
|
105
|
+
// 32: a content-related seqno must exceed every earlier one (they arrive in
|
|
106
|
+
// msg_id order). Code 33 (too high) can't occur under serial processing.
|
|
107
|
+
if (seqNo <= this.lastContentSeqNo)
|
|
108
|
+
return { ok: false, code: 32 };
|
|
109
|
+
this.lastContentSeqNo = seqNo;
|
|
110
|
+
}
|
|
111
|
+
this.note(msgId, seqNo);
|
|
112
|
+
return { ok: true };
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Record the reply (`rpc_result`) generated for a request, so a later duplicate
|
|
116
|
+
* of that request can be answered with `msg_detailed_info` instead of dropped.
|
|
117
|
+
* No-op if the request id is no longer tracked.
|
|
118
|
+
*/
|
|
119
|
+
recordAnswer(reqMsgId, answerMsgId, bytes) {
|
|
120
|
+
const e = this.received.get(reqMsgId);
|
|
121
|
+
if (e)
|
|
122
|
+
e.answer = { answerMsgId, bytes };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Record a received msg_id without validation. Used for messages observed
|
|
126
|
+
* inside a container (their ids are not individually validated), so that
|
|
127
|
+
* `msgs_state_req` can still report them as received.
|
|
128
|
+
*/
|
|
129
|
+
note(msgId, seqNo) {
|
|
130
|
+
if (this.received.has(msgId))
|
|
131
|
+
return;
|
|
132
|
+
this.received.set(msgId, { seqNo, contentRelated: seqNo % 2 === 1 });
|
|
133
|
+
this.order.push(msgId);
|
|
134
|
+
if (msgId > this.maxReceived)
|
|
135
|
+
this.maxReceived = msgId;
|
|
136
|
+
while (this.order.length > this.maxTracked) {
|
|
137
|
+
const evicted = this.order.shift();
|
|
138
|
+
this.received.delete(evicted);
|
|
139
|
+
if (evicted > this.evictedHigh)
|
|
140
|
+
this.evictedHigh = evicted;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Per-id status bytes for `msgs_state_info.info` — one byte per requested id
|
|
145
|
+
* (see the spec's status-byte table). Reports received messages as state 4
|
|
146
|
+
* with the appropriate high bits, and unseen ids as 1/2/3 by position relative
|
|
147
|
+
* to the tracking window.
|
|
148
|
+
*/
|
|
149
|
+
stateOf(ids) {
|
|
150
|
+
const nowSec = Math.floor(this.now() / 1000);
|
|
151
|
+
return Buffer.from(ids.map(id => this.stateByte(id, nowSec)));
|
|
152
|
+
}
|
|
153
|
+
stateByte(id, nowSec) {
|
|
154
|
+
const e = this.received.get(id);
|
|
155
|
+
if (e) {
|
|
156
|
+
// 4 = received. Pure service messages don't require an ack (+16);
|
|
157
|
+
// content-related queries are processed and answered (+32 +64).
|
|
158
|
+
return e.contentRelated ? 4 + 32 + 64 : 4 + 16;
|
|
159
|
+
}
|
|
160
|
+
const msgSec = Number(id >> 32n);
|
|
161
|
+
// 1 = nothing known (too old / already forgotten); 3 = too high (not yet
|
|
162
|
+
// received); 2 = within the known range but not received.
|
|
163
|
+
if (msgSec < nowSec - this.pastTolerance || id <= this.evictedHigh)
|
|
164
|
+
return 1;
|
|
165
|
+
if (id > this.maxReceived)
|
|
166
|
+
return 3;
|
|
167
|
+
return 2;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=inbound-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-tracker.js","sourceRoot":"","sources":["../../src/session/inbound-tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MTProto message-id and sequence-number generation, ported from the existing
|
|
3
|
+
* server (`mtproto-tools.generateId` + `generateMessageId`/`generateMessageSeqNo`).
|
|
4
|
+
*
|
|
5
|
+
* A message id encodes a unix timestamp in its high bits; the low 2 bits encode
|
|
6
|
+
* direction/intent: server responses end in 1, notifications in 3. Ids are kept
|
|
7
|
+
* strictly increasing per connection.
|
|
8
|
+
*/
|
|
9
|
+
export interface MsgIdState {
|
|
10
|
+
lastMessageId: bigint | null;
|
|
11
|
+
messageSeqNo: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function nextMessageId(state: MsgIdState, isNotification?: boolean): bigint;
|
|
14
|
+
/**
|
|
15
|
+
* Sequence number for an outgoing message. Content-related messages (rpc_result,
|
|
16
|
+
* updates) consume a slot and get an odd seqno; pure service messages do not.
|
|
17
|
+
*/
|
|
18
|
+
export declare function nextSeqNo(state: MsgIdState, contentRelated?: boolean): number;
|
|
19
|
+
//# sourceMappingURL=message-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-id.d.ts","sourceRoot":"","sources":["../../src/session/message-id.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,YAAY,EAAE,MAAM,CAAA;CACvB;AAUD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,UAAQ,GAAG,MAAM,CAS/E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,UAAO,GAAG,MAAM,CAI1E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
function generateId() {
|
|
3
|
+
const ticks = Date.now();
|
|
4
|
+
const timeSec = Math.floor(ticks / 1000);
|
|
5
|
+
const timeMSec = ticks % 1000;
|
|
6
|
+
const random = randomBytes(2).readUInt16LE(0);
|
|
7
|
+
return (BigInt(timeSec) << 32n) | BigInt((timeMSec << 21) | (random << 3) | 4);
|
|
8
|
+
}
|
|
9
|
+
export function nextMessageId(state, isNotification = false) {
|
|
10
|
+
let id = generateId();
|
|
11
|
+
if (state.lastMessageId !== null && id <= state.lastMessageId) {
|
|
12
|
+
id = state.lastMessageId + 1n;
|
|
13
|
+
}
|
|
14
|
+
const target = isNotification ? 3n : 1n;
|
|
15
|
+
while (id % 4n !== target)
|
|
16
|
+
id++;
|
|
17
|
+
state.lastMessageId = id;
|
|
18
|
+
return id;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sequence number for an outgoing message. Content-related messages (rpc_result,
|
|
22
|
+
* updates) consume a slot and get an odd seqno; pure service messages do not.
|
|
23
|
+
*/
|
|
24
|
+
export function nextSeqNo(state, contentRelated = true) {
|
|
25
|
+
const seq = state.messageSeqNo;
|
|
26
|
+
if (contentRelated)
|
|
27
|
+
state.messageSeqNo++;
|
|
28
|
+
return seq * 2 + (contentRelated ? 1 : 0);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=message-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-id.js","sourceRoot":"","sources":["../../src/session/message-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAezC,SAAS,UAAU;IACf,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACxB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAA;IAC7B,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IAC7C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;AAClF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAiB,EAAE,cAAc,GAAG,KAAK;IACnE,IAAI,EAAE,GAAG,UAAU,EAAE,CAAA;IACrB,IAAI,KAAK,CAAC,aAAa,KAAK,IAAI,IAAI,EAAE,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QAC5D,EAAE,GAAG,KAAK,CAAC,aAAa,GAAG,EAAE,CAAA;IACjC,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACvC,OAAO,EAAE,GAAG,EAAE,KAAK,MAAM;QAAE,EAAE,EAAE,CAAA;IAC/B,KAAK,CAAC,aAAa,GAAG,EAAE,CAAA;IACxB,OAAO,EAAE,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,cAAc,GAAG,IAAI;IAC9D,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAA;IAC9B,IAAI,cAAc;QAAE,KAAK,CAAC,YAAY,EAAE,CAAA;IACxC,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7C,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SaltRepo, SaltScheduleEntry } from '../storage/types.js';
|
|
2
|
+
export interface SaltServiceOptions {
|
|
3
|
+
/** Validity length of each salt, seconds (default 1800 = 30 min). */
|
|
4
|
+
windowSec?: number;
|
|
5
|
+
/** Spacing between consecutive window starts, seconds. Must be `<= windowSec`
|
|
6
|
+
* for overlap (default 900 = 15 min, giving two concurrently-valid salts). */
|
|
7
|
+
stepSec?: number;
|
|
8
|
+
/** Windows to keep minted ahead of the current one (default 1). */
|
|
9
|
+
prefetch?: number;
|
|
10
|
+
/** Injectable clock returning unix seconds (default `Date.now()/1000`). */
|
|
11
|
+
nowSec?: () => number;
|
|
12
|
+
}
|
|
13
|
+
/** Result of {@link SaltService.resolve}: the salt to advertise + whether the
|
|
14
|
+
* salt the client used is currently valid. */
|
|
15
|
+
export interface SaltCheck {
|
|
16
|
+
current: bigint;
|
|
17
|
+
valid: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare class SaltService {
|
|
20
|
+
private readonly repo;
|
|
21
|
+
private readonly window;
|
|
22
|
+
private readonly step;
|
|
23
|
+
private readonly prefetch;
|
|
24
|
+
private readonly now;
|
|
25
|
+
constructor(repo: SaltRepo, opts?: SaltServiceOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Seed the schedule's first window from the handshake-derived salt. Idempotent
|
|
28
|
+
* (a no-op if a schedule already exists), and wire-compatible: the first salt
|
|
29
|
+
* keeps its `xor(newNonce, serverNonce)` value.
|
|
30
|
+
*/
|
|
31
|
+
seed(authKeyId: bigint, firstSalt: bigint): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Advertise the current salt and report whether `clientSalt` is valid right
|
|
34
|
+
* now. Mints the current window (and `prefetch` successors) on demand. The
|
|
35
|
+
* decrypt path uses this to drive `bad_server_salt`.
|
|
36
|
+
*/
|
|
37
|
+
resolve(authKeyId: bigint, clientSalt: bigint): Promise<SaltCheck>;
|
|
38
|
+
/**
|
|
39
|
+
* The next `num` scheduled salts starting from the current window, minting
|
|
40
|
+
* more if the schedule is short. Backs `get_future_salts(num)`.
|
|
41
|
+
*/
|
|
42
|
+
future(authKeyId: bigint, num: number): Promise<SaltScheduleEntry[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Ensure the schedule contains the window covering `now` plus `ahead` further
|
|
45
|
+
* grid windows; return the refreshed, ascending schedule. Opportunistically
|
|
46
|
+
* prunes windows that expired more than one window ago.
|
|
47
|
+
*/
|
|
48
|
+
private ensure;
|
|
49
|
+
private windowAt;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=salts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salts.d.ts","sourceRoot":"","sources":["../../src/session/salts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAoBtE,MAAM,WAAW,kBAAkB;IAC/B,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;mFAC+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;CACxB;AAED;+CAC+C;AAC/C,MAAM,WAAW,SAAS;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,OAAO,CAAA;CACjB;AAED,qBAAa,WAAW;IAOhB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;gBAGb,IAAI,EAAE,QAAQ,EAC/B,IAAI,GAAE,kBAAuB;IAWjC;;;;OAIG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/D;;;;OAIG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IASxE;;;OAGG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAc1E;;;;OAIG;YACW,MAAM;IAyBpB,OAAO,CAAC,QAAQ;CAGnB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { toBigIntLE } from '../util/bytes.js';
|
|
3
|
+
/**
|
|
4
|
+
* Server-salt scheduler — the spec-faithful core of the salt subsystem
|
|
5
|
+
* (https://core.telegram.org/mtproto/service_messages).
|
|
6
|
+
*
|
|
7
|
+
* Each auth key gets a rolling schedule of 64-bit salts, each valid for a bounded
|
|
8
|
+
* window (~30 min) with overlap: a new salt is minted before the previous expires,
|
|
9
|
+
* so there is always a current salt and a ready successor.
|
|
10
|
+
*
|
|
11
|
+
* Windows lie on a deterministic grid anchored at the first (handshake-derived)
|
|
12
|
+
* salt's `validSince`: window `k` is `[t0 + k·step, t0 + k·step + window)`. Because
|
|
13
|
+
* the anchor is persisted and `step`/`window` are constants, every gateway node
|
|
14
|
+
* derives the same window boundaries and (via the repo's insert-if-absent
|
|
15
|
+
* semantics) converges on one salt per window — so any node validates any salt.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_WINDOW_SEC = 30 * 60;
|
|
18
|
+
const DEFAULT_STEP_SEC = 15 * 60;
|
|
19
|
+
export class SaltService {
|
|
20
|
+
repo;
|
|
21
|
+
window;
|
|
22
|
+
step;
|
|
23
|
+
prefetch;
|
|
24
|
+
now;
|
|
25
|
+
constructor(repo, opts = {}) {
|
|
26
|
+
this.repo = repo;
|
|
27
|
+
this.window = opts.windowSec ?? DEFAULT_WINDOW_SEC;
|
|
28
|
+
this.step = opts.stepSec ?? DEFAULT_STEP_SEC;
|
|
29
|
+
this.prefetch = Math.max(0, opts.prefetch ?? 1);
|
|
30
|
+
this.now = opts.nowSec ?? (() => Math.floor(Date.now() / 1000));
|
|
31
|
+
if (this.step <= 0 || this.step > this.window) {
|
|
32
|
+
throw new Error('SaltService: require 0 < stepSec <= windowSec for overlapping windows');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Seed the schedule's first window from the handshake-derived salt. Idempotent
|
|
37
|
+
* (a no-op if a schedule already exists), and wire-compatible: the first salt
|
|
38
|
+
* keeps its `xor(newNonce, serverNonce)` value.
|
|
39
|
+
*/
|
|
40
|
+
async seed(authKeyId, firstSalt) {
|
|
41
|
+
if ((await this.repo.list(authKeyId)).length)
|
|
42
|
+
return;
|
|
43
|
+
const since = this.now();
|
|
44
|
+
await this.repo.append(authKeyId, [
|
|
45
|
+
{ salt: firstSalt, validSince: since, validUntil: since + this.window },
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Advertise the current salt and report whether `clientSalt` is valid right
|
|
50
|
+
* now. Mints the current window (and `prefetch` successors) on demand. The
|
|
51
|
+
* decrypt path uses this to drive `bad_server_salt`.
|
|
52
|
+
*/
|
|
53
|
+
async resolve(authKeyId, clientSalt) {
|
|
54
|
+
const now = this.now();
|
|
55
|
+
const list = await this.ensure(authKeyId, now, this.prefetch);
|
|
56
|
+
return {
|
|
57
|
+
current: pickCurrent(list, now).salt,
|
|
58
|
+
valid: list.some(e => covers(e, now) && e.salt === clientSalt),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The next `num` scheduled salts starting from the current window, minting
|
|
63
|
+
* more if the schedule is short. Backs `get_future_salts(num)`.
|
|
64
|
+
*/
|
|
65
|
+
async future(authKeyId, num) {
|
|
66
|
+
const n = Math.max(1, num);
|
|
67
|
+
const now = this.now();
|
|
68
|
+
const list = await this.ensure(authKeyId, now, n - 1);
|
|
69
|
+
const { t0, kNow } = grid(list, now, this.step);
|
|
70
|
+
const out = [];
|
|
71
|
+
for (let k = kNow; k < kNow + n; k++) {
|
|
72
|
+
const since = t0 + k * this.step;
|
|
73
|
+
const e = list.find(x => x.validSince === since);
|
|
74
|
+
if (e)
|
|
75
|
+
out.push(e);
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Ensure the schedule contains the window covering `now` plus `ahead` further
|
|
81
|
+
* grid windows; return the refreshed, ascending schedule. Opportunistically
|
|
82
|
+
* prunes windows that expired more than one window ago.
|
|
83
|
+
*/
|
|
84
|
+
async ensure(authKeyId, now, ahead) {
|
|
85
|
+
let list = await this.repo.list(authKeyId);
|
|
86
|
+
if (!list.length) {
|
|
87
|
+
// Defensive: no handshake seed (e.g. get_future_salts on a key with no
|
|
88
|
+
// persisted schedule). Anchor a fresh grid at now.
|
|
89
|
+
await this.repo.append(authKeyId, [this.windowAt(now, randomSalt())]);
|
|
90
|
+
list = await this.repo.list(authKeyId);
|
|
91
|
+
}
|
|
92
|
+
const { t0, kNow } = grid(list, now, this.step);
|
|
93
|
+
const missing = [];
|
|
94
|
+
for (let k = kNow; k <= kNow + ahead; k++) {
|
|
95
|
+
const since = t0 + k * this.step;
|
|
96
|
+
if (!list.some(e => e.validSince === since))
|
|
97
|
+
missing.push(this.windowAt(since, randomSalt()));
|
|
98
|
+
}
|
|
99
|
+
if (missing.length) {
|
|
100
|
+
await this.repo.append(authKeyId, missing);
|
|
101
|
+
list = await this.repo.list(authKeyId);
|
|
102
|
+
}
|
|
103
|
+
// Keep one window of expired history (covers messages still in flight).
|
|
104
|
+
await this.repo.prune(authKeyId, now - this.window).catch(() => { });
|
|
105
|
+
return list;
|
|
106
|
+
}
|
|
107
|
+
windowAt(since, salt) {
|
|
108
|
+
return { salt, validSince: since, validUntil: since + this.window };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function covers(e, now) {
|
|
112
|
+
return e.validSince <= now && now < e.validUntil;
|
|
113
|
+
}
|
|
114
|
+
/** The grid anchor `t0` (first window start) and the index `kNow` of the window
|
|
115
|
+
* covering `now`. All windows sit on `t0 + k·step`, so any surviving entry is a
|
|
116
|
+
* valid anchor — pruning the first one keeps the grid aligned. */
|
|
117
|
+
function grid(list, now, step) {
|
|
118
|
+
const t0 = list[0].validSince;
|
|
119
|
+
return { t0, kNow: Math.max(0, Math.floor((now - t0) / step)) };
|
|
120
|
+
}
|
|
121
|
+
/** Newest window covering `now`; falls back to the latest entry if a gap. */
|
|
122
|
+
function pickCurrent(list, now) {
|
|
123
|
+
let best;
|
|
124
|
+
for (const e of list)
|
|
125
|
+
if (covers(e, now) && (!best || e.validSince > best.validSince))
|
|
126
|
+
best = e;
|
|
127
|
+
return best ?? list[list.length - 1];
|
|
128
|
+
}
|
|
129
|
+
function randomSalt() {
|
|
130
|
+
return toBigIntLE(randomBytes(8));
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=salts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salts.js","sourceRoot":"","sources":["../../src/session/salts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Logger } from '@mt-tl/tl';
|
|
2
|
+
import type { Connection } from '../transport/connection.js';
|
|
3
|
+
import type { Storage } from '../storage/index.js';
|
|
4
|
+
import type { Responder } from '../dispatch/types.js';
|
|
5
|
+
export interface SessionInfo {
|
|
6
|
+
sessionId: bigint;
|
|
7
|
+
authKeyId: bigint;
|
|
8
|
+
firstMsgId: bigint;
|
|
9
|
+
subject?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ensures a persisted session exists for the connection. On the first message
|
|
13
|
+
* of a new session, persists it and emits `new_session_created`. Ported from
|
|
14
|
+
* the existing `handleSessionMessage`, but the session is durable (storage),
|
|
15
|
+
* not an in-memory-only Map.
|
|
16
|
+
*/
|
|
17
|
+
export declare function ensureSession(storage: Storage, responder: Responder, conn: Connection, info: SessionInfo, log?: Logger): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/session/session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAGrD,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAC/B,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,WAAW,EACjB,GAAG,GAAE,MAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { noopLogger } from '@mt-tl/tl';
|
|
2
|
+
import { randomBigInt } from '../crypto/hashes.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ensures a persisted session exists for the connection. On the first message
|
|
5
|
+
* of a new session, persists it and emits `new_session_created`. Ported from
|
|
6
|
+
* the existing `handleSessionMessage`, but the session is durable (storage),
|
|
7
|
+
* not an in-memory-only Map.
|
|
8
|
+
*/
|
|
9
|
+
export async function ensureSession(storage, responder, conn, info, log = noopLogger) {
|
|
10
|
+
const existing = await storage.sessions.get(info.sessionId);
|
|
11
|
+
if (existing && existing.authKeyId === info.authKeyId) {
|
|
12
|
+
await storage.sessions.touch(info.sessionId);
|
|
13
|
+
conn.ctx.uniqueId = existing.uniqueId;
|
|
14
|
+
conn.ctx.apiLayer = existing.apiLayer;
|
|
15
|
+
conn.ctx.subject = existing.subject;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (existing)
|
|
19
|
+
await storage.sessions.delete(info.sessionId);
|
|
20
|
+
const uniqueId = randomBigInt(64);
|
|
21
|
+
conn.ctx.uniqueId = uniqueId;
|
|
22
|
+
conn.ctx.subject = info.subject;
|
|
23
|
+
await storage.sessions.save({
|
|
24
|
+
sessionId: info.sessionId,
|
|
25
|
+
authKeyId: info.authKeyId,
|
|
26
|
+
uniqueId,
|
|
27
|
+
apiLayer: conn.ctx.apiLayer,
|
|
28
|
+
subject: info.subject,
|
|
29
|
+
lastActivity: Date.now(),
|
|
30
|
+
});
|
|
31
|
+
log.info('session.new', {
|
|
32
|
+
sessionId: info.sessionId,
|
|
33
|
+
authKeyId: info.authKeyId,
|
|
34
|
+
subject: info.subject,
|
|
35
|
+
});
|
|
36
|
+
responder.sendEncrypted(conn, {
|
|
37
|
+
_: 'new_session_created',
|
|
38
|
+
first_msg_id: info.firstMsgId,
|
|
39
|
+
unique_id: uniqueId,
|
|
40
|
+
server_salt: conn.ctx.serverSalt ?? 0n,
|
|
41
|
+
}, { isNotification: true, contentRelated: false });
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=session-manager.js.map
|