From bd5130c77b280673af49e5179f7d74e0460f73a5 Mon Sep 17 00:00:00 2001 From: teidesu <86301490+teidesu@users.noreply.github.com> Date: Tue, 8 Nov 2022 06:50:49 +0300 Subject: [PATCH] fix(core): use existing auth_key from storage --- packages/core/src/base-client.ts | 4 +- .../src/network/multi-session-connection.ts | 22 +++++- packages/core/src/network/network-manager.ts | 71 +++++++++++++------ .../core/src/network/session-connection.ts | 8 +-- 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/packages/core/src/base-client.ts b/packages/core/src/base-client.ts index 3c47eb5b..44770b95 100644 --- a/packages/core/src/base-client.ts +++ b/packages/core/src/base-client.ts @@ -334,6 +334,7 @@ export class BaseTelegramClient extends EventEmitter { storage: this.storage, testMode: this._testMode, transport: opts.transport, + _emitError: this._emitError.bind(this), ...(opts.network ?? {}), }, this._config) @@ -881,9 +882,8 @@ export class BaseTelegramClient extends EventEmitter { } } - await this.storage.updatePeers(parsedPeers) - if (count > 0) { + await this.storage.updatePeers(parsedPeers) this.log.debug('cached %d peers', count) } diff --git a/packages/core/src/network/multi-session-connection.ts b/packages/core/src/network/multi-session-connection.ts index 18cb16b8..0b718dfa 100644 --- a/packages/core/src/network/multi-session-connection.ts +++ b/packages/core/src/network/multi-session-connection.ts @@ -10,7 +10,7 @@ import { MtprotoSession } from './mtproto-session' export class MultiSessionConnection extends EventEmitter { private _log: Logger - private _sessions: MtprotoSession[] + readonly _sessions: MtprotoSession[] constructor( readonly params: SessionConnectionParams, @@ -88,6 +88,7 @@ export class MultiSessionConnection extends EventEmitter { if (this._connections.length > this._count) { // destroy extra connections for (let i = this._connections.length - 1; i >= this._count; i--) { + this._connections[i].removeAllListeners() this._connections[i].destroy() } @@ -97,10 +98,17 @@ export class MultiSessionConnection extends EventEmitter { // create new connections for (let i = this._connections.length; i < this._count; i++) { - const session = this.params.isMainConnection ? this._sessions[i] : this._sessions[0] + const session = this.params.isMainConnection + ? this._sessions[i] + : this._sessions[0] const conn = new SessionConnection(this.params, session) conn.on('update', (update) => this.emit('update', update)) + conn.on('error', (err) => this.emit('error', err, conn)) + conn.on('key-change', (key) => this.emit('key-change', i, key)) + conn.on('tmp-key-change', (key, expires) => + this.emit('tmp-key-change', i, key, expires) + ) this._connections.push(conn) } @@ -128,7 +136,9 @@ export class MultiSessionConnection extends EventEmitter { let minIdx = 0 for (let i = 0; i < this._connections.length; i++) { const conn = this._connections[i] - const total = conn._session.queuedRpc.length + conn._session.pendingMessages.size() + const total = + conn._session.queuedRpc.length + + conn._session.pendingMessages.size() if (total < min) { min = total @@ -157,4 +167,10 @@ export class MultiSessionConnection extends EventEmitter { conn.connect() } } + + async setAuthKey(authKey: Buffer | null, temp = false, idx = 0): Promise { + const session = this._sessions[idx] + const key = temp ? session._authKeyTemp : session._authKey + await key.setup(authKey) + } } diff --git a/packages/core/src/network/network-manager.ts b/packages/core/src/network/network-manager.ts index 7cbe7b8c..3c5c718d 100644 --- a/packages/core/src/network/network-manager.ts +++ b/packages/core/src/network/network-manager.ts @@ -10,16 +10,10 @@ import { import { PersistentConnectionParams } from './persistent-connection' import { ConfigManager } from './config-manager' import { MultiSessionConnection } from './multi-session-connection' -import { SessionConnectionParams } from './session-connection' +import { SessionConnection, SessionConnectionParams } from "./session-connection"; import { ITelegramStorage } from '../storage' export class DcConnectionManager { - constructor( - readonly manager: NetworkManager, - readonly dcId: number, - private _dc: tl.RawDcOption - ) {} - private __baseConnectionParams = (): SessionConnectionParams => ({ crypto: this.manager.params.crypto, initConnection: this.manager._initConnectionParams, @@ -43,6 +37,38 @@ export class DcConnectionManager { 1, this.manager._log ) + + constructor( + readonly manager: NetworkManager, + readonly dcId: number, + private _dc: tl.RawDcOption + ) { + this._setupStorageHandlers(this.mainConnection) + } + + private _setupStorageHandlers(connection: MultiSessionConnection): void { + connection.on('key-change', (idx, key) => { + this.manager._log.debug('key change for dc %d from connection %d', this.dcId, idx) + this.manager._storage.setAuthKeyFor(this.dcId, key) + }) + connection.on('tmp-key-change', (idx, key, expires) => { + this.manager._log.debug('temp key change for dc %d from connection %d', this.dcId, idx) + this.manager._storage.setTempAuthKeyFor(this.dcId, idx, key, expires * 1000) + }) + } + + async loadKeys(): Promise { + const permanent = await this.manager._storage.getAuthKeyFor(this.dcId) + + await this.mainConnection.setAuthKey(permanent) + + if (this.manager.params.usePfs) { + for (let i = 0; i < this.mainConnection._sessions.length; i++) { + const temp = await this.manager._storage.getAuthKeyFor(this.dcId, i) + await this.mainConnection.setAuthKey(temp, true, i) + } + } + } } /** @@ -66,6 +92,7 @@ export interface NetworkManagerParams { layer: number readerMap: TlReaderMap writerMap: TlWriterMap + _emitError: (err: Error, connection?: SessionConnection) => void } /** @@ -82,6 +109,7 @@ export interface NetworkManagerExtraParams { export class NetworkManager { readonly _log = this.params.log.create('network') + readonly _storage = this.params.storage readonly _initConnectionParams: tl.RawInitConnectionRequest readonly _transportFactory: TransportFactory @@ -92,6 +120,8 @@ export class NetworkManager { private _keepAliveInterval?: NodeJS.Timeout private _keepAliveAction = this._defaultKeepAliveAction.bind(this) + private _lastUpdateTime = 0 + private _updateHandler: (upd: tl.TypeUpdates) => void = () => {} private _defaultKeepAliveAction(): void { if (this._keepAliveInterval) return @@ -160,9 +190,7 @@ export class NetworkManager { this._primaryDc = dc - // todo add handlers - /* - this.primaryConnection.on('usable', () => { + dc.mainConnection.on('usable', () => { this._lastUpdateTime = Date.now() if (this._keepAliveInterval) clearInterval(this._keepAliveInterval) @@ -173,22 +201,19 @@ export class NetworkManager { } }, 60_000) }) - this.primaryConnection.on('update', (update) => { + dc.mainConnection.on('update', (update) => { this._lastUpdateTime = Date.now() - this._handleUpdate(update) + this._updateHandler(update) }) - this.primaryConnection.on('wait', () => - this._cleanupPrimaryConnection() + // dc.mainConnection.on('wait', () => + // this._cleanupPrimaryConnection() + // ) + dc.mainConnection.on('error', (err, conn) => + this.params._emitError(err, conn) ) - this.primaryConnection.on('key-change', async (key) => { - this.storage.setAuthKeyFor(this._defaultDc.id, key) - await this._saveStorage() - }) - this.primaryConnection.on('error', (err) => - this._emitError(err, this.primaryConnection) - ) - */ - dc.mainConnection.connect() + dc.loadKeys() + .catch((e) => this.params._emitError(e)) + .then(() => dc.mainConnection.connect()) } /** diff --git a/packages/core/src/network/session-connection.ts b/packages/core/src/network/session-connection.ts index 23d2b5b3..4bfad440 100644 --- a/packages/core/src/network/session-connection.ts +++ b/packages/core/src/network/session-connection.ts @@ -41,7 +41,7 @@ import { import { TransportError } from './transports' import { createAesIgeForMessageOld } from '../utils/crypto/mtproto' -const TEMP_AUTH_KEY_EXPIRY = 300 // 86400 fixme +const TEMP_AUTH_KEY_EXPIRY = 86400 export interface SessionConnectionParams extends PersistentConnectionParams { initConnection: tl.RawInitConnectionRequest @@ -57,7 +57,7 @@ export interface SessionConnectionParams extends PersistentConnectionParams { } // destroy_auth_key#d1435160 = DestroyAuthKeyRes; -const DESTROY_AUTH_KEY = Buffer.from('605134d1', 'hex') +// const DESTROY_AUTH_KEY = Buffer.from('605134d1', 'hex') function makeNiceStack( error: tl.errors.RpcError, @@ -160,7 +160,7 @@ export class SessionConnection extends PersistentConnection { this._authorize() // todo: if we use pfs, we can also start temp key exchange here } else if (this.params.usePfs && !this._session._authKeyTemp.ready) { - this.log.info('no perm auth key but using pfs, authorizing') + this.log.info('no temp auth key but using pfs, authorizing') this._authorizePfs() } else { this.log.info('auth keys are already available') @@ -234,7 +234,7 @@ export class SessionConnection extends PersistentConnection { } } - this.emit('err', error) + this.emit('error', error) } protected onConnectionUsable() {