diff --git a/src/lib/mtproto/apiFileManager.ts b/src/lib/mtproto/apiFileManager.ts index fdd402f1..e79582da 100644 --- a/src/lib/mtproto/apiFileManager.ts +++ b/src/lib/mtproto/apiFileManager.ts @@ -234,14 +234,14 @@ export class ApiFileManager extends AppManager { const invoke = async(): Promise => { checkCancel && checkCancel(); // do not remove async, because checkCancel will throw an error - const promise = this.apiManager.invokeApi('upload.getFile', { + const promise = /* pause(1000).then(() => */this.apiManager.invokeApi('upload.getFile', { location, offset, limit }, { dcId, fileDownload: true - }) as Promise; + }) as Promise/* ) */; return promise.catch((err) => { if(err.type === 'FILE_REFERENCE_EXPIRED') { diff --git a/src/lib/mtproto/apiManager.ts b/src/lib/mtproto/apiManager.ts index 54a1558b..cbbab997 100644 --- a/src/lib/mtproto/apiManager.ts +++ b/src/lib/mtproto/apiManager.ts @@ -9,10 +9,6 @@ * https://github.com/zhukov/webogram/blob/master/LICENSE */ -/// #if !MTPROTO_WORKER -import rootScope from '../rootScope'; -/// #endif - /// #if MTPROTO_AUTO import transportController from './transports/controller'; import MTTransport from './transports/transport'; @@ -21,16 +17,14 @@ import MTTransport from './transports/transport'; import type { UserAuth } from './mtproto_config'; import sessionStorage from '../sessionStorage'; import MTPNetworker, { MTMessage } from './networker'; -//import { telegramMeWebService } from './mtproto'; -import { ConnectionType, DcConfigurator, TransportType } from './dcConfigurator'; +import { ConnectionType, constructTelegramWebSocketUrl, DcConfigurator, TransportType } from './dcConfigurator'; import { logger } from '../logger'; import type { DcAuthKey, DcId, DcServerSalt, InvokeApiOptions } from '../../types'; import type { MethodDeclMap } from '../../layer'; import deferredPromise, { CancellablePromise } from '../../helpers/cancellablePromise'; -//import { clamp } from '../../helpers/number'; import App from '../../config/app'; import { MOUNT_CLASS_TO } from '../../config/debug'; -import IDBStorage, { IDB } from '../idb'; +import { IDB } from '../idb'; import CryptoWorker from "../crypto/cryptoMessagePort"; import ctx from '../../environment/ctx'; import noop from '../../helpers/noop'; @@ -41,21 +35,8 @@ import isObject from '../../helpers/object/isObject'; import pause from '../../helpers/schedulers/pause'; import ApiManagerMethods from './api_methods'; import { getEnvironment } from '../../environment/utils'; -import AppStorage from '../storage'; import toggleStorages from '../../helpers/toggleStorages'; - -/* var networker = apiManager.cachedNetworkers.websocket.upload[2]; -networker.wrapMtpMessage({ - _: 'msgs_state_req', - msg_ids: ["6888292542796810828"] -}, { - notContentRelated: true -}).then((res) => { - console.log('status', res); -}); */ - -//console.error('apiManager included!'); -// TODO: если запрос словил флуд, нужно сохранять его параметры и возвращать тот же промис на новый такой же запрос, например - загрузка истории +import type TcpObfuscated from './transports/tcpObfuscated'; export type ApiError = Partial<{ code: number, @@ -137,6 +118,25 @@ export class ApiManager extends ApiManagerMethods { this.getAppConfig(true); } }); + + this.rootScope.addEventListener('premium_toggle', (isPremium) => { + this.iterateNetworkers(({networker, connectionType, dcId, transportType}) => { + if(connectionType === 'client' || transportType !== 'websocket') { + return; + } + + const transport = networker.transport; + if(!transport) { + this.log.error('wow what, no transport?', networker); + return; + } + + if((transport as TcpObfuscated).connection) { + const url = constructTelegramWebSocketUrl(dcId, connectionType, isPremium); + (transport as TcpObfuscated).changeUrl(url); + } + }); + }); } //private lol = false; @@ -348,7 +348,7 @@ export class ApiManager extends ApiManagerMethods { // @ts-ignore const maxNetworkers = connectionType === 'client' || transportType === 'https' ? 1 : (this.rootScope.premium ? PREMIUM_FILE_NETWORKERS_COUNT : REGULAR_FILE_NETWORKERS_COUNT); if(networkers.length >= maxNetworkers) { - let i = networkers.length - 1, found = false; + let i = maxNetworkers - 1, found = false; for(; i >= 0; --i) { if(networkers[i].isOnline) { found = true; @@ -356,7 +356,7 @@ export class ApiManager extends ApiManagerMethods { } } - const networker = found ? networkers.splice(i, 1)[0] : networkers.pop(); + const networker = networkers.splice(found ? i : maxNetworkers - 1, 1)[0]; networkers.unshift(networker); return Promise.resolve(networker); } @@ -443,6 +443,15 @@ export class ApiManager extends ApiManagerMethods { networker.changeTransport(transport); } + private onNetworkerDrain(networker: MTPNetworker) { + this.log('networker drain', networker.dcId); + networker.onDrain = undefined; + this.changeNetworkerTransport(networker); + networker.destroy(); + this.networkerFactory.removeNetworker(networker); + DcConfigurator.removeTransport(this.cachedNetworkers, networker); + } + public setOnDrainIfNeeded(networker: MTPNetworker) { if(networker.onDrain) { return; @@ -457,16 +466,7 @@ export class ApiManager extends ApiManagerMethods { } if(canRelease) { - networker.onDrain = () => { - this.log('networker drain', networker.dcId); - - networker.onDrain = undefined; - this.changeNetworkerTransport(networker); - networker.destroy(); - this.networkerFactory.removeNetworker(networker); - DcConfigurator.removeTransport(this.cachedNetworkers, networker); - }; - + networker.onDrain = () => this.onNetworkerDrain(networker); networker.setDrainTimeout(); } }); @@ -645,7 +645,7 @@ export class ApiManager extends ApiManagerMethods { options.waitTime = options.waitTime ? Math.min(60, options.waitTime * 1.5) : 1; return pause(options.waitTime * 1000).then(() => performRequest()); - } else if(error.type === 'UNKNOWN') { + } else if(error.type === 'UNKNOWN' || error.type === 'MTPROTO_CLUSTER_INVALID') { // cluster invalid - request from regular user to premium endpoint return pause(1000).then(() => performRequest()); } else { throw error; diff --git a/src/lib/mtproto/dcConfigurator.ts b/src/lib/mtproto/dcConfigurator.ts index 63cde200..1621e056 100644 --- a/src/lib/mtproto/dcConfigurator.ts +++ b/src/lib/mtproto/dcConfigurator.ts @@ -44,6 +44,20 @@ type Servers = { const TEST_SUFFIX = Modes.test ? '_test' : ''; const PREMIUM_SUFFIX = '_premium'; +export function getTelegramConnectionSuffix(connectionType: ConnectionType) { + return connectionType === 'client' ? '' : '-1'; +} + +/// #if MTPROTO_HAS_WS +export function constructTelegramWebSocketUrl(dcId: DcId, connectionType: ConnectionType, premium?: boolean) { + const suffix = getTelegramConnectionSuffix(connectionType); + const path = connectionType !== 'client' ? 'apiws' + (premium ? PREMIUM_SUFFIX : TEST_SUFFIX) : ('apiws' + TEST_SUFFIX); + const chosenServer = `wss://${App.suffix.toLowerCase()}ws${dcId}${suffix}.web.telegram.org/${path}`; + + return chosenServer; +} +/// #endif + export class DcConfigurator { private sslSubdomains = ['pluto', 'venus', 'aurora', 'vesta', 'flora']; @@ -64,9 +78,8 @@ export class DcConfigurator { public chosenServers: Servers = {} as any; /// #if MTPROTO_HAS_WS - private transportSocket = (dcId: DcId, connectionType: ConnectionType, suffix: string, premium?: boolean) => { - const path = connectionType !== 'client' ? 'apiws' + (premium ? PREMIUM_SUFFIX : TEST_SUFFIX) : ('apiws' + TEST_SUFFIX); - const chosenServer = `wss://${App.suffix.toLowerCase()}ws${dcId}${suffix}.web.telegram.org/${path}`; + private transportSocket = (dcId: DcId, connectionType: ConnectionType, premium?: boolean) => { + const chosenServer = constructTelegramWebSocketUrl(dcId, connectionType, premium); const logSuffix = connectionType === 'upload' ? '-U' : connectionType === 'download' ? '-D' : ''; const retryTimeout = connectionType === 'client' ? 10000 : 10000; @@ -83,10 +96,11 @@ export class DcConfigurator { /// #endif /// #if MTPROTO_HAS_HTTP - private transportHTTP = (dcId: DcId, connectionType: ConnectionType, suffix: string, premium?: boolean) => { + private transportHTTP = (dcId: DcId, connectionType: ConnectionType, premium?: boolean) => { let chosenServer: string; if(Modes.ssl || !Modes.http) { - const subdomain = this.sslSubdomains[dcId - 1] + (connectionType !== 'client' ? '-1' : ''); + const suffix = getTelegramConnectionSuffix(connectionType); + const subdomain = this.sslSubdomains[dcId - 1] + suffix; const path = Modes.test ? 'apiw_test1' : 'apiw1'; chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path; } else { @@ -133,14 +147,12 @@ export class DcConfigurator { if(!transports.length || !reuse/* || (upload && transports.length < 1) */) { let transport: MTTransport; - const suffix = connectionType === 'client' ? '' : '-1'; - /// #if MTPROTO_HAS_WS && MTPROTO_HAS_HTTP - transport = (transportType === 'websocket' ? this.transportSocket : this.transportHTTP)(dcId, connectionType, suffix, premium); + transport = (transportType === 'websocket' ? this.transportSocket : this.transportHTTP)(dcId, connectionType, premium); /// #elif !MTPROTO_HTTP - transport = this.transportSocket(dcId, connectionType, suffix, premium); + transport = this.transportSocket(dcId, connectionType, premium); /// #else - transport = this.transportHTTP(dcId, connectionType, suffix, premium); + transport = this.transportHTTP(dcId, connectionType, premium); /// #endif if(!transport) { diff --git a/src/lib/mtproto/transports/tcpObfuscated.ts b/src/lib/mtproto/transports/tcpObfuscated.ts index 0b9988eb..832cd837 100644 --- a/src/lib/mtproto/transports/tcpObfuscated.ts +++ b/src/lib/mtproto/transports/tcpObfuscated.ts @@ -265,6 +265,15 @@ export default class TcpObfuscated implements MTTransport { this.connection.addEventListener('message', this.onMessage); } + public changeUrl(url: string) { + if(this.url === url) { + return; + } + + this.url = url; + this.forceReconnect(); + } + private encodeBody(body: Uint8Array) { const toEncode = this.codec.encodePacket(body);