feat(core): change transport at runtime

This commit is contained in:
teidesu 2021-05-23 13:35:03 +03:00
parent 256b219247
commit 1c4d9c1ab3
2 changed files with 41 additions and 8 deletions

View file

@ -215,7 +215,7 @@ export class BaseTelegramClient {
// not really connected, but rather "connect() was called" // not really connected, but rather "connect() was called"
private _connected = false private _connected = false
private _onError?: (err: Error) => void private _onError?: (err: Error, connection?: TelegramConnection) => void
/** /**
* The primary {@link TelegramConnection} that is used for * The primary {@link TelegramConnection} that is used for
@ -354,7 +354,7 @@ export class BaseTelegramClient {
this.storage.setAuthKeyFor(this._primaryDc.id, key) this.storage.setAuthKeyFor(this._primaryDc.id, key)
await this._saveStorage() await this._saveStorage()
}) })
this.primaryConnection.on('error', (err) => this._emitError(err)) this.primaryConnection.on('error', (err) => this._emitError(err, this.primaryConnection))
} }
/** /**
@ -587,7 +587,7 @@ export class BaseTelegramClient {
inactivityTimeout, inactivityTimeout,
}) })
connection.on('error', (err) => this._emitError(err)) connection.on('error', (err) => this._emitError(err, connection))
connection.authKey = await this.storage.getAuthKeyFor(dc.id) connection.authKey = await this.storage.getAuthKeyFor(dc.id)
connection.connect() connection.connect()
@ -629,13 +629,38 @@ export class BaseTelegramClient {
this._additionalConnections.splice(idx, 1) this._additionalConnections.splice(idx, 1)
} }
onError(handler: (err: Error) => void): void { /**
* Change transport for the client.
*
* Can be used, for example, to change proxy at runtime
*
* This effectively calls `changeTransport()` on
* `primaryConnection` and all additional connections.
*
* @param factory New transport factory
*/
changeTransport(factory: TransportFactory): void {
this.primaryConnection.changeTransport(factory)
this._additionalConnections.forEach((conn) => conn.changeTransport(factory))
}
/**
* Register an error handler for the client
*
* @param handler
* Error handler. Called with one or two parameters.
* The first one is always the error, and the second is
* the connection in which the error has occurred, in case
* this was connection-related error.
*/
onError(handler: (err: Error, connection?: TelegramConnection) => void): void {
this._onError = handler this._onError = handler
} }
protected _emitError(err: Error): void { protected _emitError(err: Error, connection?: TelegramConnection): void {
if (this._onError) { if (this._onError) {
this._onError(err) this._onError(err, connection)
} else { } else {
console.error(err) console.error(err)
} }

View file

@ -53,8 +53,16 @@ export abstract class PersistentConnection extends EventEmitter {
protected constructor(params: PersistentConnectionParams) { protected constructor(params: PersistentConnectionParams) {
super() super()
this.params = params this.params = params
this._transport = params.transportFactory() this.changeTransport(params.transportFactory)
this._transport.setupCrypto?.(params.crypto) }
changeTransport(factory: TransportFactory): void {
if (this._transport) {
this._transport.close()
}
this._transport = factory()
this._transport.setupCrypto?.(this.params.crypto)
this._transport.on('ready', this.onTransportReady.bind(this)) this._transport.on('ready', this.onTransportReady.bind(this))
this._transport.on('message', this.onTransportMessage.bind(this)) this._transport.on('message', this.onTransportMessage.bind(this))