max-account-api 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.
@@ -0,0 +1,125 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { UserAgent, HelloResponse } from './types.js';
3
+ export interface RawTransportOptions {
4
+ host?: string;
5
+ port?: number;
6
+ servername?: string;
7
+ /** Reject self-signed / mismatched certs (default true). */
8
+ rejectUnauthorized?: boolean;
9
+ connectTimeoutMs?: number;
10
+ requestTimeoutMs?: number;
11
+ /** When true, hex-dump every TX/RX frame to stderr for diagnostics. */
12
+ debug?: boolean;
13
+ }
14
+ export interface SendOptions {
15
+ /**
16
+ * If set, prepend `(<prefixInt>, <hint>, body)` to the payload — observed on
17
+ * op 17 phone-auth frames (prefixInt=-16). For op 17 hints:
18
+ * - 21 for START_AUTH
19
+ * - 17 for RESEND
20
+ */
21
+ prependOpHint?: number;
22
+ /**
23
+ * Custom prefix byte when `prependOpHint` is set. Defaults to 0xf0
24
+ * (observed on op 17 / 18 / 115). Sent as a raw byte.
25
+ */
26
+ prefixInt?: number;
27
+ /**
28
+ * Prepend a single msgpack int before the payload (no hint). Used by op 18
29
+ * verify (observed prefix = -31).
30
+ */
31
+ prependScalar?: number;
32
+ /** Override the flags byte (header offset 6). Op 17 uses 1, op 18 uses 2. */
33
+ flags?: number;
34
+ /**
35
+ * Raw bytes prepended verbatim before the msgpack body. Used by HELLO
36
+ * (`[0xf3, 0x5a]`) — a fixed "session-greeting" tag that gates mobile-only
37
+ * features server-side. Mutually exclusive with `prependOpHint` /
38
+ * `prependScalar`.
39
+ */
40
+ rawPrefix?: Buffer;
41
+ }
42
+ export declare class RawTransport extends EventEmitter {
43
+ private sock;
44
+ private seq;
45
+ private readonly pending;
46
+ private rxBuf;
47
+ private readonly opts;
48
+ constructor(opts?: RawTransportOptions);
49
+ private hexDump;
50
+ connect(): Promise<void>;
51
+ close(): void;
52
+ /**
53
+ * Op 290 — confirm a web-side QR login from this authenticated mobile
54
+ * session. This is the headless equivalent of scanning the QR with the
55
+ * MAX mobile app's camera.
56
+ *
57
+ * Pass the `qrLink` string returned by the web client's op 288 response.
58
+ * The server uses this to flip the corresponding `trackId` to
59
+ * `loginAvailable:true`, which the web client picks up via op 289 polling.
60
+ *
61
+ * Returns when the server ACKs (empty body). The actual web-side LOGIN
62
+ * issuance happens on the web WS — see {@link import('./qr-bind.js').qrBindWebSession}
63
+ * for the full flow.
64
+ *
65
+ * Wire prefix: `f0 34` (op-hint 0x34), `flags=1`.
66
+ */
67
+ confirmQrAuth(qrLink: string): Promise<void>;
68
+ /**
69
+ * Send op 19 (LOGIN) over the mobile binary transport.
70
+ *
71
+ * Reversed from MAX Android v26.15.1: the request map carries:
72
+ * { chatCacheFingerprint: <96-byte binary>, // local cache hash; zeros OK for fresh session
73
+ * exp: { chatsCountGroups: <2-byte binary> }, // server-side experiment caps
74
+ * token: <LOGIN token from op 115>,
75
+ * presenceSync: 0,
76
+ * interactive: true }
77
+ * with a 5-byte raw prefix `f0 ff ff ff 3c` and `flags=1` in the header.
78
+ *
79
+ * Returns the full LoginResponse (profile, chats, contacts, refreshed token).
80
+ * Use after HELLO + phone-auth (op 17/18 [+ 115 for 2FA]) on the same socket.
81
+ */
82
+ mobileLogin(token: string): Promise<unknown>;
83
+ /**
84
+ * Send op 6 (HELLO) using the captured Android byte template.
85
+ *
86
+ * MAX's server rejects any re-encoded HELLO whose msgpack token stream
87
+ * deviates from the captured Android-client form — even semantically
88
+ * identical maps trigger a silent TCP close. We work around this by
89
+ * shipping the exact bytes the v26.15.1 Android client sent and patching
90
+ * only the per-install identifiers (`mt_instanceid` UUID + 16-hex
91
+ * `deviceId`). `userAgent` content is therefore fixed at the template's
92
+ * values; the `userAgent` argument is ignored (kept for API parity but
93
+ * marked optional). Always emits the first frame (seq=1) on a fresh
94
+ * connection — call right after `connect()`.
95
+ */
96
+ hello(mobileDeviceId: string, mtInstanceId: string, _userAgent?: UserAgent): Promise<HelloResponse>;
97
+ request<TRes = unknown>(opcode: number, payload?: unknown, opts?: SendOptions): Promise<TRes>;
98
+ private key;
99
+ private encodeBody;
100
+ private encodeFrame;
101
+ private onData;
102
+ private handleFrame;
103
+ /**
104
+ * Decompress an LZ4-block-encoded body. The mobile binary protocol uses
105
+ * `lz4-java` `fastCompressor()` server-side (see `d2d.java`); we use the
106
+ * pure-JS `lz4js` block codec on the client. The `cof` byte from the header
107
+ * encodes the ratio `(uncompressed/compressed)+1`, which we use to size the
108
+ * output buffer with headroom.
109
+ */
110
+ private lz4Decompress;
111
+ /**
112
+ * Decode the body. Mobile-protocol responses prepend 2+ raw bytes before
113
+ * the actual msgpack map (e.g. op 6 reply: `f0 d2 … 87 <map>`; op 17 reply:
114
+ * `f3 a7 … 85 <map>`; op 18: similar). The map's trailing bytes can also
115
+ * contain "junk" the server still sends — `msgpackDecode` errors on extra
116
+ * bytes after the value. We scan offsets for a container header (fixmap /
117
+ * fixarray / map16) and use `decodeMulti` to take the FIRST value, which
118
+ * tolerates trailing data. Falls back to last stream value otherwise.
119
+ */
120
+ private decodeBody;
121
+ /** Scan `buf` for the longest msgpack str8/str16/str32 ASCII payload. */
122
+ private extractLongestString;
123
+ private onClose;
124
+ }
125
+ //# sourceMappingURL=raw-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-transport.d.ts","sourceRoot":"","sources":["../src/raw-transport.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAE7E,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiCD,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,IAAI,CAA8B;IAC1C,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;gBAEzC,IAAI,GAAE,mBAAwB;IAc1C,OAAO,CAAC,OAAO;IAcf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BxB,KAAK,IAAI,IAAI;IAUb;;;;;;;;;;;;;;OAcG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAelD;;;;;;;;;;;;OAYG;IACG,KAAK,CACT,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,SAAS,GACrB,OAAO,CAAC,aAAa,CAAC;IAmCzB,OAAO,CAAC,IAAI,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BjG,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,MAAM;IAuBd,OAAO,CAAC,WAAW;IA+CnB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAcrB;;;;;;;;OAQG;IACH,OAAO,CAAC,UAAU;IA4DlB,yEAAyE;IACzE,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,OAAO;CAQhB"}
@@ -0,0 +1,510 @@
1
+ /**
2
+ * Raw TLS transport for the MAX mobile protocol (api.oneme.ru:443).
3
+ *
4
+ * The web client uses WebSocket with JSON frames; the Android/iOS client
5
+ * uses a custom binary frame format over plain TLS — and crucially, the
6
+ * server gates phone-auth (ops 17/18) and other mobile-only flows behind
7
+ * `userAgent.deviceType === 'ANDROID'` / `'IOS'`, which the WS endpoint
8
+ * refuses (close code 1008, "deviceType forbidden").
9
+ *
10
+ * Wire format (observed via Frida hooks on Conscrypt SSLOutputStream):
11
+ *
12
+ * offset 0 : 0x0a magic
13
+ * offset 1 : direction (0 = client→server, 1 = server→client, 3 = error)
14
+ * offset 2-3 : seq (2B big-endian — wraps at 65536)
15
+ * offset 4-5 : opcode (2B big-endian — high byte is 0 for op < 256;
16
+ * non-zero for op > 255, e.g. op 290 = 0x0122)
17
+ * offset 6 : flags (observed 0 for PING/HELLO, 1 for op-17 phone-auth)
18
+ * offset 7-9 : payload length (3B big-endian)
19
+ * offset 10+ : msgpack payload
20
+ *
21
+ * Most payloads are a plain msgpack map (e.g. PING `{interactive:true}`).
22
+ * Some ops (notably op 17 phone-auth) prepend two msgpack ints to the map
23
+ * (observed `(-16, 21, {...})` for START_AUTH, `(-16, 17, {...})` for
24
+ * RESEND). We replicate the mobile behaviour by wrapping such payloads in
25
+ * a `[hint, op, body]` triplet when `prependOpHint` is set.
26
+ *
27
+ * This module ships only what the phone-auth flow needs:
28
+ * - `RawTransport.hello()` → op 6 with ANDROID userAgent
29
+ * - `RawTransport.request(op, body)` → generic request/response
30
+ * - automatic seq numbering + (op, seq) correlation
31
+ */
32
+ import * as tls from 'node:tls';
33
+ import { EventEmitter } from 'node:events';
34
+ import { encode as msgpackEncode, decodeMulti as msgpackDecodeMulti, decode as msgpackDecode } from '@msgpack/msgpack';
35
+ // @ts-expect-error — no types ship with lz4js (pure-JS LZ4 block codec).
36
+ import lz4js from 'lz4js';
37
+ import { Opcode } from './opcodes.js';
38
+ const FRAME_MAGIC = 0x0a;
39
+ const HEADER_SIZE = 10;
40
+ const DIR_CLIENT = 0;
41
+ const FLAGS_DEFAULT = 0;
42
+ const FLAGS_PHONE_AUTH = 1;
43
+ /**
44
+ * Captured byte-template of a real Android client's op 6 HELLO frame.
45
+ * Re-encoding the same map content via standard msgpack is silently dropped
46
+ * by the server (no error reply, just TCP close) — the server's parser
47
+ * appears to depend on this *exact* token stream, including bytes that look
48
+ * like JNI buffer artifacts but are part of the protocol. The only fields
49
+ * we patch are `mt_instanceid` (UUID, offset 29, 36 bytes) and `deviceId`
50
+ * (16-hex, offset 298, 16 bytes). Header seq stays 1 — HELLO is always the
51
+ * first frame on a fresh connection.
52
+ *
53
+ * Captured from MAX Android v26.15.1 (build 6690) against api.oneme.ru:443.
54
+ */
55
+ const HELLO_TEMPLATE_HEX = '0a000001000602000130f35a84ad6d745f696e7374616e63656964d92430393437366632372d663230362d343139362d383662612d656537663434643566363233a9757365724167656e748baa64657669636554797065a7414e44524f4944aa61707056657273696f6ea732362e31352e31a96f731200f322aa416e64726f6964203134a874696d657a6f6e65ad4575726f70652f4d6f73636f77a673637265656eb7343430647069200700f500313038307832313338ae70757368447500f31aa347434da461726368a67838365f3634a66c6f63616c65a27275ab6275696c644e756d626572cd1a22a900f20a4e616d65ba476f6f676c652073646b5f6770686f6e6536345f3f0012accf00144c4500a0af636c69656e74536573cf004249640ba82100f0044964b066646630393164333564346535343162';
56
+ const HELLO_TEMPLATE = Buffer.from(HELLO_TEMPLATE_HEX, 'hex');
57
+ const HELLO_MT_OFFSET = 29; // 36 chars
58
+ const HELLO_DEVICE_OFFSET = 298; // 16 chars
59
+ export class RawTransport extends EventEmitter {
60
+ sock = null;
61
+ seq = 0;
62
+ pending = new Map();
63
+ rxBuf = Buffer.alloc(0);
64
+ opts;
65
+ constructor(opts = {}) {
66
+ super();
67
+ this.opts = {
68
+ host: 'api.oneme.ru',
69
+ port: 443,
70
+ servername: opts.servername ?? opts.host ?? 'api.oneme.ru',
71
+ rejectUnauthorized: true,
72
+ connectTimeoutMs: 15_000,
73
+ requestTimeoutMs: 30_000,
74
+ debug: false,
75
+ ...opts,
76
+ };
77
+ }
78
+ hexDump(tag, buf) {
79
+ if (!this.opts.debug)
80
+ return;
81
+ const lines = [`[${tag}] ${buf.length} bytes`];
82
+ for (let off = 0; off < buf.length; off += 16) {
83
+ const chunk = buf.subarray(off, off + 16);
84
+ const hex = Array.from(chunk).map((b) => b.toString(16).padStart(2, '0')).join(' ');
85
+ const ascii = Array.from(chunk)
86
+ .map((b) => (b >= 32 && b < 127 ? String.fromCharCode(b) : '.'))
87
+ .join('');
88
+ lines.push(` ${off.toString(16).padStart(4, '0')}: ${hex.padEnd(48)} ${ascii}`);
89
+ }
90
+ process.stderr.write(lines.join('\n') + '\n');
91
+ }
92
+ connect() {
93
+ return new Promise((resolve, reject) => {
94
+ const sock = tls.connect({
95
+ host: this.opts.host,
96
+ port: this.opts.port,
97
+ servername: this.opts.servername,
98
+ rejectUnauthorized: this.opts.rejectUnauthorized,
99
+ // Mobile clients negotiate plain TLS (no ALPN preference observed).
100
+ });
101
+ this.sock = sock;
102
+ const to = setTimeout(() => {
103
+ sock.destroy(new Error('TLS connect timeout'));
104
+ }, this.opts.connectTimeoutMs);
105
+ sock.once('secureConnect', () => {
106
+ clearTimeout(to);
107
+ this.emit('open');
108
+ resolve();
109
+ });
110
+ sock.on('data', (chunk) => this.onData(typeof chunk === 'string' ? Buffer.from(chunk) : chunk));
111
+ sock.on('error', (e) => {
112
+ clearTimeout(to);
113
+ this.emit('error', e);
114
+ reject(e);
115
+ });
116
+ sock.on('close', () => this.onClose());
117
+ });
118
+ }
119
+ close() {
120
+ this.sock?.end();
121
+ this.sock = null;
122
+ for (const [k, p] of this.pending) {
123
+ clearTimeout(p.timer);
124
+ p.reject(new Error('Transport closed'));
125
+ this.pending.delete(k);
126
+ }
127
+ }
128
+ /**
129
+ * Op 290 — confirm a web-side QR login from this authenticated mobile
130
+ * session. This is the headless equivalent of scanning the QR with the
131
+ * MAX mobile app's camera.
132
+ *
133
+ * Pass the `qrLink` string returned by the web client's op 288 response.
134
+ * The server uses this to flip the corresponding `trackId` to
135
+ * `loginAvailable:true`, which the web client picks up via op 289 polling.
136
+ *
137
+ * Returns when the server ACKs (empty body). The actual web-side LOGIN
138
+ * issuance happens on the web WS — see {@link import('./qr-bind.js').qrBindWebSession}
139
+ * for the full flow.
140
+ *
141
+ * Wire prefix: `f0 34` (op-hint 0x34), `flags=1`.
142
+ */
143
+ async confirmQrAuth(qrLink) {
144
+ const req = { qrLink };
145
+ await this.request(Opcode.QR_CONFIRM, req, { prependOpHint: 0x34, flags: 1 });
146
+ }
147
+ /**
148
+ * Send op 19 (LOGIN) over the mobile binary transport.
149
+ *
150
+ * Reversed from MAX Android v26.15.1: the request map carries:
151
+ * { chatCacheFingerprint: <96-byte binary>, // local cache hash; zeros OK for fresh session
152
+ * exp: { chatsCountGroups: <2-byte binary> }, // server-side experiment caps
153
+ * token: <LOGIN token from op 115>,
154
+ * presenceSync: 0,
155
+ * interactive: true }
156
+ * with a 5-byte raw prefix `f0 ff ff ff 3c` and `flags=1` in the header.
157
+ *
158
+ * Returns the full LoginResponse (profile, chats, contacts, refreshed token).
159
+ * Use after HELLO + phone-auth (op 17/18 [+ 115 for 2FA]) on the same socket.
160
+ */
161
+ async mobileLogin(token) {
162
+ if (!this.sock || this.sock.destroyed)
163
+ throw new Error('RawTransport not connected');
164
+ const payload = {
165
+ chatCacheFingerprint: Buffer.alloc(96), // 96-byte zero binary for fresh session
166
+ exp: { chatsCountGroups: Buffer.from([0x09, 0x32]) },
167
+ token,
168
+ presenceSync: 0,
169
+ interactive: true,
170
+ };
171
+ return this.request(19, payload, {
172
+ flags: 1,
173
+ rawPrefix: Buffer.from([0xf0, 0xff, 0xff, 0xff, 0x3c]),
174
+ });
175
+ }
176
+ /**
177
+ * Send op 6 (HELLO) using the captured Android byte template.
178
+ *
179
+ * MAX's server rejects any re-encoded HELLO whose msgpack token stream
180
+ * deviates from the captured Android-client form — even semantically
181
+ * identical maps trigger a silent TCP close. We work around this by
182
+ * shipping the exact bytes the v26.15.1 Android client sent and patching
183
+ * only the per-install identifiers (`mt_instanceid` UUID + 16-hex
184
+ * `deviceId`). `userAgent` content is therefore fixed at the template's
185
+ * values; the `userAgent` argument is ignored (kept for API parity but
186
+ * marked optional). Always emits the first frame (seq=1) on a fresh
187
+ * connection — call right after `connect()`.
188
+ */
189
+ async hello(mobileDeviceId, mtInstanceId, _userAgent) {
190
+ if (!this.sock || this.sock.destroyed)
191
+ throw new Error('RawTransport not connected');
192
+ if (!/^[0-9a-f]{16}$/.test(mobileDeviceId)) {
193
+ throw new Error('hello(): mobileDeviceId must be 16 lowercase hex chars');
194
+ }
195
+ if (mtInstanceId.length !== 36) {
196
+ throw new Error('hello(): mtInstanceId must be a 36-char UUID string');
197
+ }
198
+ const frame = Buffer.from(HELLO_TEMPLATE);
199
+ Buffer.from(mtInstanceId, 'utf-8').copy(frame, HELLO_MT_OFFSET);
200
+ Buffer.from(mobileDeviceId, 'utf-8').copy(frame, HELLO_DEVICE_OFFSET);
201
+ // Sync our seq counter with the template (1) so subsequent ops get 2, 3, …
202
+ this.seq = 1;
203
+ const seq = 1;
204
+ this.hexDump('TX op=6 (HELLO template)', frame);
205
+ return new Promise((resolve, reject) => {
206
+ const timer = setTimeout(() => {
207
+ this.pending.delete(this.key(6, seq));
208
+ reject(new Error('HELLO timeout'));
209
+ }, this.opts.requestTimeoutMs);
210
+ this.pending.set(this.key(6, seq), {
211
+ resolve: (v) => resolve(v),
212
+ reject,
213
+ timer,
214
+ });
215
+ this.sock.write(frame, (err) => {
216
+ if (err) {
217
+ clearTimeout(timer);
218
+ this.pending.delete(this.key(6, seq));
219
+ reject(err);
220
+ }
221
+ });
222
+ });
223
+ }
224
+ request(opcode, payload, opts = {}) {
225
+ if (!this.sock || this.sock.destroyed) {
226
+ return Promise.reject(new Error('RawTransport not connected'));
227
+ }
228
+ const seq = (++this.seq) & 0xffff;
229
+ const body = this.encodeBody(opcode, payload, opts);
230
+ let flags = FLAGS_DEFAULT;
231
+ if (opts.flags !== undefined)
232
+ flags = opts.flags;
233
+ else if (opts.prependOpHint !== undefined)
234
+ flags = FLAGS_PHONE_AUTH;
235
+ const frame = this.encodeFrame(seq, opcode, flags, body);
236
+ this.hexDump(`TX op=${opcode} seq=${seq} flags=${flags}`, frame);
237
+ return new Promise((resolve, reject) => {
238
+ const timer = setTimeout(() => {
239
+ this.pending.delete(this.key(opcode, seq));
240
+ reject(new Error(`Request timeout: op=${opcode} seq=${seq}`));
241
+ }, this.opts.requestTimeoutMs);
242
+ this.pending.set(this.key(opcode, seq), {
243
+ resolve: (v) => resolve(v),
244
+ reject,
245
+ timer,
246
+ });
247
+ this.sock.write(frame, (err) => {
248
+ if (err) {
249
+ clearTimeout(timer);
250
+ this.pending.delete(this.key(opcode, seq));
251
+ reject(err);
252
+ }
253
+ });
254
+ });
255
+ }
256
+ key(op, seq) {
257
+ return `${op}:${seq}`;
258
+ }
259
+ encodeBody(_op, payload, opts) {
260
+ if (payload === undefined)
261
+ return Buffer.alloc(0);
262
+ const body = Buffer.from(msgpackEncode(payload));
263
+ if (opts.rawPrefix !== undefined) {
264
+ return Buffer.concat([opts.rawPrefix, body]);
265
+ }
266
+ if (opts.prependOpHint !== undefined) {
267
+ // Observed wire prefix: 2 raw bytes [0xf0, <hint>]. The first byte
268
+ // is fixed (0xf0); the second is an op-specific subtype byte and is
269
+ // NOT msgpack-encoded — values >0x7f appear verbatim (e.g. 0xad on op 18).
270
+ const prefixByte = (opts.prefixInt ?? 0xf0) & 0xff;
271
+ const hintByte = opts.prependOpHint & 0xff;
272
+ return Buffer.concat([Buffer.from([prefixByte, hintByte]), body]);
273
+ }
274
+ if (opts.prependScalar !== undefined) {
275
+ return Buffer.concat([Buffer.from(msgpackEncode(opts.prependScalar)), body]);
276
+ }
277
+ return body;
278
+ }
279
+ encodeFrame(seq, op, flags, body) {
280
+ const buf = Buffer.alloc(HEADER_SIZE + body.length);
281
+ buf[0] = FRAME_MAGIC;
282
+ buf[1] = DIR_CLIENT;
283
+ buf[2] = (seq >> 8) & 0xff;
284
+ buf[3] = seq & 0xff;
285
+ buf[4] = (op >> 8) & 0xff;
286
+ buf[5] = op & 0xff;
287
+ buf[6] = flags & 0xff;
288
+ buf[7] = (body.length >> 16) & 0xff;
289
+ buf[8] = (body.length >> 8) & 0xff;
290
+ buf[9] = body.length & 0xff;
291
+ body.copy(buf, HEADER_SIZE);
292
+ return buf;
293
+ }
294
+ onData(chunk) {
295
+ this.rxBuf = this.rxBuf.length === 0 ? chunk : Buffer.concat([this.rxBuf, chunk]);
296
+ while (this.rxBuf.length >= HEADER_SIZE) {
297
+ const magic = this.rxBuf[0];
298
+ if (magic !== FRAME_MAGIC) {
299
+ this.emit('error', new Error(`Bad frame magic: 0x${magic.toString(16)}`));
300
+ this.rxBuf = Buffer.alloc(0);
301
+ return;
302
+ }
303
+ const dir = this.rxBuf[1];
304
+ const seq = (this.rxBuf[2] << 8) | this.rxBuf[3];
305
+ const op = (this.rxBuf[4] << 8) | this.rxBuf[5];
306
+ const flags = this.rxBuf[6];
307
+ const len = (this.rxBuf[7] << 16) | (this.rxBuf[8] << 8) | this.rxBuf[9];
308
+ if (this.rxBuf.length < HEADER_SIZE + len)
309
+ return; // wait for more
310
+ const fullFrame = this.rxBuf.subarray(0, HEADER_SIZE + len);
311
+ const body = this.rxBuf.subarray(HEADER_SIZE, HEADER_SIZE + len);
312
+ this.hexDump(`RX op=${op} seq=${seq} flags=${flags}`, fullFrame);
313
+ this.rxBuf = this.rxBuf.subarray(HEADER_SIZE + len);
314
+ this.handleFrame(dir, seq, op, flags, body);
315
+ }
316
+ }
317
+ handleFrame(dir, seq, op, flags, body) {
318
+ let payload = undefined;
319
+ if (body.length > 0) {
320
+ // `flags` is the `cof` byte (compress-or-flag): when non-zero the
321
+ // mobile binary protocol stores LZ4-compressed bytes after the header.
322
+ // The Android client encodes the ratio as `(uncompressed/compressed)+1`
323
+ // so we use it to size the decompression target generously, then trim.
324
+ let workingBody = body;
325
+ if (flags !== 0) {
326
+ try {
327
+ workingBody = this.lz4Decompress(body, flags);
328
+ }
329
+ catch (e) {
330
+ this.emit('error', new Error(`LZ4 decompress fail op=${op}: ${e.message}`));
331
+ // Fall back to raw bytes — extractLongestString may still find a token.
332
+ workingBody = body;
333
+ }
334
+ }
335
+ try {
336
+ payload = this.decodeBody(workingBody);
337
+ }
338
+ catch (e) {
339
+ this.emit('error', new Error(`msgpack decode fail op=${op}: ${e.message}`));
340
+ return;
341
+ }
342
+ }
343
+ this.emit('frame', { dir, seq, op, flags, payload });
344
+ if (dir === DIR_CLIENT) {
345
+ // echoed our own frame? unlikely on TLS but skip just in case
346
+ return;
347
+ }
348
+ // dir = server → either response to our request or server-pushed event.
349
+ const p = this.pending.get(this.key(op, seq));
350
+ if (p) {
351
+ clearTimeout(p.timer);
352
+ this.pending.delete(this.key(op, seq));
353
+ if (payload && typeof payload === 'object' && payload.error) {
354
+ p.reject(new Error(`Server error: ${payload.error}`));
355
+ }
356
+ else {
357
+ p.resolve(payload);
358
+ }
359
+ return;
360
+ }
361
+ this.emit('push', { seq, op, payload });
362
+ }
363
+ /**
364
+ * Decompress an LZ4-block-encoded body. The mobile binary protocol uses
365
+ * `lz4-java` `fastCompressor()` server-side (see `d2d.java`); we use the
366
+ * pure-JS `lz4js` block codec on the client. The `cof` byte from the header
367
+ * encodes the ratio `(uncompressed/compressed)+1`, which we use to size the
368
+ * output buffer with headroom.
369
+ */
370
+ lz4Decompress(body, cof) {
371
+ // Headroom factor: cof=1 means ratio<2 (low compression), cof=N means up
372
+ // to (N-1)x. Use (cof+2)x + 1KB padding for safety; lz4js writes only the
373
+ // actual decompressed bytes and returns the length.
374
+ const headroom = Math.max(cof, 2) + 2;
375
+ const estSize = body.length * headroom + 1024;
376
+ const out = Buffer.alloc(estSize);
377
+ const inU8 = body instanceof Uint8Array ? body : new Uint8Array(body);
378
+ const written = lz4js.decompressBlock(inU8, out, 0, body.length, 0);
379
+ return out.subarray(0, written);
380
+ }
381
+ /**
382
+ * Decode the body. Mobile-protocol responses prepend 2+ raw bytes before
383
+ * the actual msgpack map (e.g. op 6 reply: `f0 d2 … 87 <map>`; op 17 reply:
384
+ * `f3 a7 … 85 <map>`; op 18: similar). The map's trailing bytes can also
385
+ * contain "junk" the server still sends — `msgpackDecode` errors on extra
386
+ * bytes after the value. We scan offsets for a container header (fixmap /
387
+ * fixarray / map16) and use `decodeMulti` to take the FIRST value, which
388
+ * tolerates trailing data. Falls back to last stream value otherwise.
389
+ */
390
+ decodeBody(body) {
391
+ // Scan offsets 0..8 for a container header. Prefer MAP candidates over
392
+ // ARRAY candidates — op 18 reply starts with `f2 91 82 …` where `91` is
393
+ // a fixarray-1 wrapping the real fixmap-2 payload at offset 2; without
394
+ // this preference we'd return `[{…}]` instead of `{…}`.
395
+ let arrayFallback = undefined;
396
+ const tryAt = (off) => {
397
+ try {
398
+ for (const v of msgpackDecodeMulti(body.subarray(off))) {
399
+ return v; // first value only
400
+ }
401
+ }
402
+ catch {
403
+ // ignore
404
+ }
405
+ return undefined;
406
+ };
407
+ for (let pass = 0; pass < 2; pass++) {
408
+ const wantMap = pass === 0;
409
+ for (let off = 0; off < Math.min(body.length, 9); off++) {
410
+ const h = body[off];
411
+ const isFixmap = h >= 0x80 && h <= 0x8f;
412
+ const isFixarr = h >= 0x90 && h <= 0x9f;
413
+ const isMap16 = h === 0xde || h === 0xdf;
414
+ const isArr16 = h === 0xdc || h === 0xdd;
415
+ const matches = wantMap ? (isFixmap || isMap16) : (isFixarr || isArr16);
416
+ if (!matches)
417
+ continue;
418
+ const v = tryAt(off);
419
+ if (v && typeof v === 'object') {
420
+ if (wantMap)
421
+ return v;
422
+ // Unwrap a 1-element array containing a map (server wraps some
423
+ // responses like op 18 in a fixarray).
424
+ if (Array.isArray(v) && v.length === 1 && v[0] && typeof v[0] === 'object') {
425
+ return v[0];
426
+ }
427
+ arrayFallback ??= v;
428
+ }
429
+ }
430
+ }
431
+ if (arrayFallback !== undefined)
432
+ return arrayFallback;
433
+ // Fallback A: stream-decode, return the last value.
434
+ try {
435
+ const values = [];
436
+ for (const v of msgpackDecodeMulti(body))
437
+ values.push(v);
438
+ if (values.length > 0)
439
+ return values[values.length - 1];
440
+ }
441
+ catch {
442
+ try {
443
+ return msgpackDecode(body);
444
+ }
445
+ catch { }
446
+ }
447
+ // Fallback B: if the body clearly contains a LOGIN token response (op 115
448
+ // / op 18 happy path), the server uses an opaque non-msgpack form for the
449
+ // inner `LOGIN.<key>` field — scan for ASCII markers and pull out the
450
+ // longest str8/str16 value as the token.
451
+ const hasTokenAttrs = body.indexOf(Buffer.from('tokenAttrs')) >= 0;
452
+ const hasLogin = body.indexOf(Buffer.from('LOGIN')) >= 0;
453
+ if (hasTokenAttrs && hasLogin) {
454
+ const tok = this.extractLongestString(body);
455
+ if (tok)
456
+ return { tokenAttrs: { LOGIN: { token: tok } } };
457
+ }
458
+ return undefined;
459
+ }
460
+ /** Scan `buf` for the longest msgpack str8/str16/str32 ASCII payload. */
461
+ extractLongestString(buf) {
462
+ let best = null;
463
+ for (let i = 0; i < buf.length - 2; i++) {
464
+ let len = 0;
465
+ let start = -1;
466
+ const h = buf[i];
467
+ if (h === 0xd9) {
468
+ len = buf[i + 1];
469
+ start = i + 2;
470
+ }
471
+ else if (h === 0xda) {
472
+ len = (buf[i + 1] << 8) | buf[i + 2];
473
+ start = i + 3;
474
+ }
475
+ else if (h === 0xdb) {
476
+ len = ((buf[i + 1] << 24) >>> 0) | (buf[i + 2] << 16) | (buf[i + 3] << 8) | buf[i + 4];
477
+ start = i + 5;
478
+ }
479
+ else
480
+ continue;
481
+ if (len < 50 || start + len > buf.length)
482
+ continue;
483
+ const slice = buf.subarray(start, start + len);
484
+ // Token-like = printable ASCII (base64url charset).
485
+ let printable = true;
486
+ for (let k = 0; k < slice.length; k++) {
487
+ const c = slice[k];
488
+ if (c < 0x20 || c > 0x7e) {
489
+ printable = false;
490
+ break;
491
+ }
492
+ }
493
+ if (!printable)
494
+ continue;
495
+ const s = slice.toString('utf-8');
496
+ if (!best || s.length > best.length)
497
+ best = s;
498
+ }
499
+ return best;
500
+ }
501
+ onClose() {
502
+ this.emit('close');
503
+ for (const [k, p] of this.pending) {
504
+ clearTimeout(p.timer);
505
+ p.reject(new Error('Transport closed by peer'));
506
+ this.pending.delete(k);
507
+ }
508
+ }
509
+ }
510
+ //# sourceMappingURL=raw-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-transport.js","sourceRoot":"","sources":["../src/raw-transport.ts"],"names":[],"mappings":"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"}