@mtcute/core 0.15.2 → 0.16.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/highlevel/base.d.ts +3 -3
- package/cjs/highlevel/base.js.map +1 -1
- package/cjs/highlevel/methods/files/download-iterable.js +1 -1
- package/cjs/highlevel/methods/files/download-iterable.js.map +1 -1
- package/cjs/highlevel/methods/users/resolve-peer-many.js +1 -1
- package/cjs/highlevel/methods/users/resolve-peer-many.js.map +1 -1
- package/cjs/highlevel/types/messages/dialog.d.ts +4 -2
- package/cjs/highlevel/types/messages/dialog.js +4 -2
- package/cjs/highlevel/types/messages/dialog.js.map +1 -1
- package/cjs/highlevel/types/messages/message-action.d.ts +15 -1
- package/cjs/highlevel/types/messages/message-action.js +10 -0
- package/cjs/highlevel/types/messages/message-action.js.map +1 -1
- package/cjs/highlevel/types/peers/full-chat.d.ts +2 -0
- package/cjs/highlevel/types/peers/full-chat.js +4 -0
- package/cjs/highlevel/types/peers/full-chat.js.map +1 -1
- package/cjs/highlevel/updates/manager.js +3 -3
- package/cjs/highlevel/updates/manager.js.map +1 -1
- package/cjs/highlevel/worker/invoker.js +2 -1
- package/cjs/highlevel/worker/invoker.js.map +1 -1
- package/cjs/highlevel/worker/port.js +4 -3
- package/cjs/highlevel/worker/port.js.map +1 -1
- package/cjs/highlevel/worker/protocol.d.ts +10 -5
- package/cjs/highlevel/worker/protocol.js +66 -0
- package/cjs/highlevel/worker/protocol.js.map +1 -1
- package/cjs/highlevel/worker/worker.js +6 -5
- package/cjs/highlevel/worker/worker.js.map +1 -1
- package/cjs/network/client.d.ts +0 -16
- package/cjs/network/client.js +0 -2
- package/cjs/network/client.js.map +1 -1
- package/cjs/network/index.d.ts +2 -1
- package/cjs/network/index.js +1 -0
- package/cjs/network/index.js.map +1 -1
- package/cjs/network/middlewares/bundle.d.ts +3 -0
- package/cjs/network/middlewares/bundle.js +20 -0
- package/cjs/network/middlewares/bundle.js.map +1 -0
- package/cjs/network/middlewares/default.d.ts +8 -0
- package/cjs/network/middlewares/default.js +10 -0
- package/cjs/network/middlewares/default.js.map +1 -0
- package/cjs/network/middlewares/flood-waiter.d.ts +37 -0
- package/cjs/network/middlewares/flood-waiter.js +70 -0
- package/cjs/network/middlewares/flood-waiter.js.map +1 -0
- package/cjs/network/middlewares/index.d.ts +2 -0
- package/cjs/network/middlewares/index.js +29 -0
- package/cjs/network/middlewares/index.js.map +1 -0
- package/cjs/network/middlewares/internal-errors.d.ts +17 -0
- package/cjs/network/middlewares/internal-errors.js +41 -0
- package/cjs/network/middlewares/internal-errors.js.map +1 -0
- package/cjs/network/middlewares/on-error.d.ts +30 -0
- package/cjs/network/middlewares/on-error.js +44 -0
- package/cjs/network/middlewares/on-error.js.map +1 -0
- package/cjs/network/middlewares/on-method.d.ts +39 -0
- package/cjs/network/middlewares/on-method.js +45 -0
- package/cjs/network/middlewares/on-method.js.map +1 -0
- package/cjs/network/mtproto-session.js +1 -1
- package/cjs/network/mtproto-session.js.map +1 -1
- package/cjs/network/multi-session-connection.js +1 -1
- package/cjs/network/multi-session-connection.js.map +1 -1
- package/cjs/network/network-manager.d.ts +23 -6
- package/cjs/network/network-manager.js +55 -102
- package/cjs/network/network-manager.js.map +1 -1
- package/cjs/network/persistent-connection.js +5 -5
- package/cjs/network/persistent-connection.js.map +1 -1
- package/cjs/network/session-connection.js +6 -6
- package/cjs/network/session-connection.js.map +1 -1
- package/cjs/storage/driver.js +1 -1
- package/cjs/storage/driver.js.map +1 -1
- package/cjs/storage/storage.js +1 -1
- package/cjs/storage/storage.js.map +1 -1
- package/cjs/utils/abort-signal.d.ts +1 -0
- package/cjs/utils/abort-signal.js +13 -0
- package/cjs/utils/abort-signal.js.map +1 -0
- package/cjs/utils/composer.d.ts +3 -0
- package/cjs/utils/composer.js +22 -0
- package/cjs/utils/composer.js.map +1 -0
- package/cjs/utils/error-reporting.js +1 -1
- package/cjs/utils/error-reporting.js.map +1 -1
- package/cjs/utils/index.d.ts +1 -0
- package/cjs/utils/index.js +1 -0
- package/cjs/utils/index.js.map +1 -1
- package/cjs/utils/logger.js +15 -3
- package/cjs/utils/logger.js.map +1 -1
- package/esm/highlevel/base.d.ts +3 -3
- package/esm/highlevel/base.js.map +1 -1
- package/esm/highlevel/methods/files/download-iterable.js +1 -1
- package/esm/highlevel/methods/files/download-iterable.js.map +1 -1
- package/esm/highlevel/methods/users/resolve-peer-many.js +1 -1
- package/esm/highlevel/methods/users/resolve-peer-many.js.map +1 -1
- package/esm/highlevel/types/messages/dialog.d.ts +4 -2
- package/esm/highlevel/types/messages/dialog.js +4 -2
- package/esm/highlevel/types/messages/dialog.js.map +1 -1
- package/esm/highlevel/types/messages/message-action.d.ts +15 -1
- package/esm/highlevel/types/messages/message-action.js +10 -0
- package/esm/highlevel/types/messages/message-action.js.map +1 -1
- package/esm/highlevel/types/peers/full-chat.d.ts +2 -0
- package/esm/highlevel/types/peers/full-chat.js +4 -0
- package/esm/highlevel/types/peers/full-chat.js.map +1 -1
- package/esm/highlevel/updates/manager.js +3 -3
- package/esm/highlevel/updates/manager.js.map +1 -1
- package/esm/highlevel/worker/invoker.js +2 -1
- package/esm/highlevel/worker/invoker.js.map +1 -1
- package/esm/highlevel/worker/port.js +4 -3
- package/esm/highlevel/worker/port.js.map +1 -1
- package/esm/highlevel/worker/protocol.d.ts +10 -5
- package/esm/highlevel/worker/protocol.js +60 -1
- package/esm/highlevel/worker/protocol.js.map +1 -1
- package/esm/highlevel/worker/worker.js +6 -5
- package/esm/highlevel/worker/worker.js.map +1 -1
- package/esm/network/client.d.ts +0 -16
- package/esm/network/client.js +0 -2
- package/esm/network/client.js.map +1 -1
- package/esm/network/index.d.ts +2 -1
- package/esm/network/index.js +1 -0
- package/esm/network/index.js.map +1 -1
- package/esm/network/middlewares/bundle.d.ts +3 -0
- package/esm/network/middlewares/bundle.js +4 -0
- package/esm/network/middlewares/bundle.js.map +1 -0
- package/esm/network/middlewares/default.d.ts +8 -0
- package/esm/network/middlewares/default.js +6 -0
- package/esm/network/middlewares/default.js.map +1 -0
- package/esm/network/middlewares/flood-waiter.d.ts +37 -0
- package/esm/network/middlewares/flood-waiter.js +66 -0
- package/esm/network/middlewares/flood-waiter.js.map +1 -0
- package/esm/network/middlewares/index.d.ts +2 -0
- package/esm/network/middlewares/index.js +3 -0
- package/esm/network/middlewares/index.js.map +1 -0
- package/esm/network/middlewares/internal-errors.d.ts +17 -0
- package/esm/network/middlewares/internal-errors.js +37 -0
- package/esm/network/middlewares/internal-errors.js.map +1 -0
- package/esm/network/middlewares/on-error.d.ts +30 -0
- package/esm/network/middlewares/on-error.js +40 -0
- package/esm/network/middlewares/on-error.js.map +1 -0
- package/esm/network/middlewares/on-method.d.ts +39 -0
- package/esm/network/middlewares/on-method.js +41 -0
- package/esm/network/middlewares/on-method.js.map +1 -0
- package/esm/network/mtproto-session.js +1 -1
- package/esm/network/mtproto-session.js.map +1 -1
- package/esm/network/multi-session-connection.js +1 -1
- package/esm/network/multi-session-connection.js.map +1 -1
- package/esm/network/network-manager.d.ts +23 -6
- package/esm/network/network-manager.js +57 -104
- package/esm/network/network-manager.js.map +1 -1
- package/esm/network/persistent-connection.js +5 -5
- package/esm/network/persistent-connection.js.map +1 -1
- package/esm/network/session-connection.js +6 -6
- package/esm/network/session-connection.js.map +1 -1
- package/esm/storage/driver.js +1 -1
- package/esm/storage/driver.js.map +1 -1
- package/esm/storage/storage.js +1 -1
- package/esm/storage/storage.js.map +1 -1
- package/esm/utils/abort-signal.d.ts +1 -0
- package/esm/utils/abort-signal.js +9 -0
- package/esm/utils/abort-signal.js.map +1 -0
- package/esm/utils/composer.d.ts +3 -0
- package/esm/utils/composer.js +18 -0
- package/esm/utils/composer.js.map +1 -0
- package/esm/utils/error-reporting.js +1 -1
- package/esm/utils/error-reporting.js.map +1 -1
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/esm/utils/logger.js +15 -3
- package/esm/utils/logger.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flood-waiter.js","sourceRoot":"","sources":["../../../../src/network/middlewares/flood-waiter.ts"],"names":[],"mappings":"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","sourcesContent":["import { mtp } from '@mtcute/tl'\n\nimport { combineAbortSignals } from '../../utils/abort-signal.js'\nimport { sleepWithAbort } from '../../utils/misc-utils.js'\nimport { isTlRpcError } from '../../utils/type-assertions.js'\nimport { RpcCallMiddleware } from '../network-manager.js'\n\nexport interface FloodWaiterOptions {\n /**\n * Maximum number of ms to wait when a FLOOD_WAIT_X\n * error is encountered. If the wait time is greater\n * than this value, the request will throw an error instead\n *\n * This can be overwritten on a per-request basis by setting\n * `floodSleepThreshold` in the request parameters\n *\n * @default 10_000\n */\n maxWait?: number\n\n /**\n * Maximum number of retries to perform when a FLOOD_WAIT_X\n * error is encountered. After this number of retries, the\n * last error will be thrown\n *\n * @default 5\n */\n maxRetries?: number\n\n /**\n * Whether to store the last flood wait time and delay\n * the consecutive requests accordingly\n *\n * @default true\n */\n store?: boolean\n\n /**\n * If the stored wait time is less than this value,\n * the request will not be delayed\n *\n * @default 3_000\n */\n minStoredWait?: number\n}\n\nexport function floodWaiter(options: FloodWaiterOptions): RpcCallMiddleware {\n const { maxWait = 10_000, maxRetries = 5, store = true, minStoredWait = 3_000 } = options\n\n const storage = new Map<string, number>()\n\n return async (ctx, next) => {\n // do not send requests that are in flood wait\n const method = ctx.request._\n const storedWaitUntil = store ? storage.get(method) : undefined\n const floodSleepThreshold = ctx.params?.floodSleepThreshold ?? maxWait\n\n if (storedWaitUntil !== undefined) {\n const delta = storedWaitUntil - Date.now()\n\n if (delta <= minStoredWait) {\n // flood waits below 3 seconds are \"ignored\"\n storage.delete(method)\n } else if (delta <= floodSleepThreshold) {\n await sleepWithAbort(delta, combineAbortSignals(ctx.manager.params.stopSignal, ctx.params?.abortSignal))\n storage.delete(method)\n } else {\n return {\n _: 'mt_rpc_error',\n errorCode: 420,\n errorMessage: `FLOOD_WAIT_${Math.ceil(delta / 1000)}`,\n } satisfies mtp.RawMt_rpc_error\n }\n }\n\n let lastError: mtp.RawMt_rpc_error | undefined\n\n for (let i = 0; i <= maxRetries; i++) {\n const res = await next(ctx)\n\n if (!isTlRpcError(res)) {\n return res\n }\n\n lastError = res\n\n const err = res.errorMessage\n\n if (\n err.startsWith('FLOOD_WAIT_') ||\n err.startsWith('SLOWMODE_WAIT_') ||\n err.startsWith('FLOOD_TEST_PHONE_WAIT_')\n ) {\n let seconds = Number(err.slice(err.lastIndexOf('_') + 1))\n\n if (Number.isNaN(seconds)) {\n ctx.manager._log.warn('invalid flood wait error received: %s, ignoring', err)\n\n return res\n }\n\n if (store && !err.startsWith('SLOWMODE_WAIT_')) {\n // SLOW_MODE_WAIT is per-chat, not per-request\n storage.set(method, Date.now() + seconds * 1000)\n }\n\n // In test servers, FLOOD_WAIT_0 has been observed, and sleeping for\n // such a short amount will cause retries very fast leading to issues\n if (seconds === 0) {\n seconds = 1\n }\n\n const ms = seconds * 1000\n\n if (ms <= floodSleepThreshold) {\n ctx.manager._log.warn('%s resulted in a flood wait, will retry in %d seconds', method, seconds)\n await sleepWithAbort(\n ms,\n combineAbortSignals(ctx.manager.params.stopSignal, ctx.params?.abortSignal),\n )\n continue\n }\n }\n }\n\n return lastError\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/network/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,kBAAkB,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,kBAAkB,EAAE,CAAA","sourcesContent":["import * as networkMiddlewares from './bundle.js'\n\nexport { networkMiddlewares }\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RpcCallMiddleware } from '../network-manager.js';
|
|
2
|
+
export interface InternalErrorsHandlerOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Maximum number of retries to perform when an internal server error is encountered.
|
|
5
|
+
*
|
|
6
|
+
* @default Infinity
|
|
7
|
+
*/
|
|
8
|
+
maxRetries?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Number of seconds to wait before retrying
|
|
11
|
+
* when an internal server error is encountered.
|
|
12
|
+
*
|
|
13
|
+
* @default 1
|
|
14
|
+
*/
|
|
15
|
+
waitTime?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function internalErrorsHandler(params: InternalErrorsHandlerOptions): RpcCallMiddleware;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { tl } from '@mtcute/tl';
|
|
2
|
+
import { MtTimeoutError } from '../../types/errors.js';
|
|
3
|
+
import { combineAbortSignals } from '../../utils/abort-signal.js';
|
|
4
|
+
import { sleepWithAbort } from '../../utils/misc-utils.js';
|
|
5
|
+
import { isTlRpcError } from '../../utils/type-assertions.js';
|
|
6
|
+
const CLIENT_ERRORS = /* #__PURE__ */ new Set([
|
|
7
|
+
tl.RpcError.BAD_REQUEST,
|
|
8
|
+
tl.RpcError.UNAUTHORIZED,
|
|
9
|
+
tl.RpcError.FORBIDDEN,
|
|
10
|
+
tl.RpcError.NOT_FOUND,
|
|
11
|
+
tl.RpcError.FLOOD,
|
|
12
|
+
tl.RpcError.SEE_OTHER,
|
|
13
|
+
tl.RpcError.NOT_ACCEPTABLE,
|
|
14
|
+
]);
|
|
15
|
+
export function internalErrorsHandler(params) {
|
|
16
|
+
const { maxRetries = Infinity, waitTime = 1 } = params;
|
|
17
|
+
return async (ctx, next) => {
|
|
18
|
+
const numRetries = ctx.params?.maxRetryCount ?? maxRetries;
|
|
19
|
+
for (let i = 0; i <= numRetries; i++) {
|
|
20
|
+
const res = await next(ctx);
|
|
21
|
+
if (!isTlRpcError(res))
|
|
22
|
+
return res;
|
|
23
|
+
if (!CLIENT_ERRORS.has(res.errorCode)) {
|
|
24
|
+
if (ctx.params?.throw503 && res.errorCode === -503) {
|
|
25
|
+
throw new MtTimeoutError();
|
|
26
|
+
}
|
|
27
|
+
const waitSeconds = res.errorMessage === 'WORKER_BUSY_TOO_LONG_RETRY' ? Math.max(1, waitTime) : waitTime;
|
|
28
|
+
ctx.manager._log.warn('Telegram is having internal issues: %d:%s, retrying in %ds', res.errorCode, res.errorMessage, waitSeconds);
|
|
29
|
+
if (waitSeconds > 0) {
|
|
30
|
+
await sleepWithAbort(waitSeconds * 1000, combineAbortSignals(ctx.manager.params.stopSignal, ctx.params?.abortSignal));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return res;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=internal-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-errors.js","sourceRoot":"","sources":["../../../../src/network/middlewares/internal-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAA;AAE/B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAG7D,MAAM,aAAa,GAAG,eAAe,CAAC,IAAI,GAAG,CAAS;IAClD,EAAE,CAAC,QAAQ,CAAC,WAAW;IACvB,EAAE,CAAC,QAAQ,CAAC,YAAY;IACxB,EAAE,CAAC,QAAQ,CAAC,SAAS;IACrB,EAAE,CAAC,QAAQ,CAAC,SAAS;IACrB,EAAE,CAAC,QAAQ,CAAC,KAAK;IACjB,EAAE,CAAC,QAAQ,CAAC,SAAS;IACrB,EAAE,CAAC,QAAQ,CAAC,cAAc;CAC7B,CAAC,CAAA;AAmBF,MAAM,UAAU,qBAAqB,CAAC,MAAoC;IACtE,MAAM,EAAE,UAAU,GAAG,QAAQ,EAAE,QAAQ,GAAG,CAAC,EAAE,GAAG,MAAM,CAAA;IAEtD,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,IAAI,UAAU,CAAA;QAE1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;YAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAA;YAElC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACpC,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,CAAC,SAAS,KAAK,CAAC,GAAG,EAAE,CAAC;oBACjD,MAAM,IAAI,cAAc,EAAE,CAAA;gBAC9B,CAAC;gBAED,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,KAAK,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;gBAExG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CACjB,4DAA4D,EAC5D,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,YAAY,EAChB,WAAW,CACd,CAAA;gBAED,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;oBAClB,MAAM,cAAc,CAChB,WAAW,GAAG,IAAI,EAClB,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAC9E,CAAA;gBACL,CAAC;YACL,CAAC;YAED,OAAO,GAAG,CAAA;QACd,CAAC;IACL,CAAC,CAAA;AACL,CAAC","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { MtTimeoutError } from '../../types/errors.js'\nimport { combineAbortSignals } from '../../utils/abort-signal.js'\nimport { sleepWithAbort } from '../../utils/misc-utils.js'\nimport { isTlRpcError } from '../../utils/type-assertions.js'\nimport { RpcCallMiddleware } from '../network-manager.js'\n\nconst CLIENT_ERRORS = /* #__PURE__ */ new Set<number>([\n tl.RpcError.BAD_REQUEST,\n tl.RpcError.UNAUTHORIZED,\n tl.RpcError.FORBIDDEN,\n tl.RpcError.NOT_FOUND,\n tl.RpcError.FLOOD,\n tl.RpcError.SEE_OTHER,\n tl.RpcError.NOT_ACCEPTABLE,\n])\n\nexport interface InternalErrorsHandlerOptions {\n /**\n * Maximum number of retries to perform when an internal server error is encountered.\n *\n * @default Infinity\n */\n maxRetries?: number\n\n /**\n * Number of seconds to wait before retrying\n * when an internal server error is encountered.\n *\n * @default 1\n */\n waitTime?: number\n}\n\nexport function internalErrorsHandler(params: InternalErrorsHandlerOptions): RpcCallMiddleware {\n const { maxRetries = Infinity, waitTime = 1 } = params\n\n return async (ctx, next) => {\n const numRetries = ctx.params?.maxRetryCount ?? maxRetries\n\n for (let i = 0; i <= numRetries; i++) {\n const res = await next(ctx)\n if (!isTlRpcError(res)) return res\n\n if (!CLIENT_ERRORS.has(res.errorCode)) {\n if (ctx.params?.throw503 && res.errorCode === -503) {\n throw new MtTimeoutError()\n }\n\n const waitSeconds = res.errorMessage === 'WORKER_BUSY_TOO_LONG_RETRY' ? Math.max(1, waitTime) : waitTime\n\n ctx.manager._log.warn(\n 'Telegram is having internal issues: %d:%s, retrying in %ds',\n res.errorCode,\n res.errorMessage,\n waitSeconds,\n )\n\n if (waitSeconds > 0) {\n await sleepWithAbort(\n waitSeconds * 1000,\n combineAbortSignals(ctx.manager.params.stopSignal, ctx.params?.abortSignal),\n )\n }\n }\n\n return res\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mtp } from '@mtcute/tl';
|
|
2
|
+
import { MaybePromise } from '../../types/utils.js';
|
|
3
|
+
import { RpcCallMiddleware, RpcCallMiddlewareContext } from '../network-manager.js';
|
|
4
|
+
/**
|
|
5
|
+
* Middleware that will call `handler` whenever an RPC error happens,
|
|
6
|
+
* with the error object itself.
|
|
7
|
+
*
|
|
8
|
+
* The handler can either return nothing
|
|
9
|
+
* (in which case the original error will be thrown), a new error
|
|
10
|
+
* (via the `_: 'mt_rpc_error'` object), or any other value, which
|
|
11
|
+
* will be returned as the result of the RPC call.
|
|
12
|
+
*
|
|
13
|
+
* Note that the return value is **not type-checked**
|
|
14
|
+
* due to limitations of TypeScript. You'll probably want to use `satisfies`
|
|
15
|
+
* keyword to ensure the return value is correct, for example:
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* networkMiddlewares.onRpcError(async (ctx, error) => {
|
|
19
|
+
* if (rpc.request._ === 'help.getNearestDc') {
|
|
20
|
+
* return {
|
|
21
|
+
* _: 'nearestDc',
|
|
22
|
+
* country: 'RU',
|
|
23
|
+
* thisDc: 2,
|
|
24
|
+
* nearestDc: 2,
|
|
25
|
+
* } satisfies tl.RpcCallReturn['help.getNearestDc']
|
|
26
|
+
* }
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function onRpcError(handler: (ctx: RpcCallMiddlewareContext, error: mtp.RawMt_rpc_error) => MaybePromise<unknown>): RpcCallMiddleware;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isTlRpcError } from '../../utils/type-assertions.js';
|
|
2
|
+
/**
|
|
3
|
+
* Middleware that will call `handler` whenever an RPC error happens,
|
|
4
|
+
* with the error object itself.
|
|
5
|
+
*
|
|
6
|
+
* The handler can either return nothing
|
|
7
|
+
* (in which case the original error will be thrown), a new error
|
|
8
|
+
* (via the `_: 'mt_rpc_error'` object), or any other value, which
|
|
9
|
+
* will be returned as the result of the RPC call.
|
|
10
|
+
*
|
|
11
|
+
* Note that the return value is **not type-checked**
|
|
12
|
+
* due to limitations of TypeScript. You'll probably want to use `satisfies`
|
|
13
|
+
* keyword to ensure the return value is correct, for example:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* networkMiddlewares.onRpcError(async (ctx, error) => {
|
|
17
|
+
* if (rpc.request._ === 'help.getNearestDc') {
|
|
18
|
+
* return {
|
|
19
|
+
* _: 'nearestDc',
|
|
20
|
+
* country: 'RU',
|
|
21
|
+
* thisDc: 2,
|
|
22
|
+
* nearestDc: 2,
|
|
23
|
+
* } satisfies tl.RpcCallReturn['help.getNearestDc']
|
|
24
|
+
* }
|
|
25
|
+
* })
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function onRpcError(handler) {
|
|
29
|
+
return async (ctx, next) => {
|
|
30
|
+
let res = await next(ctx);
|
|
31
|
+
if (isTlRpcError(res)) {
|
|
32
|
+
const handlerRes = await handler(ctx, res);
|
|
33
|
+
if (handlerRes !== undefined) {
|
|
34
|
+
res = handlerRes;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return res;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=on-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-error.js","sourceRoot":"","sources":["../../../../src/network/middlewares/on-error.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAG7D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,UAAU,CACtB,OAA6F;IAE7F,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACvB,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;QAEzB,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;YAE1C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC3B,GAAG,GAAG,UAAU,CAAA;YACpB,CAAC;QACL,CAAC;QAED,OAAO,GAAG,CAAA;IACd,CAAC,CAAA;AACL,CAAC","sourcesContent":["import { mtp } from '@mtcute/tl'\n\nimport { MaybePromise } from '../../types/utils.js'\nimport { isTlRpcError } from '../../utils/type-assertions.js'\nimport { RpcCallMiddleware, RpcCallMiddlewareContext } from '../network-manager.js'\n\n/**\n * Middleware that will call `handler` whenever an RPC error happens,\n * with the error object itself.\n *\n * The handler can either return nothing\n * (in which case the original error will be thrown), a new error\n * (via the `_: 'mt_rpc_error'` object), or any other value, which\n * will be returned as the result of the RPC call.\n *\n * Note that the return value is **not type-checked**\n * due to limitations of TypeScript. You'll probably want to use `satisfies`\n * keyword to ensure the return value is correct, for example:\n *\n * ```ts\n * networkMiddlewares.onRpcError(async (ctx, error) => {\n * if (rpc.request._ === 'help.getNearestDc') {\n * return {\n * _: 'nearestDc',\n * country: 'RU',\n * thisDc: 2,\n * nearestDc: 2,\n * } satisfies tl.RpcCallReturn['help.getNearestDc']\n * }\n * })\n * ```\n */\nexport function onRpcError(\n handler: (ctx: RpcCallMiddlewareContext, error: mtp.RawMt_rpc_error) => MaybePromise<unknown>,\n): RpcCallMiddleware {\n return async (ctx, next) => {\n let res = await next(ctx)\n\n if (isTlRpcError(res)) {\n const handlerRes = await handler(ctx, res)\n\n if (handlerRes !== undefined) {\n res = handlerRes\n }\n }\n\n return res\n }\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tl } from '@mtcute/tl';
|
|
2
|
+
import { Middleware } from '../../utils/composer.js';
|
|
3
|
+
import { RpcCallMiddleware, RpcCallMiddlewareContext } from '../network-manager.js';
|
|
4
|
+
/**
|
|
5
|
+
* Middleware that will call `handler` whenever `method` RPC method is called.
|
|
6
|
+
*
|
|
7
|
+
* This helper exists due to TypeScript limitations not allowing us to
|
|
8
|
+
* properly type the return type without explicit type annotations,
|
|
9
|
+
* for a bit more type-safe and clean code:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* // before
|
|
13
|
+
* async (ctx, next) => {
|
|
14
|
+
* if (rpc.request._ === 'help.getNearestDc') {
|
|
15
|
+
* return {
|
|
16
|
+
* _: 'nearestDc',
|
|
17
|
+
* country: 'RU',
|
|
18
|
+
* thisDc: 2,
|
|
19
|
+
* nearestDc: 2,
|
|
20
|
+
* } satisfies tl.RpcCallReturn['help.getNearestDc']
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* return next(ctx)
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // after
|
|
27
|
+
* onMethod('help.getNearestDc', async () => ({
|
|
28
|
+
* _: 'nearestDc' as const, // (otherwise ts will infer this as `string` and will complain)
|
|
29
|
+
* country: 'RU',
|
|
30
|
+
* thisDc: 2,
|
|
31
|
+
* nearestDc: 2,
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function onMethod<T extends tl.RpcMethod['_']>(method: T, middleware: Middleware<Omit<RpcCallMiddlewareContext, 'request'> & {
|
|
36
|
+
request: Extract<tl.RpcMethod, {
|
|
37
|
+
_: T;
|
|
38
|
+
}>;
|
|
39
|
+
}, tl.RpcCallReturn[T]>): RpcCallMiddleware;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware that will call `handler` whenever `method` RPC method is called.
|
|
3
|
+
*
|
|
4
|
+
* This helper exists due to TypeScript limitations not allowing us to
|
|
5
|
+
* properly type the return type without explicit type annotations,
|
|
6
|
+
* for a bit more type-safe and clean code:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* // before
|
|
10
|
+
* async (ctx, next) => {
|
|
11
|
+
* if (rpc.request._ === 'help.getNearestDc') {
|
|
12
|
+
* return {
|
|
13
|
+
* _: 'nearestDc',
|
|
14
|
+
* country: 'RU',
|
|
15
|
+
* thisDc: 2,
|
|
16
|
+
* nearestDc: 2,
|
|
17
|
+
* } satisfies tl.RpcCallReturn['help.getNearestDc']
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* return next(ctx)
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* // after
|
|
24
|
+
* onMethod('help.getNearestDc', async () => ({
|
|
25
|
+
* _: 'nearestDc' as const, // (otherwise ts will infer this as `string` and will complain)
|
|
26
|
+
* country: 'RU',
|
|
27
|
+
* thisDc: 2,
|
|
28
|
+
* nearestDc: 2,
|
|
29
|
+
* })
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function onMethod(method, middleware) {
|
|
33
|
+
return async (ctx, next) => {
|
|
34
|
+
if (ctx.request._ !== method) {
|
|
35
|
+
return next(ctx);
|
|
36
|
+
}
|
|
37
|
+
// eslint-disable-next-line
|
|
38
|
+
return middleware(ctx, next);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=on-method.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-method.js","sourceRoot":"","sources":["../../../../src/network/middlewares/on-method.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,QAAQ,CACpB,MAAS,EACT,UAKC;IAED,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACvB,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;QACpB,CAAC;QAED,2BAA2B;QAC3B,OAAO,UAAU,CAAC,GAAU,EAAE,IAAI,CAAC,CAAA;IACvC,CAAC,CAAA;AACL,CAAC","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { Middleware } from '../../utils/composer.js'\nimport { RpcCallMiddleware, RpcCallMiddlewareContext } from '../network-manager.js'\n\n/**\n * Middleware that will call `handler` whenever `method` RPC method is called.\n *\n * This helper exists due to TypeScript limitations not allowing us to\n * properly type the return type without explicit type annotations,\n * for a bit more type-safe and clean code:\n *\n * ```ts\n * // before\n * async (ctx, next) => {\n * if (rpc.request._ === 'help.getNearestDc') {\n * return {\n * _: 'nearestDc',\n * country: 'RU',\n * thisDc: 2,\n * nearestDc: 2,\n * } satisfies tl.RpcCallReturn['help.getNearestDc']\n * }\n *\n * return next(ctx)\n * }\n *\n * // after\n * onMethod('help.getNearestDc', async () => ({\n * _: 'nearestDc' as const, // (otherwise ts will infer this as `string` and will complain)\n * country: 'RU',\n * thisDc: 2,\n * nearestDc: 2,\n * })\n * ```\n */\nexport function onMethod<T extends tl.RpcMethod['_']>(\n method: T,\n middleware: Middleware<\n Omit<RpcCallMiddlewareContext, 'request'> & {\n request: Extract<tl.RpcMethod, { _: T }>\n },\n tl.RpcCallReturn[T]\n >,\n): RpcCallMiddleware {\n return async (ctx, next) => {\n if (ctx.request._ !== method) {\n return next(ctx)\n }\n\n // eslint-disable-next-line\n return middleware(ctx as any, next)\n }\n}\n"]}
|
|
@@ -239,7 +239,7 @@ export class MtprotoSession {
|
|
|
239
239
|
}
|
|
240
240
|
if (lastMsgId.eq(msgId)) {
|
|
241
241
|
// last message of the chain, remove it
|
|
242
|
-
this.log.debug('chain %s: exhausted, last message %l',
|
|
242
|
+
this.log.debug('chain %s: exhausted, last message %l', chainId, msgId);
|
|
243
243
|
this.chains.delete(chainId);
|
|
244
244
|
}
|
|
245
245
|
// do nothing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mtproto-session.js","sourceRoot":"","sources":["../../../src/network/mtproto-session.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\n\nimport { mtp, tl } from '@mtcute/tl'\nimport { TlBinaryWriter, TlReaderMap, TlSerializationCounter, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { MtcuteError } from '../types/index.js'\nimport {\n compareLongs,\n ControllablePromise,\n Deque,\n getRandomInt,\n ICryptoProvider,\n Logger,\n LongMap,\n LruSet,\n randomLong,\n SortedArray,\n} from '../utils/index.js'\nimport { AuthKey } from './auth-key.js'\nimport { ServerSaltManager } from './server-salt.js'\n\nexport interface PendingRpc {\n method: string\n data: Uint8Array\n promise: ControllablePromise\n stack?: string\n gzipOverhead?: number\n\n chainId?: string | number\n invokeAfter?: Long\n\n sent?: boolean\n done?: boolean\n msgId?: Long\n seqNo?: number\n containerId?: Long\n acked?: boolean\n initConn?: boolean\n getState?: number\n cancelled?: boolean\n timeout?: NodeJS.Timeout\n}\n\nexport type PendingMessage =\n | {\n _: 'rpc'\n rpc: PendingRpc\n }\n | {\n _: 'container'\n msgIds: Long[]\n }\n | {\n _: 'state'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'resend'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'ping'\n pingId: Long\n containerId: Long\n }\n | {\n _: 'destroy_session'\n sessionId: Long\n containerId: Long\n }\n | {\n _: 'cancel'\n msgId: Long\n containerId: Long\n }\n | {\n _: 'future_salts'\n containerId: Long\n }\n | {\n _: 'bind'\n promise: ControllablePromise\n }\n\n/**\n * Class encapsulating a single MTProto session and storing\n * all the relevant state\n */\nexport class MtprotoSession {\n _sessionId = randomLong()\n\n _authKey: AuthKey\n _authKeyTemp: AuthKey\n _authKeyTempSecondary: AuthKey\n\n _timeOffset = 0\n _lastMessageId = Long.ZERO\n _seqNo = 0\n\n /// state ///\n // recent msg ids\n recentOutgoingMsgIds = new LruSet<Long>(1000, true)\n recentIncomingMsgIds = new LruSet<Long>(1000, true)\n\n // queues\n queuedRpc = new Deque<PendingRpc>()\n queuedAcks: Long[] = []\n queuedStateReq: Long[] = []\n queuedResendReq: Long[] = []\n queuedCancelReq: Long[] = []\n getStateSchedule = new SortedArray<PendingRpc>([], (a, b) => a.getState! - b.getState!)\n\n chains = new Map<string | number, Long>()\n chainsPendingFails = new Map<string | number, SortedArray<PendingRpc>>()\n\n // requests info\n pendingMessages = new LongMap<PendingMessage>()\n destroySessionIdToMsgId = new LongMap<Long>()\n\n lastPingRtt = NaN\n lastPingTime = 0\n lastPingMsgId = Long.ZERO\n lastSessionCreatedUid = Long.ZERO\n\n initConnectionCalled = false\n authorizationPending = false\n\n next429Timeout = 1000\n current429Timeout?: NodeJS.Timeout\n next429ResetTimeout?: NodeJS.Timeout\n\n constructor(\n readonly _crypto: ICryptoProvider,\n readonly log: Logger,\n readonly _readerMap: TlReaderMap,\n readonly _writerMap: TlWriterMap,\n readonly _salts: ServerSaltManager,\n ) {\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n this._authKey = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTemp = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTempSecondary = new AuthKey(_crypto, log, _readerMap)\n }\n\n get hasPendingMessages(): boolean {\n return Boolean(\n this.queuedRpc.length ||\n this.queuedAcks.length ||\n this.queuedStateReq.length ||\n this.queuedResendReq.length,\n )\n }\n\n /**\n * Reset session by resetting auth key(s) and session state\n */\n reset(withAuthKey = false): void {\n if (withAuthKey) {\n this.resetAuthKey()\n }\n\n clearTimeout(this.current429Timeout)\n this.resetState(withAuthKey)\n this.resetLastPing(true)\n }\n\n resetAuthKey(): void {\n this._authKey.reset()\n this._authKeyTemp.reset()\n this._authKeyTempSecondary.reset()\n }\n\n updateTimeOffset(offset: number) {\n this.log.debug('time offset updated: %d', offset)\n this._timeOffset = offset\n // lastMessageId was generated with (potentially) wrong time\n // reset it to avoid bigger issues - at worst, we'll get bad_msg_notification\n this._lastMessageId = Long.ZERO\n }\n\n /**\n * Reset session state and generate a new session ID.\n *\n * By default, also cancels any pending RPC requests.\n * If `keepPending` is set to `true`, pending requests will be kept\n */\n resetState(keepPending = false): void {\n this._lastMessageId = Long.ZERO\n this._seqNo = 0\n\n this._sessionId = randomLong()\n this.log.debug('session reset, new sid = %h', this._sessionId)\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n // reset session state\n\n if (!keepPending) {\n for (const info of this.pendingMessages.values()) {\n if (info._ === 'rpc') {\n this.log.debug('rejecting pending rpc %s', info.rpc.method)\n info.rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n this.pendingMessages.clear()\n }\n\n this.recentOutgoingMsgIds.clear()\n this.recentIncomingMsgIds.clear()\n\n if (!keepPending) {\n while (this.queuedRpc.length) {\n const rpc = this.queuedRpc.popFront()!\n\n if (rpc.sent === false) {\n this.log.debug('rejecting pending rpc %s', rpc.method)\n rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n }\n\n this.queuedAcks.length = 0\n this.queuedStateReq.length = 0\n this.queuedResendReq.length = 0\n this.queuedCancelReq.length = 0\n this.getStateSchedule.clear()\n this.chains.clear()\n this.chainsPendingFails.clear()\n }\n\n enqueueRpc(rpc: PendingRpc, force?: boolean): boolean {\n // already queued or cancelled\n if ((!force && !rpc.sent) || rpc.cancelled) return false\n\n rpc.sent = false\n rpc.containerId = undefined\n this.log.debug('enqueued %s for sending (msg_id = %s)', rpc.method, rpc.msgId || 'n/a')\n this.queuedRpc.pushBack(rpc)\n\n return true\n }\n\n getMessageId(): Long {\n const timeTicks = Date.now()\n const timeSec = Math.floor(timeTicks / 1000) - this._timeOffset\n const timeMSec = timeTicks % 1000\n const random = getRandomInt(0xffff)\n\n let messageId = new Long((timeMSec << 21) | (random << 3) | 4, timeSec)\n\n if (this._lastMessageId.ge(messageId)) {\n messageId = this._lastMessageId.add(4)\n }\n\n this._lastMessageId = messageId\n\n return messageId\n }\n\n getSeqNo(isContentRelated = true): number {\n let seqNo = this._seqNo\n\n if (isContentRelated) {\n seqNo += 1\n this._seqNo += 2\n }\n\n return seqNo\n }\n\n /** Encrypt a single MTProto message using session's keys */\n encryptMessage(message: Uint8Array): Uint8Array {\n const key = this._authKeyTemp.ready ? this._authKeyTemp : this._authKey\n\n return key.encryptMessage(message, this._salts.currentSalt, this._sessionId)\n }\n\n /** Decrypt a single MTProto message using session's keys */\n decryptMessage(data: Uint8Array, callback: Parameters<AuthKey['decryptMessage']>[2]): void {\n if (!this._authKey.ready) throw new MtcuteError('Keys are not set up!')\n\n const authKeyId = data.subarray(0, 8)\n\n let key: AuthKey\n\n if (this._authKey.match(authKeyId)) {\n key = this._authKey\n } else if (this._authKeyTemp.match(authKeyId)) {\n key = this._authKeyTemp\n } else if (this._authKeyTempSecondary.match(authKeyId)) {\n key = this._authKeyTempSecondary\n } else {\n this.log.warn(\n 'received message with unknown authKey = %h (expected %h or %h or %h)',\n authKeyId,\n this._authKey.id,\n this._authKeyTemp.id,\n this._authKeyTempSecondary.id,\n )\n\n return\n }\n\n return key.decryptMessage(data, this._sessionId, callback)\n }\n\n writeMessage(\n writer: TlBinaryWriter,\n content: tl.TlObject | mtp.TlObject | Uint8Array,\n isContentRelated = true,\n ): Long {\n const messageId = this.getMessageId()\n const seqNo = this.getSeqNo(isContentRelated)\n\n const length = ArrayBuffer.isView(content) ?\n content.length :\n TlSerializationCounter.countNeededBytes(writer.objectMap!, content)\n\n writer.long(messageId)\n writer.int(seqNo)\n writer.uint(length)\n if (ArrayBuffer.isView(content)) writer.raw(content)\n else writer.object(content as tl.TlObject)\n\n return messageId\n }\n\n onTransportFlood(callback: () => void) {\n if (this.current429Timeout) return // already waiting\n\n // all active queries must be resent after a timeout\n this.resetLastPing(true)\n\n const timeout = this.next429Timeout\n\n this.next429Timeout = Math.min(this.next429Timeout * 2, 32000)\n clearTimeout(this.current429Timeout)\n clearTimeout(this.next429ResetTimeout)\n\n this.current429Timeout = setTimeout(() => {\n this.current429Timeout = undefined\n callback()\n }, timeout)\n this.next429ResetTimeout = setTimeout(() => {\n this.next429ResetTimeout = undefined\n this.next429Timeout = 1000\n }, 60000)\n\n this.log.debug('transport flood, waiting for %d ms before proceeding', timeout)\n\n return Date.now() + timeout\n }\n\n resetLastPing(withTime = false): void {\n if (withTime) this.lastPingTime = 0\n\n if (!this.lastPingMsgId.isZero()) {\n this.pendingMessages.delete(this.lastPingMsgId)\n }\n\n this.lastPingMsgId = Long.ZERO\n }\n\n addToChain(chainId: string | number, msgId: Long): Long | undefined {\n const prevMsgId = this.chains.get(chainId)\n this.chains.set(chainId, msgId)\n\n this.log.debug('added message %l to chain %s (prev: %l)', msgId, chainId, prevMsgId)\n\n return prevMsgId\n }\n\n removeFromChain(chainId: string | number, msgId: Long): void {\n const lastMsgId = this.chains.get(chainId)\n\n if (!lastMsgId) {\n this.log.warn('tried to remove message %l from empty chain %s', msgId, chainId)\n\n return\n }\n\n if (lastMsgId.eq(msgId)) {\n // last message of the chain, remove it\n this.log.debug('chain %s: exhausted, last message %l', msgId, chainId)\n this.chains.delete(chainId)\n }\n\n // do nothing\n }\n\n getPendingChainedFails(chainId: string | number): SortedArray<PendingRpc> {\n let arr = this.chainsPendingFails.get(chainId)\n\n if (!arr) {\n arr = new SortedArray<PendingRpc>([], (a, b) => compareLongs(a.invokeAfter!, b.invokeAfter!))\n this.chainsPendingFails.set(chainId, arr)\n }\n\n return arr\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mtproto-session.js","sourceRoot":"","sources":["../../../src/network/mtproto-session.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\n\nimport { mtp, tl } from '@mtcute/tl'\nimport { TlBinaryWriter, TlReaderMap, TlSerializationCounter, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { MtcuteError } from '../types/index.js'\nimport {\n compareLongs,\n ControllablePromise,\n Deque,\n getRandomInt,\n ICryptoProvider,\n Logger,\n LongMap,\n LruSet,\n randomLong,\n SortedArray,\n} from '../utils/index.js'\nimport { AuthKey } from './auth-key.js'\nimport { ServerSaltManager } from './server-salt.js'\n\nexport interface PendingRpc {\n method: string\n data: Uint8Array\n promise: ControllablePromise\n stack?: string\n gzipOverhead?: number\n\n chainId?: string | number\n invokeAfter?: Long\n\n sent?: boolean\n done?: boolean\n msgId?: Long\n seqNo?: number\n containerId?: Long\n acked?: boolean\n initConn?: boolean\n getState?: number\n cancelled?: boolean\n timeout?: NodeJS.Timeout\n}\n\nexport type PendingMessage =\n | {\n _: 'rpc'\n rpc: PendingRpc\n }\n | {\n _: 'container'\n msgIds: Long[]\n }\n | {\n _: 'state'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'resend'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'ping'\n pingId: Long\n containerId: Long\n }\n | {\n _: 'destroy_session'\n sessionId: Long\n containerId: Long\n }\n | {\n _: 'cancel'\n msgId: Long\n containerId: Long\n }\n | {\n _: 'future_salts'\n containerId: Long\n }\n | {\n _: 'bind'\n promise: ControllablePromise\n }\n\n/**\n * Class encapsulating a single MTProto session and storing\n * all the relevant state\n */\nexport class MtprotoSession {\n _sessionId = randomLong()\n\n _authKey: AuthKey\n _authKeyTemp: AuthKey\n _authKeyTempSecondary: AuthKey\n\n _timeOffset = 0\n _lastMessageId = Long.ZERO\n _seqNo = 0\n\n /// state ///\n // recent msg ids\n recentOutgoingMsgIds = new LruSet<Long>(1000, true)\n recentIncomingMsgIds = new LruSet<Long>(1000, true)\n\n // queues\n queuedRpc = new Deque<PendingRpc>()\n queuedAcks: Long[] = []\n queuedStateReq: Long[] = []\n queuedResendReq: Long[] = []\n queuedCancelReq: Long[] = []\n getStateSchedule = new SortedArray<PendingRpc>([], (a, b) => a.getState! - b.getState!)\n\n chains = new Map<string | number, Long>()\n chainsPendingFails = new Map<string | number, SortedArray<PendingRpc>>()\n\n // requests info\n pendingMessages = new LongMap<PendingMessage>()\n destroySessionIdToMsgId = new LongMap<Long>()\n\n lastPingRtt = NaN\n lastPingTime = 0\n lastPingMsgId = Long.ZERO\n lastSessionCreatedUid = Long.ZERO\n\n initConnectionCalled = false\n authorizationPending = false\n\n next429Timeout = 1000\n current429Timeout?: NodeJS.Timeout\n next429ResetTimeout?: NodeJS.Timeout\n\n constructor(\n readonly _crypto: ICryptoProvider,\n readonly log: Logger,\n readonly _readerMap: TlReaderMap,\n readonly _writerMap: TlWriterMap,\n readonly _salts: ServerSaltManager,\n ) {\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n this._authKey = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTemp = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTempSecondary = new AuthKey(_crypto, log, _readerMap)\n }\n\n get hasPendingMessages(): boolean {\n return Boolean(\n this.queuedRpc.length ||\n this.queuedAcks.length ||\n this.queuedStateReq.length ||\n this.queuedResendReq.length,\n )\n }\n\n /**\n * Reset session by resetting auth key(s) and session state\n */\n reset(withAuthKey = false): void {\n if (withAuthKey) {\n this.resetAuthKey()\n }\n\n clearTimeout(this.current429Timeout)\n this.resetState(withAuthKey)\n this.resetLastPing(true)\n }\n\n resetAuthKey(): void {\n this._authKey.reset()\n this._authKeyTemp.reset()\n this._authKeyTempSecondary.reset()\n }\n\n updateTimeOffset(offset: number) {\n this.log.debug('time offset updated: %d', offset)\n this._timeOffset = offset\n // lastMessageId was generated with (potentially) wrong time\n // reset it to avoid bigger issues - at worst, we'll get bad_msg_notification\n this._lastMessageId = Long.ZERO\n }\n\n /**\n * Reset session state and generate a new session ID.\n *\n * By default, also cancels any pending RPC requests.\n * If `keepPending` is set to `true`, pending requests will be kept\n */\n resetState(keepPending = false): void {\n this._lastMessageId = Long.ZERO\n this._seqNo = 0\n\n this._sessionId = randomLong()\n this.log.debug('session reset, new sid = %h', this._sessionId)\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n // reset session state\n\n if (!keepPending) {\n for (const info of this.pendingMessages.values()) {\n if (info._ === 'rpc') {\n this.log.debug('rejecting pending rpc %s', info.rpc.method)\n info.rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n this.pendingMessages.clear()\n }\n\n this.recentOutgoingMsgIds.clear()\n this.recentIncomingMsgIds.clear()\n\n if (!keepPending) {\n while (this.queuedRpc.length) {\n const rpc = this.queuedRpc.popFront()!\n\n if (rpc.sent === false) {\n this.log.debug('rejecting pending rpc %s', rpc.method)\n rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n }\n\n this.queuedAcks.length = 0\n this.queuedStateReq.length = 0\n this.queuedResendReq.length = 0\n this.queuedCancelReq.length = 0\n this.getStateSchedule.clear()\n this.chains.clear()\n this.chainsPendingFails.clear()\n }\n\n enqueueRpc(rpc: PendingRpc, force?: boolean): boolean {\n // already queued or cancelled\n if ((!force && !rpc.sent) || rpc.cancelled) return false\n\n rpc.sent = false\n rpc.containerId = undefined\n this.log.debug('enqueued %s for sending (msg_id = %s)', rpc.method, rpc.msgId || 'n/a')\n this.queuedRpc.pushBack(rpc)\n\n return true\n }\n\n getMessageId(): Long {\n const timeTicks = Date.now()\n const timeSec = Math.floor(timeTicks / 1000) - this._timeOffset\n const timeMSec = timeTicks % 1000\n const random = getRandomInt(0xffff)\n\n let messageId = new Long((timeMSec << 21) | (random << 3) | 4, timeSec)\n\n if (this._lastMessageId.ge(messageId)) {\n messageId = this._lastMessageId.add(4)\n }\n\n this._lastMessageId = messageId\n\n return messageId\n }\n\n getSeqNo(isContentRelated = true): number {\n let seqNo = this._seqNo\n\n if (isContentRelated) {\n seqNo += 1\n this._seqNo += 2\n }\n\n return seqNo\n }\n\n /** Encrypt a single MTProto message using session's keys */\n encryptMessage(message: Uint8Array): Uint8Array {\n const key = this._authKeyTemp.ready ? this._authKeyTemp : this._authKey\n\n return key.encryptMessage(message, this._salts.currentSalt, this._sessionId)\n }\n\n /** Decrypt a single MTProto message using session's keys */\n decryptMessage(data: Uint8Array, callback: Parameters<AuthKey['decryptMessage']>[2]): void {\n if (!this._authKey.ready) throw new MtcuteError('Keys are not set up!')\n\n const authKeyId = data.subarray(0, 8)\n\n let key: AuthKey\n\n if (this._authKey.match(authKeyId)) {\n key = this._authKey\n } else if (this._authKeyTemp.match(authKeyId)) {\n key = this._authKeyTemp\n } else if (this._authKeyTempSecondary.match(authKeyId)) {\n key = this._authKeyTempSecondary\n } else {\n this.log.warn(\n 'received message with unknown authKey = %h (expected %h or %h or %h)',\n authKeyId,\n this._authKey.id,\n this._authKeyTemp.id,\n this._authKeyTempSecondary.id,\n )\n\n return\n }\n\n return key.decryptMessage(data, this._sessionId, callback)\n }\n\n writeMessage(\n writer: TlBinaryWriter,\n content: tl.TlObject | mtp.TlObject | Uint8Array,\n isContentRelated = true,\n ): Long {\n const messageId = this.getMessageId()\n const seqNo = this.getSeqNo(isContentRelated)\n\n const length = ArrayBuffer.isView(content) ?\n content.length :\n TlSerializationCounter.countNeededBytes(writer.objectMap!, content)\n\n writer.long(messageId)\n writer.int(seqNo)\n writer.uint(length)\n if (ArrayBuffer.isView(content)) writer.raw(content)\n else writer.object(content as tl.TlObject)\n\n return messageId\n }\n\n onTransportFlood(callback: () => void) {\n if (this.current429Timeout) return // already waiting\n\n // all active queries must be resent after a timeout\n this.resetLastPing(true)\n\n const timeout = this.next429Timeout\n\n this.next429Timeout = Math.min(this.next429Timeout * 2, 32000)\n clearTimeout(this.current429Timeout)\n clearTimeout(this.next429ResetTimeout)\n\n this.current429Timeout = setTimeout(() => {\n this.current429Timeout = undefined\n callback()\n }, timeout)\n this.next429ResetTimeout = setTimeout(() => {\n this.next429ResetTimeout = undefined\n this.next429Timeout = 1000\n }, 60000)\n\n this.log.debug('transport flood, waiting for %d ms before proceeding', timeout)\n\n return Date.now() + timeout\n }\n\n resetLastPing(withTime = false): void {\n if (withTime) this.lastPingTime = 0\n\n if (!this.lastPingMsgId.isZero()) {\n this.pendingMessages.delete(this.lastPingMsgId)\n }\n\n this.lastPingMsgId = Long.ZERO\n }\n\n addToChain(chainId: string | number, msgId: Long): Long | undefined {\n const prevMsgId = this.chains.get(chainId)\n this.chains.set(chainId, msgId)\n\n this.log.debug('added message %l to chain %s (prev: %l)', msgId, chainId, prevMsgId)\n\n return prevMsgId\n }\n\n removeFromChain(chainId: string | number, msgId: Long): void {\n const lastMsgId = this.chains.get(chainId)\n\n if (!lastMsgId) {\n this.log.warn('tried to remove message %l from empty chain %s', msgId, chainId)\n\n return\n }\n\n if (lastMsgId.eq(msgId)) {\n // last message of the chain, remove it\n this.log.debug('chain %s: exhausted, last message %l', chainId, msgId)\n this.chains.delete(chainId)\n }\n\n // do nothing\n }\n\n getPendingChainedFails(chainId: string | number): SortedArray<PendingRpc> {\n let arr = this.chainsPendingFails.get(chainId)\n\n if (!arr) {\n arr = new SortedArray<PendingRpc>([], (a, b) => compareLongs(a.invokeAfter!, b.invokeAfter!))\n this.chainsPendingFails.set(chainId, arr)\n }\n\n return arr\n }\n}\n"]}
|
|
@@ -90,7 +90,7 @@ export class MultiSessionConnection extends EventEmitter {
|
|
|
90
90
|
for (let i = this._connections.length - 1; i >= this._count; i--) {
|
|
91
91
|
this._connections[i].removeAllListeners();
|
|
92
92
|
this._connections[i].destroy().catch((err) => {
|
|
93
|
-
this._log.warn('error destroying connection: %
|
|
93
|
+
this._log.warn('error destroying connection: %e', err);
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
this._connections.splice(this._count);
|
|
@@ -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 { mtp, 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 this.params.salts,\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().catch((err) => {\n this._log.warn('error destroying connection: %s', err)\n })\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('future-salts', (salts) => this.emit('future-salts', salts))\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('wait', () => this.emit('wait', 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 async destroy(): Promise<void> {\n await Promise.all(this._connections.map((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 timeout?: number,\n abortSignal?: AbortSignal,\n chainId?: string | number,\n ): Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error> {\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, timeout, abortSignal, chainId)\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 notifyNetworkChanged(connected: boolean): void {\n for (const conn of this._connections) {\n conn.notifyNetworkChanged(connected)\n }\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 { mtp, 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 this.params.salts,\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().catch((err) => {\n this._log.warn('error destroying connection: %e', err)\n })\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('future-salts', (salts) => this.emit('future-salts', salts))\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('wait', () => this.emit('wait', 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 async destroy(): Promise<void> {\n await Promise.all(this._connections.map((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 timeout?: number,\n abortSignal?: AbortSignal,\n chainId?: string | number,\n ): Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error> {\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, timeout, abortSignal, chainId)\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 notifyNetworkChanged(connected: boolean): void {\n for (const conn of this._connections) {\n conn.notifyNetworkChanged(connected)\n }\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,6 +1,7 @@
|
|
|
1
1
|
import { mtp, tl } from '@mtcute/tl';
|
|
2
2
|
import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime';
|
|
3
3
|
import { StorageManager } from '../storage/storage.js';
|
|
4
|
+
import { Middleware } from '../utils/composer.js';
|
|
4
5
|
import { DcOptions, ICryptoProvider, Logger } from '../utils/index.js';
|
|
5
6
|
import { ConfigManager } from './config-manager.js';
|
|
6
7
|
import { MultiSessionConnection } from './multi-session-connection.js';
|
|
@@ -22,8 +23,6 @@ export interface NetworkManagerParams {
|
|
|
22
23
|
initConnectionOptions?: Partial<Omit<tl.RawInitConnectionRequest, 'apiId' | 'query'>>;
|
|
23
24
|
transport: TransportFactory;
|
|
24
25
|
reconnectionStrategy?: ReconnectionStrategy<PersistentConnectionParams>;
|
|
25
|
-
floodSleepThreshold: number;
|
|
26
|
-
maxRetryCount: number;
|
|
27
26
|
disableUpdates?: boolean;
|
|
28
27
|
testMode: boolean;
|
|
29
28
|
layer: number;
|
|
@@ -71,6 +70,13 @@ export interface NetworkManagerExtraParams {
|
|
|
71
70
|
* @default 60000 (60 seconds).
|
|
72
71
|
*/
|
|
73
72
|
inactivityTimeout?: number;
|
|
73
|
+
/**
|
|
74
|
+
* List of middlewares to use for the network manager
|
|
75
|
+
*
|
|
76
|
+
* > **Note**: these middlewares apply to **outgoing requests only**.
|
|
77
|
+
* > If you need to handle incoming updates, use a {@link Dispatcher} instead.
|
|
78
|
+
*/
|
|
79
|
+
middlewares?: Middleware<RpcCallMiddlewareContext, unknown>[];
|
|
74
80
|
}
|
|
75
81
|
/** Options that can be customized when making an RPC call */
|
|
76
82
|
export interface RpcCallOptions {
|
|
@@ -80,14 +86,15 @@ export interface RpcCallOptions {
|
|
|
80
86
|
*
|
|
81
87
|
* If set to `0`, the call will not be retried.
|
|
82
88
|
*
|
|
83
|
-
*
|
|
89
|
+
* Only applies when the flood waiter middleware is enabled.
|
|
84
90
|
*/
|
|
85
91
|
floodSleepThreshold?: number;
|
|
86
92
|
/**
|
|
87
93
|
* If the call results in an internal server error or a flood wait,
|
|
88
94
|
* the maximum amount of times to retry the call.
|
|
89
95
|
*
|
|
90
|
-
*
|
|
96
|
+
* Only applies when the flood waiter middleware and/or
|
|
97
|
+
* internal errors handler middleware is enabled.
|
|
91
98
|
*/
|
|
92
99
|
maxRetryCount?: number;
|
|
93
100
|
/**
|
|
@@ -126,6 +133,9 @@ export interface RpcCallOptions {
|
|
|
126
133
|
*
|
|
127
134
|
* Useful for methods like `messages.getBotCallbackAnswer` that reliably return
|
|
128
135
|
* -503 in case the upstream bot failed to respond.
|
|
136
|
+
*
|
|
137
|
+
* Only applies if the internal error handler middleware is enabled,
|
|
138
|
+
* otherwise -503 is always thrown.
|
|
129
139
|
*/
|
|
130
140
|
throw503?: boolean;
|
|
131
141
|
/**
|
|
@@ -145,6 +155,12 @@ export interface RpcCallOptions {
|
|
|
145
155
|
*/
|
|
146
156
|
chainId?: string | number;
|
|
147
157
|
}
|
|
158
|
+
export interface RpcCallMiddlewareContext {
|
|
159
|
+
request: tl.RpcMethod;
|
|
160
|
+
manager: NetworkManager;
|
|
161
|
+
params?: RpcCallOptions;
|
|
162
|
+
}
|
|
163
|
+
export type RpcCallMiddleware<Result = unknown> = Middleware<RpcCallMiddlewareContext, Result>;
|
|
148
164
|
/**
|
|
149
165
|
* Wrapper over all connection pools for a single DC.
|
|
150
166
|
*/
|
|
@@ -220,8 +236,9 @@ export declare class NetworkManager {
|
|
|
220
236
|
resetSessions(): void;
|
|
221
237
|
private _onConfigChanged;
|
|
222
238
|
changePrimaryDc(newDc: number): Promise<void>;
|
|
223
|
-
|
|
224
|
-
|
|
239
|
+
readonly call: <T extends tl.RpcMethod>(message: T, params?: RpcCallOptions) => Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error>;
|
|
240
|
+
private _composeCall;
|
|
241
|
+
private _call;
|
|
225
242
|
changeTransport(factory: TransportFactory): void;
|
|
226
243
|
getPoolSize(kind: ConnectionKind, dcId?: number): number;
|
|
227
244
|
getPrimaryDcId(): number;
|