Browse Source

Upload files with HTTPS protocol

Forward chat rights
master
morethanwords 4 years ago
parent
commit
94db9c935e
  1. 10
      src/components/appSelectPeers.ts
  2. 2
      src/components/sidebarRight/tabs/forward.ts
  3. 2
      src/lib/appManagers/apiUpdatesManager.ts
  4. 4
      src/lib/appManagers/appChatsManager.ts
  5. 59
      src/lib/mtproto/apiManager.ts
  6. 91
      src/lib/mtproto/dcConfigurator.ts
  7. 179
      src/lib/mtproto/networker.ts
  8. 7
      src/lib/mtproto/networkerFactory.ts
  9. 2
      src/lib/mtproto/transports/websocket.ts
  10. 1
      webpack.common.js

10
src/components/appSelectPeers.ts

@ -2,7 +2,7 @@ import Scrollable from "./scrollable";
import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager"; import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager";
import { cancelEvent, findUpClassName, findUpAttribute } from "../lib/utils"; import { cancelEvent, findUpClassName, findUpAttribute } from "../lib/utils";
import appDialogsManager from "../lib/appManagers/appDialogsManager"; import appDialogsManager from "../lib/appManagers/appDialogsManager";
import appChatsManager from "../lib/appManagers/appChatsManager"; import appChatsManager, { ChatRights } from "../lib/appManagers/appChatsManager";
import appUsersManager from "../lib/appManagers/appUsersManager"; import appUsersManager from "../lib/appManagers/appUsersManager";
import appPeersManager from "../lib/appManagers/appPeersManager"; import appPeersManager from "../lib/appManagers/appPeersManager";
import appPhotosManager from "../lib/appManagers/appPhotosManager"; import appPhotosManager from "../lib/appManagers/appPhotosManager";
@ -37,7 +37,7 @@ export class AppSelectPeers {
private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {}; private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {};
constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: PeerType[] = ['dialogs'], onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void) { constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: PeerType[] = ['dialogs'], onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void, private chatRightsAction?: ChatRights) {
this.container.classList.add('selector'); this.container.classList.add('selector');
if(!this.renderResultsFunc) { if(!this.renderResultsFunc) {
@ -168,6 +168,12 @@ export class AppSelectPeers {
dialogs = dialogs.slice(); dialogs = dialogs.slice();
dialogs.findAndSplice(d => d.peerID == $rootScope.myID); // no my account dialogs.findAndSplice(d => d.peerID == $rootScope.myID); // no my account
if(this.chatRightsAction) {
dialogs = dialogs.filter(d => {
return d.peerID > 0 || appChatsManager.hasRights(-d.peerID, this.chatRightsAction);
});
}
this.renderSaved(); this.renderSaved();
this.offsetIndex = newOffsetIndex; this.offsetIndex = newOffsetIndex;

2
src/components/sidebarRight/tabs/forward.ts

@ -81,6 +81,6 @@ export default class AppForwardTab implements SliderTab {
appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.forward); appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.forward);
appSidebarRight.toggleSidebar(true); appSidebarRight.toggleSidebar(true);
document.body.classList.add('is-forward-active'); document.body.classList.add('is-forward-active');
}); }, null, 'send');
} }
} }

2
src/lib/appManagers/apiUpdatesManager.ts

@ -29,7 +29,7 @@ export class ApiUpdatesManager {
public channelStates: any = {}; public channelStates: any = {};
private attached = false; private attached = false;
private log = logger('UPDATES'/* , LogLevels.error */); private log = logger('UPDATES', LogLevels.error);
constructor() { constructor() {
appStateManager.addListener('save', () => { appStateManager.addListener('save', () => {

4
src/lib/appManagers/appChatsManager.ts

@ -59,6 +59,8 @@ export type Chat = {
default_banned_rights?: any default_banned_rights?: any
}; };
export type ChatRights = 'send' | 'edit_title' | 'edit_photo' | 'invite' | 'pin' | 'deleteRevoke';
export class AppChatsManager { export class AppChatsManager {
public chats: {[id: number]: Channel | Chat | any} = {}; public chats: {[id: number]: Channel | Chat | any} = {};
public usernames: any = {}; public usernames: any = {};
@ -149,7 +151,7 @@ export class AppChatsManager {
return this.chats[id] || {_: 'chatEmpty', id: id, deleted: true, access_hash: this.channelAccess[id]}; return this.chats[id] || {_: 'chatEmpty', id: id, deleted: true, access_hash: this.channelAccess[id]};
} }
public hasRights(id: number, action: 'send' | 'edit_title' | 'edit_photo' | 'invite' | 'pin' | 'deleteRevoke') { public hasRights(id: number, action: ChatRights) {
const chat = this.getChat(id); const chat = this.getChat(id);
if(chat._ == 'chatEmpty') return false; if(chat._ == 'chatEmpty') return false;

59
src/lib/mtproto/apiManager.ts

@ -1,21 +1,17 @@
import AppStorage from '../storage'; import AppStorage from '../storage';
import { MTPNetworker } from './networker'; import MTPNetworker from './networker';
import { bytesFromHex, bytesToHex, isObject } from '../bin_utils'; import { bytesFromHex, bytesToHex, isObject } from '../bin_utils';
import networkerFactory from './networkerFactory'; import networkerFactory from './networkerFactory';
//import { telegramMeWebService } from './mtproto'; //import { telegramMeWebService } from './mtproto';
import authorizer from './authorizer'; import authorizer from './authorizer';
import {App, Modes, MOUNT_CLASS_TO} from './mtproto_config'; import {App, Modes, MOUNT_CLASS_TO} from './mtproto_config';
import dcConfigurator from './dcConfigurator'; import dcConfigurator, { ConnectionType, TransportType } from './dcConfigurator';
import { logger } from '../logger'; import { logger } from '../logger';
import type { InvokeApiOptions } from '../../types'; import type { InvokeApiOptions } from '../../types';
import type { MethodDeclMap } from '../../layer'; import type { MethodDeclMap } from '../../layer';
import { CancellablePromise, deferredPromise } from '../../helpers/cancellablePromise'; import { CancellablePromise, deferredPromise } from '../../helpers/cancellablePromise';
/// #if MTPROTO_HTTP
import HTTP from './transports/http';
/// #endif
/// #if !MTPROTO_WORKER /// #if !MTPROTO_WORKER
import $rootScope from '../rootScope'; import $rootScope from '../rootScope';
/// #endif /// #endif
@ -35,8 +31,14 @@ export type ApiError = Partial<{
}>; }>;
export class ApiManager { export class ApiManager {
public cachedNetworkers: {[x: number]: MTPNetworker} = {}; public cachedNetworkers: {
public cachedUploadNetworkers: {[x: number]: MTPNetworker} = {}; [transportType in TransportType]: {
[connectionType in ConnectionType]: {
[dcID: number]: MTPNetworker
}
}
} = {} as any;
public cachedExportPromise: {[x: number]: Promise<unknown>} = {}; public cachedExportPromise: {[x: number]: Promise<unknown>} = {};
private gettingNetworkers: {[dcIDAndType: string]: Promise<MTPNetworker>} = {}; private gettingNetworkers: {[dcIDAndType: string]: Promise<MTPNetworker>} = {};
public baseDcID = 0; public baseDcID = 0;
@ -115,27 +117,30 @@ export class ApiManager {
} }
// mtpGetNetworker // mtpGetNetworker
public async getNetworker(dcID: number, options: InvokeApiOptions = {}): Promise<MTPNetworker> { public getNetworker(dcID: number, options: InvokeApiOptions = {}): Promise<MTPNetworker> {
/// #if MTPROTO_HTTP
// @ts-ignore
const upload = (options.fileUpload || options.fileDownload);
/// #else
// @ts-ignore
const upload = (options.fileUpload || options.fileDownload) && Modes.multipleConnections;
/// #endif
const transport = dcConfigurator.chooseServer(dcID, upload);
const cache = upload ? this.cachedUploadNetworkers : this.cachedNetworkers;
if(!dcID) { if(!dcID) {
throw new Error('get Networker without dcID'); throw new Error('get Networker without dcID');
} }
const connectionType: ConnectionType = options.fileDownload ? 'download' : (options.fileUpload ? 'upload' : 'client');
const transportType: TransportType = connectionType == 'upload' ? 'https' : 'websocket';
const transport = dcConfigurator.chooseServer(dcID, connectionType, transportType);
if(!this.cachedNetworkers.hasOwnProperty(transportType)) {
this.cachedNetworkers[transportType] = {
client: {},
download: {},
upload: {}
};
}
const cache = this.cachedNetworkers[transportType][connectionType];
if(cache[dcID] !== undefined) { if(cache[dcID] !== undefined) {
return cache[dcID]; return Promise.resolve(cache[dcID]);
} }
const getKey = dcID + '-' + +upload; const getKey = [dcID, transportType, connectionType].join('-');
if(this.gettingNetworkers[getKey]) { if(this.gettingNetworkers[getKey]) {
return this.gettingNetworkers[getKey]; return this.gettingNetworkers[getKey];
} }
@ -146,12 +151,6 @@ export class ApiManager {
return this.gettingNetworkers[getKey] = AppStorage.get<string[]/* |boolean[] */>([ak, akID, ss]) return this.gettingNetworkers[getKey] = AppStorage.get<string[]/* |boolean[] */>([ak, akID, ss])
.then(async([authKeyHex, authKeyIDHex, serverSaltHex]) => { .then(async([authKeyHex, authKeyIDHex, serverSaltHex]) => {
/* if(authKeyHex && !authKeyIDHex && serverSaltHex) {
this.log.warn('Updating to new version (+akID)');
await AppStorage.remove(ak, akID, ss);
authKeyHex = serverSaltHex = '';
} */
let networker: MTPNetworker; let networker: MTPNetworker;
if(authKeyHex && authKeyHex.length == 512) { if(authKeyHex && authKeyHex.length == 512) {
if(!serverSaltHex || serverSaltHex.length != 16) { if(!serverSaltHex || serverSaltHex.length != 16) {
@ -162,7 +161,7 @@ export class ApiManager {
const authKeyID = new Uint8Array(bytesFromHex(authKeyIDHex)); const authKeyID = new Uint8Array(bytesFromHex(authKeyIDHex));
const serverSalt = bytesFromHex(serverSaltHex); const serverSalt = bytesFromHex(serverSaltHex);
networker = networkerFactory.getNetworker(dcID, authKey, authKeyID, serverSalt, options); networker = networkerFactory.getNetworker(dcID, authKey, authKeyID, serverSalt, transport, options);
} else { } else {
try { // if no saved state try { // if no saved state
const auth = await authorizer.auth(dcID); const auth = await authorizer.auth(dcID);
@ -175,7 +174,7 @@ export class ApiManager {
AppStorage.set(storeObj); AppStorage.set(storeObj);
networker = networkerFactory.getNetworker(dcID, auth.authKey, auth.authKeyID, auth.serverSalt, options); networker = networkerFactory.getNetworker(dcID, auth.authKey, auth.authKeyID, auth.serverSalt, transport, options);
} catch(error) { } catch(error) {
this.log('Get networker error', error, error.stack); this.log('Get networker error', error, error.stack);
delete this.gettingNetworkers[getKey]; delete this.gettingNetworkers[getKey];

91
src/lib/mtproto/dcConfigurator.ts

@ -1,13 +1,27 @@
import MTTransport from './transports/transport'; import MTTransport from './transports/transport';
import { Modes } from './mtproto_config'; import { Modes } from './mtproto_config';
/// #if !MTPROTO_HTTP /// #if MTPROTO_HTTP_UPLOAD
// @ts-ignore
import Socket from './transports/websocket';
// @ts-ignore
import HTTP from './transports/http';
/// #elif !MTPROTO_HTTP
// @ts-ignore
import Socket from './transports/websocket'; import Socket from './transports/websocket';
/// #else /// #else
// @ts-ignore
import HTTP from './transports/http'; import HTTP from './transports/http';
/// #endif /// #endif
export type TransportType = 'websocket' | 'https' | 'http';
export type ConnectionType = 'client' | 'download' | 'upload';
type Servers = { type Servers = {
[dcID: number]: MTTransport[] [transportType in TransportType]: {
[connectionType in ConnectionType]: {
[dcID: number]: MTTransport[]
}
}
}; };
export class DcConfigurator { export class DcConfigurator {
@ -27,13 +41,45 @@ export class DcConfigurator {
{id: 5, host: '149.154.171.5', port: 80} {id: 5, host: '149.154.171.5', port: 80}
]; ];
private chosenServers: Servers = {}; private chosenServers: Servers = {} as any;
private chosenUploadServers: Servers = {};
public chooseServer(dcID: number, upload?: boolean) { private transportSocket = (dcID: number, connectionType: ConnectionType) => {
const servers = upload && Modes.multipleConnections const subdomain = this.sslSubdomains[dcID - 1];
? this.chosenUploadServers const path = Modes.test ? 'apiws_test' : 'apiws';
: this.chosenServers; const chosenServer = 'wss://' + subdomain + '.web.telegram.org/' + path;
return new Socket(dcID, chosenServer, connectionType != 'client' ? '-U' : '');
};
private transportHTTP = (dcID: number, connectionType: ConnectionType) => {
if(Modes.ssl || !Modes.http) {
const subdomain = this.sslSubdomains[dcID - 1] + (connectionType != 'client' ? '-1' : '');
const path = Modes.test ? 'apiw_test1' : 'apiw1';
const chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path;
return new HTTP(dcID, chosenServer);
} else {
for(let dcOption of this.dcOptions) {
if(dcOption.id == dcID) {
const chosenServer = 'http://' + dcOption.host + (dcOption.port != 80 ? ':' + dcOption.port : '') + '/apiw1';
return new HTTP(dcID, chosenServer);
}
}
}
};
public chooseServer(dcID: number, connectionType: ConnectionType = 'client', transportType: TransportType = 'websocket') {
/* if(transportType == 'websocket' && !Modes.multipleConnections) {
connectionType = 'client';
} */
if(!this.chosenServers.hasOwnProperty(transportType)) {
this.chosenServers[transportType] = {
client: {},
download: {},
upload: {}
};
}
const servers = this.chosenServers[transportType][connectionType];
if(!(dcID in servers)) { if(!(dcID in servers)) {
servers[dcID] = []; servers[dcID] = [];
@ -41,32 +87,15 @@ export class DcConfigurator {
const transports = servers[dcID]; const transports = servers[dcID];
if(!transports.length || (upload && transports.length < 1)) { if(!transports.length/* || (upload && transports.length < 1) */) {
let transport: MTTransport; let transport: MTTransport;
/// #if !MTPROTO_HTTP /// #if MTPROTO_HTTP_UPLOAD
//if(transportType == 'websocket') { transport = (transportType == 'websocket' ? this.transportSocket : this.transportHTTP)(dcID, connectionType);
const subdomain = this.sslSubdomains[dcID - 1]; /// #elif !MTPROTO_HTTP
const path = Modes.test ? 'apiws_test' : 'apiws'; transport = this.transportSocket(dcID, connectionType);
const chosenServer = 'wss://' + subdomain + '.web.telegram.org/' + path;
transport = new Socket(dcID, chosenServer, upload ? '-U' : '');
//} else
/// #else /// #else
// @ts-ignore transport = this.transportHTTP(dcID, connectionType);
if(Modes.ssl || !Modes.http) {
const subdomain = this.sslSubdomains[dcID - 1] + (upload ? '-1' : '');
const path = Modes.test ? 'apiw_test1' : 'apiw1';
const chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path;
transport = new HTTP(dcID, chosenServer);
} else {
for(let dcOption of this.dcOptions) {
if(dcOption.id == dcID) {
const chosenServer = 'http://' + dcOption.host + (dcOption.port != 80 ? ':' + dcOption.port : '') + '/apiw1';
transport = new HTTP(dcID, chosenServer);
break;
}
}
}
/// #endif /// #endif
if(!transport) { if(!transport) {

179
src/lib/mtproto/networker.ts

@ -9,17 +9,23 @@ import Schema from './schema';
import timeManager from './timeManager'; import timeManager from './timeManager';
import NetworkerFactory from './networkerFactory'; import NetworkerFactory from './networkerFactory';
import dcConfigurator from './dcConfigurator';
import { logger, LogLevels } from '../logger'; import { logger, LogLevels } from '../logger';
import { Modes, App } from './mtproto_config'; import { Modes, App } from './mtproto_config';
import { InvokeApiOptions } from '../../types'; import { InvokeApiOptions } from '../../types';
import { longToBytes } from '../crypto/crypto_utils'; import { longToBytes } from '../crypto/crypto_utils';
import MTTransport from './transports/transport'; import MTTransport from './transports/transport';
/// #if MTPROTO_HTTP /// #if MTPROTO_HTTP_UPLOAD
import type HTTP from './transports/http'; // @ts-ignore
import HTTP from './transports/http';
// @ts-ignore
import Socket from './transports/websocket';
/// #elif MTPROTO_HTTP
// @ts-ignore
import HTTP from './transports/http';
/// #else /// #else
import type Socket from './transports/websocket'; // @ts-ignore
import Socket from './transports/websocket';
/// #endif /// #endif
//console.error('networker included!', new Error().stack); //console.error('networker included!', new Error().stack);
@ -62,7 +68,7 @@ type Message = InvokeApiOptions & MessageOptions & {
noResponse?: true, // only with http (http_wait for longPoll) noResponse?: true, // only with http (http_wait for longPoll)
}; };
class MTPNetworker { export default class MTPNetworker {
private authKeyUint8: Uint8Array; private authKeyUint8: Uint8Array;
private upload: boolean; private upload: boolean;
@ -73,19 +79,18 @@ class MTPNetworker {
[msgID: string]: Message [msgID: string]: Message
} = {}; } = {};
private pendingMessages: any = {}; private pendingMessages: {[msgID: string]: number} = {};
private pendingAcks: Array<string> = []; private pendingAcks: Array<string> = [];
private pendingResends: Array<string> = []; private pendingResends: Array<string> = [];
private connectionInited = false; private connectionInited = false;
/// #if MTPROTO_HTTP /// #if MTPROTO_HTTP || MTPROTO_HTTP_UPLOAD
//private longPollInt: number; //private longPollInt: number;
private longPollPending = 0; private longPollPending = 0;
private nextReqTimeout: number; private nextReqTimeout: number;
private nextReq: number = 0; private nextReq: number = 0;
private checkConnectionTimeout: number; private checkConnectionTimeout: number;
private checkConnectionPeriod = 0; private checkConnectionPeriod = 0;
private onOnlineCb = this.checkConnection.bind(this);
private sleepAfter = 0; private sleepAfter = 0;
private offline = false; private offline = false;
/// #endif /// #endif
@ -99,19 +104,20 @@ class MTPNetworker {
resend_msg_ids: Array<string> resend_msg_ids: Array<string>
} | null = null; } | null = null;
private transport: MTTransport; //private transport: MTTransport;
private log: ReturnType<typeof logger>; private log: ReturnType<typeof logger>;
constructor(private dcID: number, private authKey: number[], private authKeyID: Uint8Array, constructor(private dcID: number, private authKey: number[], private authKeyID: Uint8Array,
private serverSalt: number[], private options: InvokeApiOptions = {}) { private serverSalt: number[], private transport: MTTransport, private options: InvokeApiOptions = {}) {
this.authKeyUint8 = convertToUint8Array(this.authKey); this.authKeyUint8 = convertToUint8Array(this.authKey);
//this.authKeyID = sha1BytesSync(this.authKey).slice(-8); //this.authKeyID = sha1BytesSync(this.authKey).slice(-8);
//console.trace('Create', dcID, options); //console.trace('Create', dcID, options);
this.upload = this.options.fileUpload || this.options.fileDownload; this.upload = this.options.fileUpload || this.options.fileDownload;
this.log = logger('NET-' + dcID + (this.upload ? '-U' : ''), this.upload && this.dcID == 2 ? LogLevels.debug | LogLevels.warn | LogLevels.log | LogLevels.error : LogLevels.error); //this.log = logger('NET-' + dcID + (this.upload ? '-U' : ''), this.upload && this.dcID == 2 ? LogLevels.debug | LogLevels.warn | LogLevels.log | LogLevels.error : LogLevels.error);
this.log = logger('NET-' + dcID + (this.upload ? '-U' : ''), LogLevels.log | LogLevels.error);
this.log('constructor'/* , this.authKey, this.authKeyID, this.serverSalt */); this.log('constructor'/* , this.authKey, this.authKeyID, this.serverSalt */);
/* // Test resend after bad_server_salt /* // Test resend after bad_server_salt
@ -127,9 +133,14 @@ class MTPNetworker {
// $rootScope.offlineConnecting = true */ // $rootScope.offlineConnecting = true */
// } // }
this.transport = dcConfigurator.chooseServer(this.dcID, this.upload); /// #if MTPROTO_HTTP_UPLOAD
if(this.transport instanceof HTTP) {
/// #if MTPROTO_HTTP /* this.longPollInt = */setInterval(this.checkLongPoll.bind(this), 10000);
this.checkLongPoll();
} else {
(this.transport as Socket).networker = this;
}
/// #elif MTPROTO_HTTP
//if(this.transport instanceof HTTP) { //if(this.transport instanceof HTTP) {
/* this.longPollInt = */setInterval(this.checkLongPoll.bind(this), 10000); /* this.longPollInt = */setInterval(this.checkLongPoll.bind(this), 10000);
this.checkLongPoll(); this.checkLongPoll();
@ -294,10 +305,10 @@ class MTPNetworker {
return this.pushMessage(message, options); return this.pushMessage(message, options);
} }
/// #if MTPROTO_HTTP /// #if MTPROTO_HTTP || MTPROTO_HTTP_UPLOAD
public checkLongPoll() { public checkLongPoll() {
const isClean = this.cleanupSent(); const isClean = this.cleanupSent();
//this.log('Check lp', this.longPollPending, tsNow(), this.dcID, isClean, this); //this.log.error('Check lp', this.longPollPending, this.dcID, isClean, this);
if((this.longPollPending && Date.now() < this.longPollPending) || if((this.longPollPending && Date.now() < this.longPollPending) ||
this.offline) { this.offline) {
//this.log('No lp this time'); //this.log('No lp this time');
@ -339,7 +350,7 @@ class MTPNetworker {
}); });
} }
public checkConnection(event: Event | string) { public checkConnection = (event: Event | string) => {
/* $rootScope.offlineConnecting = true */ /* $rootScope.offlineConnecting = true */
this.log('Check connection', event); this.log('Check connection', event);
@ -373,7 +384,7 @@ class MTPNetworker {
delete $rootScope.offlineConnecting delete $rootScope.offlineConnecting
}, 1000); */ }, 1000); */
}); });
} };
public toggleOffline(enabled: boolean) { public toggleOffline(enabled: boolean) {
// this.log('toggle ', enabled, this.dcID, this.iii) // this.log('toggle ', enabled, this.dcID, this.iii)
@ -397,21 +408,71 @@ class MTPNetworker {
this.checkConnectionTimeout = setTimeout(this.checkConnection.bind(this), this.checkConnectionPeriod * 1000 | 0); this.checkConnectionTimeout = setTimeout(this.checkConnection.bind(this), this.checkConnectionPeriod * 1000 | 0);
this.checkConnectionPeriod = Math.min(30, (1 + this.checkConnectionPeriod) * 1.5); this.checkConnectionPeriod = Math.min(30, (1 + this.checkConnectionPeriod) * 1.5);
document.body.addEventListener('online', this.onOnlineCb, false); document.body.addEventListener('online', this.checkConnection, false);
document.body.addEventListener('focus', this.onOnlineCb, false); document.body.addEventListener('focus', this.checkConnection, false);
} else { } else {
this.checkLongPoll(); this.checkLongPoll();
this.scheduleRequest(); this.scheduleRequest();
document.body.removeEventListener('online', this.onOnlineCb); document.body.removeEventListener('online', this.checkConnection);
document.body.removeEventListener('focus', this.onOnlineCb); document.body.removeEventListener('focus', this.checkConnection);
clearTimeout(this.checkConnectionTimeout); clearTimeout(this.checkConnectionTimeout);
this.checkConnectionTimeout = 0; this.checkConnectionTimeout = 0;
} }
} }
private handleSentEncryptedRequestHTTP(promise: ReturnType<MTPNetworker['sendEncryptedRequest']>, message: Message, noResponseMsgs: string[]) {
promise
.then((result) => {
this.toggleOffline(false);
// this.log('parse for', message)
this.parseResponse(result).then((response) => {
if(Modes.debug) {
this.log('Server response', this.dcID, response);
}
this.processMessage(response.response, response.messageID, response.sessionID);
noResponseMsgs.forEach((msgID) => {
if(this.sentMessages[msgID]) {
var deferred = this.sentMessages[msgID].deferred;
delete this.sentMessages[msgID];
deferred.resolve();
}
});
this.checkLongPoll();
this.checkConnectionPeriod = Math.max(1.1, Math.sqrt(this.checkConnectionPeriod));
});
}, (error) => {
this.log.error('Encrypted request failed', error, message);
if(message.container) {
message.inner.forEach((msgID: string) => {
this.pendingMessages[msgID] = 0;
});
delete this.sentMessages[message.msg_id];
} else {
this.pendingMessages[message.msg_id] = 0;
}
noResponseMsgs.forEach((msgID) => {
if(this.sentMessages[msgID]) {
var deferred = this.sentMessages[msgID].deferred;
delete this.sentMessages[msgID];
delete this.pendingMessages[msgID];
deferred.reject();
}
})
this.toggleOffline(true);
});
}
/// #endif /// #endif
// тут можно сделать таймаут и выводить дисконнект // тут можно сделать таймаут и выводить дисконнект
@ -502,7 +563,7 @@ class MTPNetworker {
public performScheduledRequest() { public performScheduledRequest() {
// this.log('scheduled', this.dcID, this.iii) // this.log('scheduled', this.dcID, this.iii)
/// #if MTPROTO_HTTP /// #if MTPROTO_HTTP || MTPROTO_HTTP_UPLOAD
if(this.offline) { if(this.offline) {
this.log('Cancel scheduled'); this.log('Cancel scheduled');
return false; return false;
@ -597,8 +658,11 @@ class MTPNetworker {
} }
} }
/// #if MTPROTO_HTTP /// #if MTPROTO_HTTP_UPLOAD
if(hasApiCall && !hasHttpWait/* && this.transport instanceof HTTP */) { if(this.transport instanceof HTTP)
/// #endif
/// #if MTPROTO_HTTP || MTPROTO_HTTP_UPLOAD
if(hasApiCall && !hasHttpWait) {
var serializer = new TLSerialization({mtproto: true}); var serializer = new TLSerialization({mtproto: true});
serializer.storeMethod('http_wait', { serializer.storeMethod('http_wait', {
max_delay: 500, max_delay: 500,
@ -670,57 +734,18 @@ class MTPNetworker {
let promise = this.sendEncryptedRequest(message); let promise = this.sendEncryptedRequest(message);
/// #if !MTPROTO_HTTP /// #if MTPROTO_HTTP_UPLOAD
if(!(this.transport instanceof HTTP)) {
if(noResponseMsgs.length) this.log.error('noResponseMsgs length!', noResponseMsgs);
} else {
this.handleSentEncryptedRequestHTTP(promise, message, noResponseMsgs);
}
/// #elif !MTPROTO_HTTP
//if(!(this.transport instanceof HTTP)) { //if(!(this.transport instanceof HTTP)) {
if(noResponseMsgs.length) this.log.error('noResponseMsgs length!', noResponseMsgs); if(noResponseMsgs.length) this.log.error('noResponseMsgs length!', noResponseMsgs);
//} else { //} else {
/// #else /// #else
promise.then((result) => { this.handleSentEncryptedRequestHTTP(promise, message, noResponseMsgs);
self.toggleOffline(false);
// this.log('parse for', message)
self.parseResponse(result).then((response) => {
if(Modes.debug) {
this.log('Server response', self.dcID, response);
}
self.processMessage(response.response, response.messageID, response.sessionID);
noResponseMsgs.forEach((msgID) => {
if(self.sentMessages[msgID]) {
var deferred = self.sentMessages[msgID].deferred;
delete self.sentMessages[msgID];
deferred.resolve();
}
});
self.checkLongPoll();
this.checkConnectionPeriod = Math.max(1.1, Math.sqrt(this.checkConnectionPeriod));
});
}, (error) => {
this.log.error('Encrypted request failed', error, message);
if(message.container) {
message.inner.forEach((msgID: string) => {
self.pendingMessages[msgID] = 0;
});
delete self.sentMessages[message.msg_id];
} else {
self.pendingMessages[message.msg_id] = 0;
}
noResponseMsgs.forEach((msgID) => {
if(self.sentMessages[msgID]) {
var deferred = self.sentMessages[msgID].deferred;
delete self.sentMessages[msgID];
delete self.pendingMessages[msgID];
deferred.reject();
}
})
self.toggleOffline(true);
});
//} //}
/// #endif /// #endif
@ -807,9 +832,10 @@ class MTPNetworker {
} }
const promise = this.transport.send(requestData); const promise = this.transport.send(requestData);
/// #if !MTPROTO_HTTP /// #if !MTPROTO_HTTP && !MTPROTO_HTTP_UPLOAD
/* if(!(this.transport instanceof HTTP)) */ return promise; /* if(!(this.transport instanceof HTTP)) */ return promise;
/// #else /// #else
if(!(this.transport instanceof HTTP)) return promise;
return promise.then((result) => { return promise.then((result) => {
if(!result || !result.byteLength) { if(!result || !result.byteLength) {
@ -955,12 +981,13 @@ class MTPNetworker {
} }
public scheduleRequest(delay = 0) { public scheduleRequest(delay = 0) {
/// #if !MTPROTO_HTTP /// #if !MTPROTO_HTTP && !MTPROTO_HTTP_UPLOAD
/* clearTimeout(this.nextReqTimeout); /* clearTimeout(this.nextReqTimeout);
this.nextReqTimeout = self.setTimeout(this.performScheduledRequest.bind(this), delay || 0); this.nextReqTimeout = self.setTimeout(this.performScheduledRequest.bind(this), delay || 0);
return; */ return; */
return this.performScheduledRequest(); return this.performScheduledRequest();
/// #else /// #else
if(!(this.transport instanceof HTTP)) return this.performScheduledRequest();
if(this.offline/* && this.transport instanceof HTTP */) { if(this.offline/* && this.transport instanceof HTTP */) {
this.checkConnection('forced schedule'); this.checkConnection('forced schedule');
} }
@ -1127,7 +1154,7 @@ class MTPNetworker {
break; break;
case 'bad_msg_notification': case 'bad_msg_notification':
this.log('Bad msg notification', message); this.log.error('Bad msg notification', message);
var sentMessage = this.sentMessages[message.bad_msg_id]; var sentMessage = this.sentMessages[message.bad_msg_id];
if(!sentMessage || sentMessage.seq_no != message.bad_msg_seqno) { if(!sentMessage || sentMessage.seq_no != message.bad_msg_seqno) {
this.log(message.bad_msg_id, message.bad_msg_seqno); this.log(message.bad_msg_id, message.bad_msg_seqno);
@ -1268,5 +1295,3 @@ class MTPNetworker {
} }
} }
} }
export {MTPNetworker};

7
src/lib/mtproto/networkerFactory.ts

@ -1,5 +1,6 @@
import { MTPNetworker } from "./networker"; import MTPNetworker from "./networker";
import { InvokeApiOptions } from "../../types"; import { InvokeApiOptions } from "../../types";
import MTTransport from "./transports/transport";
export class NetworkerFactory { export class NetworkerFactory {
public updatesProcessor: (obj: any, bool: boolean) => void = null; public updatesProcessor: (obj: any, bool: boolean) => void = null;
@ -8,9 +9,9 @@ export class NetworkerFactory {
this.updatesProcessor = callback; this.updatesProcessor = callback;
} }
public getNetworker(dcID: number, authKey: number[], authKeyID: Uint8Array, serverSalt: number[], options: InvokeApiOptions) { public getNetworker(dcID: number, authKey: number[], authKeyID: Uint8Array, serverSalt: number[], transport: MTTransport, options: InvokeApiOptions) {
//console.log('NetworkerFactory: creating new instance of MTPNetworker:', dcID, options); //console.log('NetworkerFactory: creating new instance of MTPNetworker:', dcID, options);
return new MTPNetworker(dcID, authKey, authKeyID, serverSalt, options); return new MTPNetworker(dcID, authKey, authKeyID, serverSalt, transport, options);
} }
} }

2
src/lib/mtproto/transports/websocket.ts

@ -2,7 +2,7 @@ import MTTransport from './transport';
//import abridgetPacketCodec from './abridged'; //import abridgetPacketCodec from './abridged';
import intermediatePacketCodec from './intermediate'; import intermediatePacketCodec from './intermediate';
import {MTPNetworker} from '../networker'; import MTPNetworker from '../networker';
import { logger, LogLevels } from '../../logger'; import { logger, LogLevels } from '../../logger';
import Obfuscation from './obfuscation'; import Obfuscation from './obfuscation';

1
webpack.common.js

@ -17,6 +17,7 @@ if(devMode) {
const opts = { const opts = {
MTPROTO_WORKER: true, MTPROTO_WORKER: true,
MTPROTO_HTTP: false, MTPROTO_HTTP: false,
MTPROTO_HTTP_UPLOAD: true,
DEBUG: devMode, DEBUG: devMode,
version: 3, version: 3,
"ifdef-verbose": devMode, // add this for verbose output "ifdef-verbose": devMode, // add this for verbose output

Loading…
Cancel
Save