Fix connection in Safari

This commit is contained in:
morethanwords 2021-02-15 13:26:26 +04:00
parent 201dde75a3
commit 90af398b77
8 changed files with 110 additions and 60 deletions

View File

@ -158,8 +158,8 @@ export class ApiManager {
// mtpGetNetworker
public getNetworker(dcId: number, options: InvokeApiOptions = {}): Promise<MTPNetworker> {
//const connectionType: ConnectionType = options.fileDownload ? 'download' : (options.fileUpload ? 'upload' : 'client');
const connectionType: ConnectionType = 'client';
const connectionType: ConnectionType = options.fileDownload ? 'download' : (options.fileUpload ? 'upload' : 'client');
//const connectionType: ConnectionType = 'client';
/// #if MTPROTO_HTTP_UPLOAD
// @ts-ignore
@ -184,7 +184,7 @@ export class ApiManager {
}
const networkers = cache[dcId];
if(networkers.length >= /* 1 */(connectionType === 'client' || transportType === 'https' ? 1 : (connectionType === 'download' ? 3 : 1))) {
if(networkers.length >= /* 1 */(connectionType === 'client' || transportType === 'https' ? 1 : (connectionType === 'download' ? 3 : 3))) {
let i = networkers.length - 1, found = false;
for(; i >= 0; --i) {
if(networkers[i].isOnline) {

View File

@ -52,7 +52,7 @@ class SocketProxied extends EventListenerBase<{
});
}
send = (payload: Uint8Array) => {
public send(payload: Uint8Array) {
const task: any = {
type: 'socketProxy',
payload: {
@ -63,7 +63,19 @@ class SocketProxied extends EventListenerBase<{
};
notifyAll(task);
};
}
public close() {
const task: any = {
type: 'socketProxy',
payload: {
type: 'close',
id: this.id
}
};
notifyAll(task);
}
}
export const socketsProxied: Map<number, SocketProxied> = new Map();
@ -94,9 +106,9 @@ export class DcConfigurator {
const chosenServer = 'wss://' + subdomain + '.web.telegram.org/' + path;
const logSuffix = connectionType === 'upload' ? '-U' : connectionType === 'download' ? '-D' : '';
const retryTimeout = connectionType === 'client' ? 30000 : 10000;
const retryTimeout = connectionType === 'client' ? 15000 : 10000;
const oooohLetMeLive: MTConnectionConstructable = (isSafari && isWebWorker) || true ? SocketProxied : Socket;
const oooohLetMeLive: MTConnectionConstructable = (isSafari && isWebWorker) /* || true */ ? SocketProxied : Socket;
return new TcpObfuscated(oooohLetMeLive, dcId, chosenServer, logSuffix, retryTimeout);
};

View File

@ -198,6 +198,9 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
if(socketTask.type === 'send') {
const socket = this.sockets.get(id);
socket.send(socketTask.payload);
} else if(socketTask.type === 'close') {
const socket = this.sockets.get(id);
socket.close();
} else if(socketTask.type === 'setup') {
const socket = new Socket(socketTask.payload.dcId, socketTask.payload.url, socketTask.payload.logSuffix);

View File

@ -11,8 +11,8 @@ import { InvokeApiOptions } from '../../types';
import { longToBytes } from '../crypto/crypto_utils';
import MTTransport from './transports/transport';
import { convertToUint8Array, bufferConcat, bytesCmp, bytesToHex } from '../../helpers/bytes';
import { nextRandomInt } from '../../helpers/random';
import { CancellablePromise } from '../../helpers/cancellablePromise';
import { nextRandomInt, randomLong } from '../../helpers/random';
import { CancellablePromise, deferredPromise } from '../../helpers/cancellablePromise';
import { isSafari } from '../../helpers/userAgent';
import App from '../../config/app';
import DEBUG from '../../config/debug';
@ -116,8 +116,6 @@ export default class MTPNetworker {
private lastResponseTime = 0;
private disconnectDelay: number;
private pingPromise: CancellablePromise<any>;
private sentPingTimes = 0;
private tt = 0;
//public onConnectionStatusChange: (online: boolean) => void;
private debugRequests: Array<{before: Uint8Array, after: Uint8Array}> = [];
@ -171,15 +169,11 @@ export default class MTPNetworker {
/// #endif
// * handle outcoming dead socket, server will close the connection
if((this.transport as TcpObfuscated).networker) {
if(isSafari) {
this.pingPromise = Promise.resolve();
} else {
this.disconnectDelay = (this.transport as TcpObfuscated).retryTimeout / 1000 | 0;
//setInterval(this.sendPingDelayDisconnect, (this.disconnectDelay - 5) * 1000);
// ! this.sendPingDelayDisconnect();
}
}
// if((this.transport as TcpObfuscated).networker) {
// this.disconnectDelay = /* (this.transport as TcpObfuscated).retryTimeout */75;
// //setInterval(this.sendPingDelayDisconnect, (this.disconnectDelay - 5) * 1000);
// this.sendPingDelayDisconnect();
// }
}
public updateSession() {
@ -401,6 +395,52 @@ export default class MTPNetworker {
// });
// };
// private sendPingDelayDisconnect = () => {
// if(this.pingPromise || true) return;
// /* if(!this.isOnline) {
// if((this.transport as TcpObfuscated).connected) {
// (this.transport as TcpObfuscated).connection.close();
// }
// return;
// } */
// const deferred = this.pingPromise = deferredPromise<void>();
// const timeoutTime = this.disconnectDelay * 1000;
// const startTime = Date.now();
// this.wrapMtpCall('ping_delay_disconnect', {
// ping_id: randomLong(),
// disconnect_delay: this.disconnectDelay
// }, {}).then(pong => {
// const elapsedTime = Date.now() - startTime;
// this.log('sendPingDelayDisconnect: response', pong, elapsedTime > timeoutTime);
// if(elapsedTime > timeoutTime) {
// deferred.reject();
// } else {
// setTimeout(deferred.resolve, timeoutTime - elapsedTime);
// }
// }, deferred.reject).finally(() => {
// clearTimeout(rejectTimeout);
// //--this.sentPingTimes;
// });
// const rejectTimeout = self.setTimeout(deferred.reject, timeoutTime);
// deferred.catch(() => {
// this.log.error('sendPingDelayDisconnect: catch, closing connection if exists');
// (this.transport as TcpObfuscated).connection.close();
// });
// deferred.finally(() => {
// this.pingPromise = null;
// this.sendPingDelayDisconnect();
// });
// };
/// #if MTPROTO_HTTP || MTPROTO_HTTP_UPLOAD
public checkLongPoll = () => {
const isClean = this.cleanupSent();
@ -640,9 +680,9 @@ export default class MTPNetworker {
});
}
/* if(!this.pingPromise && (this.transport as TcpObfuscated).networker) {
this.sendPingDelayDisconnect();
} */
// if((this.transport as TcpObfuscated).networker) {
// this.sendPingDelayDisconnect();
// }
/* this.sentPingTimes = 0;
this.sendPingDelayDisconnect(); */
}

View File

@ -95,8 +95,8 @@ export default class Obfuscation {
/* this.enc = new aesjs.ModeOfOperation.ctr(encKey, new aesjs.Counter(encIv as any));
this.dec = new aesjs.ModeOfOperation.ctr(decKey, new aesjs.Counter(decIv as any)); */
console.log('encKey', encKey.hex, encIv.hex);
console.log('decKey', decKey.hex, decIv.hex);
// console.log('encKey', encKey.hex, encIv.hex);
// console.log('decKey', decKey.hex, decIv.hex);
this.encNew = new CTR(encKey, encIv);
this.decNew = new CTR(decKey, decIv);

View File

@ -19,21 +19,17 @@ export default class TcpObfuscated implements MTTransport {
}>> = [];
private debug = Modes.debug && false;
private log: ReturnType<typeof logger>;
public connected = false;
private lastCloseTime: number;
private connection: MTConnection;
public connection: MTConnection;
//private debugPayloads: MTPNetworker['debugRequests'] = [];
constructor(private Connection: MTConnectionConstructable, private dcId: number, private url: string, private logSuffix: string, public retryTimeout: number) {
let logLevel = LogLevels.error | LogLevels.log;
if(this.debug) logLevel |= LogLevels.debug;
this.log = logger(`WS-${dcId}` + logSuffix, logLevel);
this.log = logger(`TCP-${dcId}` + logSuffix, logLevel);
this.log('constructor');
this.connect();
@ -53,6 +49,12 @@ export default class TcpObfuscated implements MTTransport {
}
}
for(const pending of this.pending) {
if(pending.encoded && pending.body) {
pending.encoded = this.encodeBody(pending.body);
}
}
setTimeout(() => {
this.releasePending();
}, 0);

View File

@ -10,6 +10,7 @@ export interface MTConnection extends EventListenerBase<{
close: () => void,
}> {
send: (data: Uint8Array) => void;
close: () => void;
}
export interface MTConnectionConstructable {

View File

@ -25,10 +25,15 @@ export default class Socket extends EventListenerBase<{
}
private removeListeners() {
if(!this.ws) {
return;
}
this.ws.removeEventListener('open', this.handleOpen);
this.ws.removeEventListener('close', this.handleClose);
this.ws.removeEventListener('error', this.handleError);
this.ws.removeEventListener('message', this.handleMessage);
this.ws = undefined;
}
private connect() {
@ -39,58 +44,45 @@ export default class Socket extends EventListenerBase<{
this.ws.addEventListener('error', this.handleError);
this.ws.addEventListener('message', this.handleMessage);
}
public close() {
if(!this.ws) {
return;
}
this.log.error('close execution');
this.ws.close();
this.handleClose();
}
handleOpen = () => {
private handleOpen = () => {
this.log('opened');
this.debug && this.log.debug('sending init packet');
this.setListenerResult('open');
};
handleError = (e: Event) => {
private handleError = (e: Event) => {
this.log.error(e);
};
handleClose = () => {
private handleClose = () => {
this.log('closed'/* , event, this.pending, this.ws.bufferedAmount */);
this.removeListeners();
this.setListenerResult('close');
};
handleMessage = (event: MessageEvent) => {
private handleMessage = (event: MessageEvent) => {
this.debug && this.log.debug('<-', 'handleMessage', /* event, */event.data.byteLength);
this.setListenerResult('message', event.data as ArrayBuffer);
};
send = (body: Uint8Array) => {
public send = (body: Uint8Array) => {
this.debug && this.log.debug('-> body length to send:', body.length);
this.ws.send(body);
};
}
/* const setupSafariFix = () => {
};
if(isWebWorker) {
import('../../polyfill').then(() => {
//ctx.postMessage('ready');
let socket: Socket;
ctx.addEventListener('message', (e) => {
console.log('websocket worker message', e);
const task = e.data;
if(task.type === 'send') {
// const promise = socket.send(task.payload);
// if(task.taskId) {
// promise
// }
} else if(task.type === 'setup') {
socket = new Socket(task.dcId, task.url, task.logSuffix, task.retryTimeout);
}
});
});
} */