Browse Source

Network:

Fix reconnecting
Fix resending answers
Try ping_disconnect_delay again
master
Eduard Kuzmenko 3 years ago
parent
commit
fa4df7ee4b
  1. 4
      src/lib/mtproto/apiManager.ts
  2. 476
      src/lib/mtproto/networker.ts

4
src/lib/mtproto/apiManager.ts

@ -76,6 +76,8 @@ export type ApiError = Partial<{
} }
} */ } */
const FILE_NETWORKERS_COUNT = 3;
export class ApiManager { export class ApiManager {
private cachedNetworkers: { private cachedNetworkers: {
[transportType in TransportType]: { [transportType in TransportType]: {
@ -321,7 +323,7 @@ export class ApiManager {
const networkers = cache[dcId]; const networkers = cache[dcId];
// @ts-ignore // @ts-ignore
const maxNetworkers = connectionType === 'client' || transportType === 'https' ? 1 : (connectionType === 'download' ? 3 : 3); const maxNetworkers = connectionType === 'client' || transportType === 'https' ? 1 : FILE_NETWORKERS_COUNT;
if(networkers.length >= maxNetworkers) { if(networkers.length >= maxNetworkers) {
let i = networkers.length - 1, found = false; let i = networkers.length - 1, found = false;
for(; i >= 0; --i) { for(; i >= 0; --i) {

476
src/lib/mtproto/networker.ts

@ -41,6 +41,8 @@ import isObject from '../../helpers/object/isObject';
import forEachReverse from '../../helpers/array/forEachReverse'; import forEachReverse from '../../helpers/array/forEachReverse';
import sortLongsArray from '../../helpers/long/sortLongsArray'; import sortLongsArray from '../../helpers/long/sortLongsArray';
import randomize from '../../helpers/array/randomize'; import randomize from '../../helpers/array/randomize';
import { CancellablePromise, deferredPromise } from '../../helpers/cancellablePromise';
import { pause } from '../../helpers/schedulers/pause';
//console.error('networker included!', new Error().stack); //console.error('networker included!', new Error().stack);
@ -50,6 +52,7 @@ export type MTMessageOptions = InvokeApiOptions & Partial<{
notContentRelated: true, // ACK notContentRelated: true, // ACK
noSchedule: true, noSchedule: true,
// withResult: true,
messageId: MTLong, messageId: MTLong,
}>; }>;
@ -62,10 +65,7 @@ export type MTMessage = InvokeApiOptions & MTMessageOptions & {
acked?: boolean, acked?: boolean,
deferred?: { deferred?: CancellablePromise<void>,
resolve: any,
reject: any
},
container?: boolean, container?: boolean,
inner?: MTLong[], inner?: MTLong[],
@ -81,8 +81,35 @@ export type MTMessage = InvokeApiOptions & MTMessageOptions & {
noResponse?: true, // only with http (http_wait for longPoll) noResponse?: true, // only with http (http_wait for longPoll)
}; };
const CONNECTION_TIMEOUT = 5000;
const DRAIN_TIMEOUT = 10000; const DRAIN_TIMEOUT = 10000;
const delays: {
[k in 'client' | 'file']: {
disconnectDelayMin: number,
disconnectDelayMax: number,
pingInterval: number,
pingMaxTime: number,
connectionTimeout: number
}
} = {
client: {
disconnectDelayMin: 7,
disconnectDelayMax: 20,
pingInterval: 2000,
pingMaxTime: 5,
connectionTimeout: 5000
},
file: {
disconnectDelayMin: 10,
disconnectDelayMax: 24,
pingInterval: 3000,
pingMaxTime: 7,
connectionTimeout: 7500
}
};
const RESEND_OPTIONS: MTMessageOptions = {
noSchedule: true,
notContentRelated: true
};
let invokeAfterMsgConstructor: number; let invokeAfterMsgConstructor: number;
export default class MTPNetworker { export default class MTPNetworker {
@ -100,7 +127,8 @@ export default class MTPNetworker {
private pendingMessages: {[msgId: MTLong]: number} = {}; private pendingMessages: {[msgId: MTLong]: number} = {};
private pendingAcks: Array<MTLong> = []; private pendingAcks: Array<MTLong> = [];
private pendingResends: Array<MTLong> = []; private pendingResendReq: MTLong[] = [];
// private pendingResendAnsReq: MTLong[] = [];
public connectionInited: boolean; public connectionInited: boolean;
private nextReqTimeout: number; private nextReqTimeout: number;
@ -123,15 +151,16 @@ export default class MTPNetworker {
private serverSalt: Uint8Array; private serverSalt: Uint8Array;
private lastResendReq: { private lastResendReq: {
req_msg_id: MTLong, reqMsgId: MTLong,
resend_msg_ids: Array<MTLong> msgIds: MTPNetworker['pendingResendReq']
} | null = null; };
// private lastResendAnsReq: MTPNetworker['lastResendReq'];
private name: string; private name: string;
private log: ReturnType<typeof logger>; private log: ReturnType<typeof logger>;
public isOnline = false; public isOnline = false;
public status: ConnectionStatus = ConnectionStatus.Closed; private status: ConnectionStatus = ConnectionStatus.Closed;
private lastResponseTime = 0; private lastResponseTime = 0;
private debug = DEBUG /* && false */ || Modes.debug; private debug = DEBUG /* && false */ || Modes.debug;
@ -143,12 +172,19 @@ export default class MTPNetworker {
public transport: MTTransport; public transport: MTTransport;
//private disconnectDelay: number; /// #if MTPROTO_HAS_WS
//private pingPromise: CancellablePromise<any>; private pingDelayDisconnectDeferred: CancellablePromise<string>;
private pingPromise: Promise<void>;
// private pingInterval: number;
private lastPingTime: number;
private lastPingDelayDisconnectId: string;
/// #endif
//public onConnectionStatusChange: (online: boolean) => void; //public onConnectionStatusChange: (online: boolean) => void;
//private debugRequests: Array<{before: Uint8Array, after: Uint8Array}> = []; //private debugRequests: Array<{before: Uint8Array, after: Uint8Array}> = [];
private delays: typeof delays[keyof typeof delays];
constructor( constructor(
public dcId: number, public dcId: number,
private authKey: Uint8Array, private authKey: Uint8Array,
@ -162,6 +198,7 @@ export default class MTPNetworker {
this.isFileUpload = !!options.fileUpload; this.isFileUpload = !!options.fileUpload;
this.isFileDownload = !!options.fileDownload; this.isFileDownload = !!options.fileDownload;
this.isFileNetworker = this.isFileUpload || this.isFileDownload; this.isFileNetworker = this.isFileUpload || this.isFileDownload;
this.delays = this.isFileNetworker ? delays.file : delays.client;
const suffix = this.isFileUpload ? '-U' : this.isFileDownload ? '-D' : ''; const suffix = this.isFileUpload ? '-U' : this.isFileDownload ? '-D' : '';
this.name = 'NET-' + dcId + suffix; this.name = 'NET-' + dcId + suffix;
@ -182,13 +219,6 @@ export default class MTPNetworker {
// /* rootScope.offline = true // /* rootScope.offline = true
// rootScope.offlineConnecting = true */ // rootScope.offlineConnecting = true */
// } // }
// * handle outcoming dead socket, server will close the connection
// if((this.transport as TcpObfuscated).networker) {
// this.disconnectDelay = /* (this.transport as TcpObfuscated).retryTimeout */75;
// //setInterval(this.sendPingDelayDisconnect, (this.disconnectDelay - 5) * 1000);
// this.sendPingDelayDisconnect();
// }
} }
private updateSession() { private updateSession() {
@ -389,6 +419,19 @@ export default class MTPNetworker {
/// #endif /// #endif
} }
this.log('change transport', transport, oldTransport);
/// #if MTPROTO_HAS_WS
this.clearPingDelayDisconnect();
// if(this.pingInterval !== undefined) {
// clearInterval(this.pingInterval);
// this.pingInterval = undefined;
// }
// this.clearPing();
/// #endif
this.transport = transport; this.transport = transport;
if(!transport) { if(!transport) {
return; return;
@ -408,10 +451,20 @@ export default class MTPNetworker {
/// #endif /// #endif
/// #endif /// #endif
if(transport.connected && (transport as TcpObfuscated).connection) { /// #if MTPROTO_HAS_WS
// * handle outcoming dead socket, server will close the connection
if((transport as TcpObfuscated).connection) {
// this.sendPingDelayDisconnect();
if(transport.connected) {
this.setConnectionStatus(ConnectionStatus.Connected); this.setConnectionStatus(ConnectionStatus.Connected);
} }
// this.pingInterval = ctx.setInterval(this.sendPing, PING_INTERVAL);
// this.sendPing();
}
/// #endif
this.resend(); this.resend();
} }
@ -435,112 +488,125 @@ export default class MTPNetworker {
} }
} }
// private sendPingDelayDisconnect = () => { /* private clearPing() {
// if(this.pingPromise || true) return; if(this.pingPromise) {
this.pingPromise = undefined;
}
// if(!this.isOnline) { this.lastPingTime = undefined;
// if((this.transport as TcpObfuscated).connected) { }
// (this.transport as TcpObfuscated).handleClose();
// }
private sendPing = () => {
// return; // return;
// }
// this.log('sendPingDelayDisconnect', this.sentPingTimes); // if(!(this.transport as TcpObfuscated).connected) {
// this.clearPing();
// /* if(this.tt) clearTimeout(this.tt); // return;
// this.tt = self.setTimeout(() => {
// (this.transport as any).ws.close(1000);
// this.tt = 0;
// }, this.disconnectDelay * 1000); */
// /* this.wrapMtpCall('ping_delay_disconnect', {
// ping_id: randomLong(),
// disconnect_delay: this.disconnectDelay
// }, {
// noResponse: true,
// notContentRelated: true
// }); */
// const deferred = this.pingPromise = deferredPromise<void>();
// const timeoutTime = this.disconnectDelay * 1000;
// /* if(!this.sentPingTimes || true) {
// ++this.sentPingTimes; */
// const startTime = Date.now();
// this.wrapMtpCall('ping', {
// ping_id: randomLong()
// }, {}).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); if(this.pingPromise) {
return;
}
// deferred.catch(() => { const startTime = Date.now();
// (this.transport as Socket).handleClose(); this.log('sendPing: ping', startTime);
// }); const promise = this.pingPromise = this.wrapMtpCall('ping', {
ping_id: randomLong()
}, {
notContentRelated: true
}).then(() => {
const elapsedTime = Date.now() - startTime;
this.lastPingTime = elapsedTime / 1000;
this.log('sendPing: pong', elapsedTime);
// deferred.finally(() => { setTimeout(() => {
// this.pingPromise = null; if(this.pingPromise !== promise) {
// this.sendPingDelayDisconnect(); return;
// }); }
// };
// private sendPingDelayDisconnect = () => { this.pingPromise = undefined;
// if(this.pingPromise || true) return; this.sendPing();
}, Math.max(0, PING_INTERVAL - elapsedTime));
});
}; */
// /* if(!this.isOnline) { private clearPingDelayDisconnect() {
// if((this.transport as TcpObfuscated).connected) { const deferred = this.pingDelayDisconnectDeferred;
// (this.transport as TcpObfuscated).connection.close(); this.pingDelayDisconnectDeferred = undefined;
// } this.lastPingDelayDisconnectId = undefined;
if(deferred) {
deferred.reject();
}
}
private sendPingDelayDisconnect = () => {
// return; // return;
// } */
// const deferred = this.pingPromise = deferredPromise<void>(); if(this.pingDelayDisconnectDeferred || !this.transport || !this.transport.connected) return;
// const timeoutTime = this.disconnectDelay * 1000; /* if(!this.isOnline) {
if((this.transport as TcpObfuscated).connected) {
(this.transport as TcpObfuscated).connection.close();
}
// const startTime = Date.now(); return;
// 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) { const deferred = this.pingDelayDisconnectDeferred = deferredPromise();
// deferred.reject(); const delays = this.delays;
// } else { const pingMaxTime = this.delays.pingMaxTime;
// setTimeout(deferred.resolve, timeoutTime - elapsedTime); const lastPingTime = Math.min(this.lastPingTime ?? 0, pingMaxTime);
// } const disconnectDelay = Math.round(delays.disconnectDelayMin + lastPingTime / pingMaxTime * (delays.disconnectDelayMax - delays.disconnectDelayMin));
// }, deferred.reject).finally(() => { const timeoutTime = disconnectDelay * 1000;
// clearTimeout(rejectTimeout); const startTime = Date.now();
// //--this.sentPingTimes; const pingId = this.lastPingDelayDisconnectId = randomLong();
// }); const options: MTMessageOptions = {notContentRelated: true};
this.wrapMtpCall('ping_delay_disconnect', {
ping_id: pingId,
disconnect_delay: disconnectDelay
}, options);
this.log(`sendPingDelayDisconnect: ping, timeout=${timeoutTime}, lastPingTime=${this.lastPingTime}, msgId=${options.messageId}`);
const rejectTimeout = self.setTimeout(deferred.reject, timeoutTime);
const onResolved = (reason: string) => {
clearTimeout(rejectTimeout);
const elapsedTime = Date.now() - startTime;
this.lastPingTime = elapsedTime / 1000;
this.log(`sendPingDelayDisconnect: pong, reason='${reason}', time=${lastPingTime}, msgId=${options.messageId}`);
if(elapsedTime > timeoutTime) {
throw undefined;
} else {
return pause(Math.max(0, this.delays.pingInterval - elapsedTime/* timeoutTime - elapsedTime - PING_INTERVAL */));
}
};
// const rejectTimeout = self.setTimeout(deferred.reject, timeoutTime); const onTimeout = () => {
clearTimeout(rejectTimeout);
const transport = this.transport as TcpObfuscated;
if(this.pingDelayDisconnectDeferred !== deferred || !transport?.connection) {
return;
}
// deferred.catch(() => { this.log.error('sendPingDelayDisconnect: catch, closing connection', this.lastPingTime, options.messageId);
// this.log.error('sendPingDelayDisconnect: catch, closing connection if exists'); transport.connection.close();
// (this.transport as TcpObfuscated).connection.close(); };
// });
// deferred.finally(() => { const onFinally = () => {
// this.pingPromise = null; if(this.pingDelayDisconnectDeferred !== deferred) {
// this.sendPingDelayDisconnect(); return;
// }); }
// };
this.pingDelayDisconnectDeferred = undefined;
this.sendPingDelayDisconnect();
};
deferred
.then(onResolved)
.catch(onTimeout)
.finally(onFinally);
};
/// #if MTPROTO_HAS_HTTP /// #if MTPROTO_HAS_HTTP
private checkLongPoll = () => { private checkLongPoll = () => {
@ -581,6 +647,7 @@ export default class MTPNetworker {
max_wait: maxWait max_wait: maxWait
}, { }, {
noResponse: true, noResponse: true,
// notContentRelated: true,
longPoll: true longPoll: true
}).then(() => { }).then(() => {
this.longPollPending = undefined; this.longPollPending = undefined;
@ -701,10 +768,12 @@ export default class MTPNetworker {
return false; return false;
}).then((shouldResolve) => { }).then((shouldResolve) => {
// clearTimeout(timeout); // clearTimeout(timeout);
const sentMessages = this.sentMessages;
noResponseMsgs.forEach((msgId) => { noResponseMsgs.forEach((msgId) => {
if(this.sentMessages[msgId]) { const sentMessage = sentMessages[msgId];
const deferred = this.sentMessages[msgId].deferred; if(sentMessage) {
delete this.sentMessages[msgId]; const deferred = sentMessage.deferred;
delete sentMessages[msgId];
delete this.pendingMessages[msgId]; delete this.pendingMessages[msgId];
shouldResolve ? deferred.resolve() : deferred.reject(); shouldResolve ? deferred.resolve() : deferred.reject();
} }
@ -720,12 +789,15 @@ export default class MTPNetworker {
body: Uint8Array | number[], body: Uint8Array | number[],
isAPI?: boolean isAPI?: boolean
}, options: MTMessageOptions) { }, options: MTMessageOptions) {
const promise = new Promise((resolve, reject) => { let promise: CancellablePromise<void>;
this.sentMessages[message.msg_id] = Object.assign(message, options, options.notContentRelated if(!options.notContentRelated || options.noResponse) {
? undefined promise = deferredPromise();
: {
deferred: {resolve, reject}
} }
this.sentMessages[message.msg_id] = Object.assign(
message,
options,
promise ? {deferred: promise} : undefined
); );
//this.log.error('Networker pushMessage:', this.sentMessages[message.msg_id]); //this.log.error('Networker pushMessage:', this.sentMessages[message.msg_id]);
@ -739,11 +811,11 @@ export default class MTPNetworker {
if(isObject(options)) { if(isObject(options)) {
options.messageId = message.msg_id; options.messageId = message.msg_id;
} }
});
if(!options.notContentRelated && !options.noResponse) { if(promise) {
const canIncrement = !options.notContentRelated;
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
if(this.lastResponseTime && (Date.now() - this.lastResponseTime) < CONNECTION_TIMEOUT) { if(this.lastResponseTime && (Date.now() - this.lastResponseTime) < this.delays.connectionTimeout) {
return; return;
} }
@ -755,22 +827,26 @@ export default class MTPNetworker {
/* this.getEncryptedOutput(message).then(bytes => { /* this.getEncryptedOutput(message).then(bytes => {
this.log.error('timeout encrypted', bytes); this.log.error('timeout encrypted', bytes);
}); */ }); */
}, CONNECTION_TIMEOUT); }, this.delays.connectionTimeout);
promise.catch(noop).finally(() => { promise.catch(noop).finally(() => {
clearTimeout(timeout); clearTimeout(timeout);
this.setConnectionStatus(ConnectionStatus.Connected); this.setConnectionStatus(ConnectionStatus.Connected);
if(canIncrement) {
--this.activeRequests; --this.activeRequests;
this.setDrainTimeout(); this.setDrainTimeout();
}
}); });
if(canIncrement) {
++this.activeRequests; ++this.activeRequests;
if(this.onDrainTimeout !== undefined) { if(this.onDrainTimeout !== undefined) {
clearTimeout(this.onDrainTimeout); clearTimeout(this.onDrainTimeout);
this.onDrainTimeout = undefined; this.onDrainTimeout = undefined;
} }
} }
}
return promise; return promise;
} }
@ -809,11 +885,10 @@ export default class MTPNetworker {
this.scheduleRequest(); this.scheduleRequest();
} }
// if((this.transport as TcpObfuscated).networker) { if((this.transport as TcpObfuscated).connection) {
// this.sendPingDelayDisconnect(); this.clearPingDelayDisconnect();
// } this.sendPingDelayDisconnect();
/* this.sentPingTimes = 0; }
this.sendPingDelayDisconnect(); */
} }
/* if(this.onConnectionStatusChange) { /* if(this.onConnectionStatusChange) {
this.onConnectionStatusChange(this.isOnline); this.onConnectionStatusChange(this.isOnline);
@ -890,8 +965,6 @@ export default class MTPNetworker {
} }
private performScheduledRequest() { private performScheduledRequest() {
// this.log('scheduled', this.dcId, this.iii)
if(this.isStopped()) { if(this.isStopped()) {
return false; return false;
} }
@ -909,27 +982,42 @@ export default class MTPNetworker {
}); });
} }
if(this.pendingResends.length) { const pendingResendReqLength = this.pendingResendReq.length;
const resendMsgIds = this.pendingResends.slice(); if(pendingResendReqLength) {
const resendOpts: MTMessageOptions = { const options: MTMessageOptions = {...RESEND_OPTIONS};
noSchedule: true, const msgIds = this.pendingResendReq.splice(0, pendingResendReqLength);
notContentRelated: true,
messageId: '' // will set in wrapMtpMessage->pushMessage
};
//this.log('resendReq messages', resendMsgIds);
this.wrapMtpMessage({ this.wrapMtpMessage({
_: 'msg_resend_req', _: 'msg_resend_req',
msg_ids: resendMsgIds msg_ids: msgIds
}, resendOpts); }, options);
this.log('resend: resending requests', options.messageId, msgIds);
/* this.lastResendReq = {
reqMsgId: options.messageId,
msgIds: msgIds
}; */
// this.pendingResendReq.length = 0;
}
// if(this.pendingResendAnsReq.length) {
// const options: MTMessageOptions = {...RESEND_OPTIONS};
// const msgIds = this.pendingResendAnsReq.slice();
// this.wrapMtpMessage({
// _: 'msg_resend_ans_req',
// msg_ids: msgIds
// }, options);
// this.log('resend: requesting answers', options.messageId, msgIds);
// this.lastResendAnsReq = {
// reqMsgId: options.messageId,
// msgIds: msgIds
// };
this.lastResendReq = { // // this.pendingResendAnsReq.length = 0;
req_msg_id: resendOpts.messageId, // }
resend_msg_ids: resendMsgIds
};
}
let outMessage: MTPNetworker['sentMessages'][keyof MTPNetworker['sentMessages']]; let outMessage: MTMessage;
const messages: typeof outMessage[] = []; const messages: typeof outMessage[] = [];
//const currentTime = Date.now(); //const currentTime = Date.now();
@ -1197,9 +1285,10 @@ export default class MTPNetworker {
}); });
} }
private sendEncryptedRequest(message: MTMessage) { private async sendEncryptedRequest(message: MTMessage) {
return this.getEncryptedOutput(message).then(requestData => { const requestData = await this.getEncryptedOutput(message);
this.debug && this.log.debug('sendEncryptedRequest: launching message into space:', message, [message.msg_id].concat(message.inner || []), requestData.length);
this.debug && this.log.debug('sending:', message, [message.msg_id].concat(message.inner || []), requestData.length);
const promise: Promise<Uint8Array> = this.transport.send(requestData) as any; const promise: Promise<Uint8Array> = this.transport.send(requestData) as any;
// this.debug && this.log.debug('sendEncryptedRequest: launched message into space:', message, promise); // this.debug && this.log.debug('sendEncryptedRequest: launched message into space:', message, promise);
@ -1235,7 +1324,6 @@ export default class MTPNetworker {
throw error; throw error;
}); });
/// #endif /// #endif
});
} }
public parseResponse(responseBuffer: Uint8Array) { public parseResponse(responseBuffer: Uint8Array) {
@ -1451,35 +1539,37 @@ export default class MTPNetworker {
this.scheduleRequest(delay); this.scheduleRequest(delay);
} }
private reqResendMessage(msgId: MTLong) { private reqResend(msgId: MTLong/* , isAnswer?: boolean */) {
if(this.debug) { if(this.debug) {
this.log.debug('Req resend', msgId); this.log.debug('Req resend', msgId/* , isAnswer */);
} }
this.pendingResends.push(msgId); // (isAnswer ? this.pendingResendAnsReq : this.pendingResendReq).push(msgId);
this.pendingResendReq.push(msgId);
this.scheduleRequest(100); this.scheduleRequest(100);
} }
public cleanupSent() { public cleanupSent() {
let notEmpty = false; let notEmpty = false;
// this.log('clean start', this.dcId/*, this.sentMessages*/) const sentMessages = this.sentMessages;
Object.keys(this.sentMessages).forEach((msgId) => { // this.log('clean start', this.dcId/*, sentMessages*/)
const message = this.sentMessages[msgId]; Object.keys(sentMessages).forEach((msgId) => {
const message = sentMessages[msgId];
// this.log('clean iter', msgID, message) // this.log('clean iter', msgID, message)
if(message.notContentRelated && this.pendingMessages[msgId] === undefined) { if(message.notContentRelated && this.pendingMessages[msgId] === undefined) {
// this.log('clean notContentRelated', msgID) // this.log('clean notContentRelated', msgID)
delete this.sentMessages[msgId]; delete sentMessages[msgId];
} else if(message.container) { } else if(message.container) {
for(const innerMsgId of message.inner) { for(const innerMsgId of message.inner) {
if(this.sentMessages[innerMsgId] !== undefined) { if(sentMessages[innerMsgId] !== undefined) {
// this.log('clean failed, found', msgID, message.inner[i], this.sentMessages[message.inner[i]].seq_no) // this.log('clean failed, found', msgID, message.inner[i], sentMessages[message.inner[i]].seq_no)
notEmpty = true; notEmpty = true;
return; return;
} }
} }
// this.log('clean container', msgID) // this.log('clean container', msgID)
delete this.sentMessages[msgId]; delete sentMessages[msgId];
} else { } else {
notEmpty = true; notEmpty = true;
} }
@ -1513,12 +1603,18 @@ export default class MTPNetworker {
* TODO: consider about containers resend * TODO: consider about containers resend
*/ */
public resend() { public resend() {
for(const id in this.sentMessages) { const sentMessages = this.sentMessages;
const msg = this.sentMessages[id]; for(const id in sentMessages) {
const msg = sentMessages[id];
if(msg.body || msg.container) { if(msg.body || msg.container) {
this.pushResend(id); this.pushResend(id);
} }
} }
if((this.transport as TcpObfuscated).connection) {
this.clearPingDelayDisconnect();
this.sendPingDelayDisconnect();
}
} }
/* public requestMessageStatus() { /* public requestMessageStatus() {
@ -1555,9 +1651,13 @@ export default class MTPNetworker {
return; return;
} }
/* if(this.debug) { if(this.debug) {
this.log('process message', message, messageId, sessionId); this.log.debug('process message', message, messageId);
} */ }
if(this.pingDelayDisconnectDeferred) {
this.pingDelayDisconnectDeferred.resolve('any message');
}
switch(message._) { switch(message._) {
case 'msg_container': { case 'msg_container': {
@ -1671,28 +1771,41 @@ export default class MTPNetworker {
break; break;
} }
case 'msg_detailed_info': case 'msg_detailed_info': {
if(!this.sentMessages[message.msg_id]) { const sentMessage = this.sentMessages[message.msg_id];
if(!sentMessage) {
this.ackMessage(message.answer_msg_id); this.ackMessage(message.answer_msg_id);
break; break;
}/* else if(sentMessage.acked) {
this.reqResend(message.answer_msg_id, true);
} }
case 'msg_new_detailed_info':
if(this.pendingAcks.indexOf(message.answer_msg_id)) { break; */
}
case 'msg_new_detailed_info': {
if(this.pendingAcks.indexOf(message.answer_msg_id) !== -1) {
break; break;
} }
this.reqResendMessage(message.answer_msg_id);
this.reqResend(message.answer_msg_id);
break; break;
}
case 'msgs_state_info': { case 'msgs_state_info': {
this.ackMessage(message.answer_msg_id); this.ackMessage(message.answer_msg_id);
if(this.lastResendReq && const arr = [
this.lastResendReq.req_msg_id === message.req_msg_id && [this.lastResendReq, this.pendingResendReq] as const
this.pendingResends.length // [this.lastResendAnsReq, this.pendingResendAnsReq] as const
) { ];
for(const badMsgId of this.lastResendReq.resend_msg_ids) {
const pos = this.pendingResends.indexOf(badMsgId); for(const [lastResend, pendingResend] of arr) {
if(lastResend?.reqMsgId === message.req_msg_id && pendingResend.length) {
for(const badMsgId of lastResend.msgIds) {
const pos = pendingResend.indexOf(badMsgId);
if(pos !== -1) { if(pos !== -1) {
this.pendingResends.splice(pos, 1); pendingResend.splice(pos, 1);
}
} }
} }
} }
@ -1706,6 +1819,10 @@ export default class MTPNetworker {
const sentMessageId = message.req_msg_id; const sentMessageId = message.req_msg_id;
const sentMessage = this.sentMessages[sentMessageId]; const sentMessage = this.sentMessages[sentMessageId];
// if(this.debug) {
// this.log.debug('Rpc response', message.result, sentMessage);
// }
this.processMessageAck(sentMessageId); this.processMessageAck(sentMessageId);
if(sentMessage) { if(sentMessage) {
const deferred = sentMessage.deferred; const deferred = sentMessage.deferred;
@ -1717,16 +1834,11 @@ export default class MTPNetworker {
} }
} else { } else {
if(deferred) { if(deferred) {
/* if(DEBUG) {
this.log.debug('Rpc response', message.result, sentMessage);
} */
deferred.resolve(message.result); deferred.resolve(message.result);
} }
if(sentMessage.isAPI && !this.connectionInited) { if(sentMessage.isAPI && !this.connectionInited) {
this.connectionInited = true; this.connectionInited = true;
////this.log('Rpc set connectionInited to:', this.connectionInited);
} }
} }
@ -1741,12 +1853,16 @@ export default class MTPNetworker {
} }
case 'pong': { // * https://core.telegram.org/mtproto/service_messages#ping-messages-pingpong - These messages don't require acknowledgments case 'pong': { // * https://core.telegram.org/mtproto/service_messages#ping-messages-pingpong - These messages don't require acknowledgments
const sentMessageId = message.msg_id; /* const sentMessageId = message.msg_id;
const sentMessage = this.sentMessages[sentMessageId]; const sentMessage = this.sentMessages[sentMessageId];
if(sentMessage) { if(sentMessage) {
sentMessage.deferred.resolve(message); sentMessage.deferred.resolve(message);
delete this.sentMessages[sentMessageId]; delete this.sentMessages[sentMessageId];
} */
const pingId = message.ping_id;
if(this.lastPingDelayDisconnectId === pingId) {
this.pingDelayDisconnectDeferred.resolve('pong');
} }
break; break;

Loading…
Cancel
Save