Fix first requests with new transport
Fix resend websocket messages after close
This commit is contained in:
parent
e7d5b52867
commit
c38c7f5051
|
@ -1,6 +1,6 @@
|
|||
import { TLSerialization, TLDeserialization } from "./tl_utils";
|
||||
import dcConfigurator from "./dcConfigurator";
|
||||
import { dT, bytesToHex, bytesCmp, bytesFromHex, bytesXor } from "../bin_utils";
|
||||
import { bytesToHex, bytesCmp, bytesFromHex, bytesXor } from "../bin_utils";
|
||||
import rsaKeysManager from "./rsaKeysManager";
|
||||
import timeManager from "./timeManager";
|
||||
|
||||
|
@ -9,6 +9,8 @@ import { BigInteger } from "jsbn";
|
|||
|
||||
import CryptoWorker from "../crypto/cryptoworker";
|
||||
|
||||
import { logger, LogLevels } from "../polyfill";
|
||||
|
||||
/* let fNewNonce: any = bytesFromHex('8761970c24cb2329b5b2459752c502f3057cb7e8dbab200e526e8767fdc73b3c').reverse();
|
||||
let fNonce: any = bytesFromHex('b597720d11faa5914ef485c529cde414').reverse();
|
||||
let fResult: any = new Uint8Array(bytesFromHex('000000000000000001b473a0661b285e480000006324160514e4cd29c585f44e91a5fa110d7297b5c0c4134c84893db5715ecd56af5ed618082182053cc5de91cd00000015c4b51c02000000a5b7f709355fc30b216be86c022bb4c3'));
|
||||
|
@ -59,7 +61,10 @@ export class Authorizer {
|
|||
[dcID: number]: Promise<AuthOptions>
|
||||
} = {};
|
||||
|
||||
private log: ReturnType<typeof logger>;
|
||||
|
||||
constructor() {
|
||||
this.log = logger(`AUTHORIZER`/* , LogLevels.error | LogLevels.log */);
|
||||
}
|
||||
|
||||
public mtpSendPlainRequest(dcID: number, requestArray: Uint8Array) {
|
||||
|
@ -94,10 +99,10 @@ export class Authorizer {
|
|||
transport: transport
|
||||
};
|
||||
|
||||
console.log(dT(), 'mtpSendPlainRequest: creating requestPromise');
|
||||
this.log('mtpSendPlainRequest: creating requestPromise');
|
||||
|
||||
return transport.send(resultArray).then(result => {
|
||||
console.log(dT(), 'mtpSendPlainRequest: in good sector', result);
|
||||
this.log('mtpSendPlainRequest: in good sector', result);
|
||||
|
||||
if(!result || !result.byteLength) {
|
||||
return Promise.reject(baseError);
|
||||
|
@ -109,17 +114,17 @@ export class Authorizer {
|
|||
|
||||
let deserializer = new TLDeserialization(result, {mtproto: true});
|
||||
let auth_key_id = deserializer.fetchLong('auth_key_id');
|
||||
if(auth_key_id != 0) console.error('auth_key_id != 0', auth_key_id);
|
||||
if(auth_key_id != 0) this.log.error('auth_key_id != 0', auth_key_id);
|
||||
|
||||
let msg_id = deserializer.fetchLong('msg_id');
|
||||
if(msg_id == 0) console.error('msg_id == 0', msg_id);
|
||||
if(msg_id == 0) this.log.error('msg_id == 0', msg_id);
|
||||
|
||||
let msg_len = deserializer.fetchInt('msg_len');
|
||||
if(!msg_len) console.error('no msg_len', msg_len);
|
||||
if(!msg_len) this.log.error('no msg_len', msg_len);
|
||||
|
||||
return deserializer;
|
||||
} catch(e) {
|
||||
console.error('mtpSendPlainRequest: deserialization went bad', e);
|
||||
this.log.error('mtpSendPlainRequest: deserialization went bad', e);
|
||||
let error = Object.assign(baseError, {originalError: e});
|
||||
throw error;
|
||||
}
|
||||
|
@ -142,15 +147,14 @@ export class Authorizer {
|
|||
// need
|
||||
rsaKeysManager.prepare().then(() => {});
|
||||
|
||||
console.log(dT(), 'Send req_pq', auth.nonce.hex);
|
||||
this.log('Send req_pq', auth.nonce.hex);
|
||||
try {
|
||||
var deserializer = await this.mtpSendPlainRequest(auth.dcID, request.getBytes(true));
|
||||
} catch(error) {
|
||||
console.error(dT(), 'req_pq error', error.message);
|
||||
this.log.error('req_pq error', error.message);
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
var response = deserializer.fetchObject('ResPQ');
|
||||
|
||||
if(response._ != 'resPQ') {
|
||||
|
@ -158,7 +162,7 @@ export class Authorizer {
|
|||
}
|
||||
|
||||
if(!bytesCmp(auth.nonce, response.nonce)) {
|
||||
console.log(auth.nonce, response.nonce);
|
||||
this.log.error(auth.nonce, response.nonce);
|
||||
throw new Error('[MT] resPQ nonce mismatch');
|
||||
}
|
||||
|
||||
|
@ -167,7 +171,7 @@ export class Authorizer {
|
|||
auth.pq = response.pq;
|
||||
auth.fingerprints = response.server_public_key_fingerprints;
|
||||
|
||||
console.log(dT(), 'Got ResPQ', bytesToHex(auth.serverNonce), bytesToHex(auth.pq), auth.fingerprints);
|
||||
this.log('Got ResPQ', bytesToHex(auth.serverNonce), bytesToHex(auth.pq), auth.fingerprints);
|
||||
|
||||
let publicKey = await rsaKeysManager.select(auth.fingerprints);
|
||||
if(!publicKey) {
|
||||
|
@ -176,19 +180,19 @@ export class Authorizer {
|
|||
|
||||
auth.publicKey = publicKey;
|
||||
|
||||
console.log(dT(), 'PQ factorization start', auth.pq);
|
||||
this.log('PQ factorization start', auth.pq);
|
||||
|
||||
try {
|
||||
var pAndQ = await CryptoWorker.factorize(auth.pq);
|
||||
} catch(error) {
|
||||
console.error('worker error factorize', error);
|
||||
this.log.error('worker error factorize', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
auth.p = pAndQ[0];
|
||||
auth.q = pAndQ[1];
|
||||
|
||||
console.log(dT(), 'PQ factorization done', pAndQ);
|
||||
this.log('PQ factorization done', pAndQ);
|
||||
/* let p = new Uint32Array(new Uint8Array(auth.p).buffer)[0];
|
||||
let q = new Uint32Array(new Uint8Array(auth.q).buffer)[0];
|
||||
console.log(dT(), 'PQ factorization done', pAndQ, p.toString(16), q.toString(16)); */
|
||||
|
@ -253,18 +257,18 @@ export class Authorizer {
|
|||
|
||||
let requestBytes = request.getBytes(true);
|
||||
|
||||
console.log(dT(), 'Send req_DH_params', req_DH_params/* , requestBytes.hex */);
|
||||
this.log('Send req_DH_params', req_DH_params/* , requestBytes.hex */);
|
||||
|
||||
try {
|
||||
var deserializer = await this.mtpSendPlainRequest(auth.dcID, requestBytes);
|
||||
} catch(error) {
|
||||
console.log(dT(), 'Send req_DH_params FAIL!', error);
|
||||
this.log('Send req_DH_params FAIL!', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
var response = deserializer.fetchObject('Server_DH_Params', 'RESPONSE');
|
||||
|
||||
console.log(dT(), 'Sent req_DH_params, response:', response);
|
||||
this.log('Sent req_DH_params, response:', response);
|
||||
|
||||
if(response._ != 'server_DH_params_fail' && response._ != 'server_DH_params_ok') {
|
||||
throw new Error('[MT] Server_DH_Params response invalid: ' + response._);
|
||||
|
@ -292,7 +296,7 @@ export class Authorizer {
|
|||
try {
|
||||
await this.mtpDecryptServerDhDataAnswer(auth, response.encrypted_answer);
|
||||
} catch(e) {
|
||||
console.error(dT(), 'mtpDecryptServerDhDataAnswer FAILED!', e);
|
||||
this.log.error('mtpDecryptServerDhDataAnswer FAILED!', e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
@ -342,7 +346,7 @@ export class Authorizer {
|
|||
throw new Error('[MT] server_DH_inner_data serverNonce mismatch');
|
||||
}
|
||||
|
||||
console.log(dT(), 'Done decrypting answer');
|
||||
this.log('Done decrypting answer');
|
||||
auth.g = response.g;
|
||||
auth.dhPrime = response.dh_prime;
|
||||
auth.gA = response.g_a;
|
||||
|
@ -362,13 +366,13 @@ export class Authorizer {
|
|||
}
|
||||
|
||||
public mtpVerifyDhParams(g: number, dhPrime: any, gA: any) {
|
||||
console.log(dT(), 'Verifying DH params');
|
||||
this.log('Verifying DH params');
|
||||
var dhPrimeHex = bytesToHex(dhPrime);
|
||||
if(g != 3 || dhPrimeHex !== 'c71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5b') {
|
||||
// The verified value is from https://core.telegram.org/mtproto/security_guidelines
|
||||
throw new Error('[MT] DH params are not verified: unknown dhPrime');
|
||||
}
|
||||
console.log(dT(), 'dhPrime cmp OK');
|
||||
this.log('dhPrime cmp OK');
|
||||
|
||||
var gABigInt = new BigInteger(bytesToHex(gA), 16);
|
||||
var dhPrimeBigInt = new BigInteger(dhPrimeHex, 16);
|
||||
|
@ -380,7 +384,7 @@ export class Authorizer {
|
|||
if(gABigInt.compareTo(dhPrimeBigInt.subtract(BigInteger.ONE)) >= 0) {
|
||||
throw new Error('[MT] DH params are not verified: gA >= dhPrime - 1');
|
||||
}
|
||||
console.log(dT(), '1 < gA < dhPrime-1 OK');
|
||||
this.log('1 < gA < dhPrime-1 OK');
|
||||
|
||||
|
||||
var two = new BigInteger(/* null */'');
|
||||
|
@ -393,7 +397,7 @@ export class Authorizer {
|
|||
if(gABigInt.compareTo(dhPrimeBigInt.subtract(twoPow)) >= 0) {
|
||||
throw new Error('[MT] DH params are not verified: gA > dhPrime - 2^{2048-64}');
|
||||
}
|
||||
console.log(dT(), '2^{2048-64} < gA < dhPrime-2^{2048-64} OK');
|
||||
this.log('2^{2048-64} < gA < dhPrime-2^{2048-64} OK');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -433,7 +437,7 @@ export class Authorizer {
|
|||
encrypted_data: encryptedData
|
||||
});
|
||||
|
||||
console.log(dT(), 'Send set_client_DH_params');
|
||||
this.log('Send set_client_DH_params');
|
||||
|
||||
try {
|
||||
var deserializer = await this.mtpSendPlainRequest(auth.dcID, request.getBytes(true));
|
||||
|
@ -466,43 +470,43 @@ export class Authorizer {
|
|||
authKeyAux = authKeyHash.slice(0, 8),
|
||||
authKeyID = authKeyHash.slice(-8);
|
||||
|
||||
console.log(dT(), 'Got Set_client_DH_params_answer', response._, authKey);
|
||||
this.log('Got Set_client_DH_params_answer', response._, authKey);
|
||||
switch(response._) {
|
||||
case 'dh_gen_ok':
|
||||
var newNonceHash1 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([1], authKeyAux))).slice(-16);
|
||||
//var newNonceHash1 = sha1BytesSync(auth.newNonce.concat([1], authKeyAux)).slice(-16);
|
||||
|
||||
if(!bytesCmp(newNonceHash1, response.new_nonce_hash1)) {
|
||||
throw new Error('[MT] Set_client_DH_params_answer new_nonce_hash1 mismatch');
|
||||
}
|
||||
|
||||
var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8));
|
||||
console.log('Auth successfull!', authKeyID, authKey, serverSalt);
|
||||
|
||||
auth.authKeyID = authKeyID;
|
||||
auth.authKey = authKey;
|
||||
auth.serverSalt = serverSalt;
|
||||
|
||||
return auth;
|
||||
break;
|
||||
var newNonceHash1 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([1], authKeyAux))).slice(-16);
|
||||
//var newNonceHash1 = sha1BytesSync(auth.newNonce.concat([1], authKeyAux)).slice(-16);
|
||||
|
||||
if(!bytesCmp(newNonceHash1, response.new_nonce_hash1)) {
|
||||
throw new Error('[MT] Set_client_DH_params_answer new_nonce_hash1 mismatch');
|
||||
}
|
||||
|
||||
var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8));
|
||||
this.log('Auth successfull!', authKeyID, authKey, serverSalt);
|
||||
|
||||
auth.authKeyID = authKeyID;
|
||||
auth.authKey = authKey;
|
||||
auth.serverSalt = serverSalt;
|
||||
|
||||
return auth;
|
||||
break;
|
||||
|
||||
case 'dh_gen_retry':
|
||||
//var newNonceHash2 = sha1BytesSync(auth.newNonce.concat([2], authKeyAux)).slice(-16);
|
||||
var newNonceHash2 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([2], authKeyAux))).slice(-16);
|
||||
if(!bytesCmp(newNonceHash2, response.new_nonce_hash2)) {
|
||||
throw new Error('[MT] Set_client_DH_params_answer new_nonce_hash2 mismatch');
|
||||
}
|
||||
|
||||
return this.mtpSendSetClientDhParams(auth);
|
||||
//var newNonceHash2 = sha1BytesSync(auth.newNonce.concat([2], authKeyAux)).slice(-16);
|
||||
var newNonceHash2 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([2], authKeyAux))).slice(-16);
|
||||
if(!bytesCmp(newNonceHash2, response.new_nonce_hash2)) {
|
||||
throw new Error('[MT] Set_client_DH_params_answer new_nonce_hash2 mismatch');
|
||||
}
|
||||
|
||||
return this.mtpSendSetClientDhParams(auth);
|
||||
|
||||
case 'dh_gen_fail':
|
||||
//var newNonceHash3 = sha1BytesSync(auth.newNonce.concat([3], authKeyAux)).slice(-16);
|
||||
var newNonceHash3 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([3], authKeyAux))).slice(-16);
|
||||
if(!bytesCmp(newNonceHash3, response.new_nonce_hash3)) {
|
||||
throw new Error('[MT] Set_client_DH_params_answer new_nonce_hash3 mismatch');
|
||||
}
|
||||
|
||||
throw new Error('[MT] Set_client_DH_params_answer fail');
|
||||
//var newNonceHash3 = sha1BytesSync(auth.newNonce.concat([3], authKeyAux)).slice(-16);
|
||||
var newNonceHash3 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([3], authKeyAux))).slice(-16);
|
||||
if(!bytesCmp(newNonceHash3, response.new_nonce_hash3)) {
|
||||
throw new Error('[MT] Set_client_DH_params_answer new_nonce_hash3 mismatch');
|
||||
}
|
||||
|
||||
throw new Error('[MT] Set_client_DH_params_answer fail');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ export const App = {
|
|||
export const Modes = {
|
||||
test: location.search.indexOf('test=1') > 0/* || true */,
|
||||
debug: location.search.indexOf('debug=1') > 0,
|
||||
http: location.search.indexOf('http=1') > 0,
|
||||
ssl: location.search.indexOf('ssl=1') > 0 || location.protocol == 'https:' && location.search.indexOf('ssl=0') == -1,
|
||||
http: false, //location.search.indexOf('http=1') > 0,
|
||||
ssl: true, // location.search.indexOf('ssl=1') > 0 || location.protocol == 'https:' && location.search.indexOf('ssl=0') == -1,
|
||||
multipleConnections: true
|
||||
};
|
||||
|
|
|
@ -121,7 +121,7 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
|||
stopTime?: number,
|
||||
rawError?: any
|
||||
} = {}): Promise<any> {
|
||||
console.log('will invokeApi:', method, params, options);
|
||||
//console.log('will invokeApi:', method, params, options);
|
||||
return this.performTaskWorker('invokeApi', method, params, options);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import NetworkerFactory from './networkerFactory';
|
|||
import dcConfigurator from './dcConfigurator';
|
||||
import Socket from './transports/websocket';
|
||||
import HTTP from './transports/http';
|
||||
import { logger } from '../polyfill';
|
||||
import { logger, LogLevels } from '../polyfill';
|
||||
import { Modes, App } from './mtproto_config';
|
||||
import { InvokeApiOptions } from '../../types';
|
||||
|
||||
|
@ -79,8 +79,6 @@ class MTPNetworker {
|
|||
|
||||
private onOnlineCb = this.checkConnection.bind(this);
|
||||
|
||||
private debug = false;
|
||||
|
||||
private lastResendReq: {
|
||||
req_msg_id: string,
|
||||
resend_msg_ids: Array<string>
|
||||
|
@ -99,6 +97,11 @@ class MTPNetworker {
|
|||
this.log = logger('NET-' + dcID + (this.upload ? '-U' : ''));
|
||||
this.log('constructor'/* , this.authKey, this.authKeyID, this.serverSalt */);
|
||||
|
||||
/* // Test resend after bad_server_salt
|
||||
if(this.dcID == 1 && this.upload) {
|
||||
this.serverSalt[0] = 0;
|
||||
} */
|
||||
|
||||
this.updateSession();
|
||||
|
||||
// if(!NetworkerFactory.offlineInited) {
|
||||
|
@ -268,7 +271,7 @@ class MTPNetworker {
|
|||
if(Modes.debug/* || true */) {
|
||||
this.log('Api call', method, message, params, options);
|
||||
} else {
|
||||
//////this.log('Api call', method);
|
||||
this.log('Api call', method, params, options);
|
||||
}
|
||||
|
||||
return this.pushMessage(message, options);
|
||||
|
@ -344,28 +347,28 @@ class MTPNetworker {
|
|||
}
|
||||
|
||||
public pushResend(messageID: string, delay = 0) {
|
||||
var value = delay ? Date.now() + delay : 0;
|
||||
var sentMessage = this.sentMessages[messageID];
|
||||
const value = delay ? Date.now() + delay : 0;
|
||||
const sentMessage = this.sentMessages[messageID];
|
||||
if(sentMessage.container) {
|
||||
for(var i = 0; i < sentMessage.inner.length; i++) {
|
||||
for(let i = 0, length = sentMessage.inner.length; i < length; i++) {
|
||||
this.pendingMessages[sentMessage.inner[i]] = value;
|
||||
}
|
||||
} else {
|
||||
this.pendingMessages[messageID] = value;
|
||||
}
|
||||
|
||||
// this.log('Resend due', messageID, this.pendingMessages)
|
||||
this.log('Resend due', messageID, this.pendingMessages);
|
||||
|
||||
this.scheduleRequest(delay);
|
||||
}
|
||||
|
||||
public async getMsgKey(dataWithPadding: ArrayBuffer, isOut: boolean) {
|
||||
var authKey = this.authKeyUint8;
|
||||
var x = isOut ? 0 : 8
|
||||
var msgKeyLargePlain = bufferConcat(authKey.subarray(88 + x, 88 + x + 32), dataWithPadding);
|
||||
const authKey = this.authKeyUint8;
|
||||
const x = isOut ? 0 : 8
|
||||
const msgKeyLargePlain = bufferConcat(authKey.subarray(88 + x, 88 + x + 32), dataWithPadding);
|
||||
|
||||
let msgKeyLarge = await CryptoWorker.sha256Hash(msgKeyLargePlain);
|
||||
var msgKey = new Uint8Array(msgKeyLarge).subarray(8, 24);
|
||||
const msgKeyLarge = await CryptoWorker.sha256Hash(msgKeyLargePlain);
|
||||
const msgKey = new Uint8Array(msgKeyLarge).subarray(8, 24);
|
||||
return msgKey;
|
||||
};
|
||||
|
||||
|
@ -513,7 +516,7 @@ class MTPNetworker {
|
|||
/* for(var i = 0; i < this.pendingResends.length; i++) {
|
||||
resendMsgIDs.push(this.pendingResends[i]);
|
||||
} */
|
||||
// this.log('resendReq messages', resendMsgIDs)
|
||||
this.log('resendReq messages', resendMsgIDs);
|
||||
this.wrapMtpMessage({
|
||||
_: 'msg_resend_req',
|
||||
msg_ids: resendMsgIDs
|
||||
|
@ -729,7 +732,7 @@ class MTPNetworker {
|
|||
public sendEncryptedRequest(message: any, options: any = {}) {
|
||||
var self = this;
|
||||
|
||||
this.debug && this.log('Send encrypted', message, options, this.authKeyID);
|
||||
this.log.debug('Send encrypted', message, options, this.authKeyID);
|
||||
// console.trace()
|
||||
var data = new TLSerialization({
|
||||
startMaxLength: message.body.length + 2048
|
||||
|
@ -740,7 +743,7 @@ class MTPNetworker {
|
|||
|
||||
data.storeLong(message.msg_id, 'message_id');
|
||||
data.storeInt(message.seq_no, 'seq_no');
|
||||
|
||||
|
||||
data.storeInt(message.body.length, 'message_data_length');
|
||||
data.storeRawBytes(message.body, 'message_data');
|
||||
|
||||
|
@ -756,7 +759,7 @@ class MTPNetworker {
|
|||
// this.log('auth_key_id', bytesToHex(self.authKeyID))
|
||||
|
||||
return this.getEncryptedMessage(dataWithPadding).then((encryptedResult) => {
|
||||
this.debug && this.log('Got encrypted out message', encryptedResult);
|
||||
this.log.debug('Got encrypted out message', encryptedResult);
|
||||
|
||||
let request = new TLSerialization({
|
||||
startMaxLength: encryptedResult.bytes.byteLength + 256
|
||||
|
@ -796,7 +799,7 @@ class MTPNetworker {
|
|||
}
|
||||
|
||||
public parseResponse(responseBuffer: Uint8Array) {
|
||||
this.debug && this.log('Start parsing response'/* , responseBuffer */);
|
||||
this.log.debug('Start parsing response'/* , responseBuffer */);
|
||||
|
||||
let self = this;
|
||||
let deserializer = new TLDeserialization(responseBuffer);
|
||||
|
@ -1016,6 +1019,18 @@ class MTPNetworker {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* только для сокета, возможно это будет неправильно работать, но в тесте сработало правильно
|
||||
*/
|
||||
public resend() {
|
||||
for(let id in this.sentMessages) {
|
||||
const msg = this.sentMessages[id];
|
||||
if(msg.body) {
|
||||
this.pushResend(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public processMessage(message: any, messageID: string, sessionID: Uint8Array | number[]) {
|
||||
var msgidInt = parseInt(messageID/* .toString(10) */.substr(0, -10), 10);
|
||||
if(msgidInt % 2) {
|
||||
|
@ -1023,7 +1038,7 @@ class MTPNetworker {
|
|||
return;
|
||||
}
|
||||
|
||||
this.debug && this.log('process message', message, messageID, sessionID);
|
||||
this.log.debug('process message', message, messageID, sessionID);
|
||||
|
||||
switch(message._) {
|
||||
case 'msg_container':
|
||||
|
@ -1040,10 +1055,20 @@ class MTPNetworker {
|
|||
this.log(message.bad_msg_id, message.bad_msg_seqno);
|
||||
throw new Error('[MT] Bad server salt for invalid message');
|
||||
}
|
||||
|
||||
|
||||
this.applyServerSalt(message.new_server_salt);
|
||||
this.pushResend(message.bad_msg_id);
|
||||
this.ackMessage(messageID);
|
||||
|
||||
/* // simulate disconnect
|
||||
try {
|
||||
this.log('networker state:', this);
|
||||
// @ts-ignore
|
||||
this.transport.ws.close(1000);
|
||||
} catch(err) {
|
||||
this.log.error('transport', this.transport, err);
|
||||
} */
|
||||
|
||||
break;
|
||||
|
||||
case 'bad_msg_notification':
|
||||
|
@ -1084,7 +1109,7 @@ class MTPNetworker {
|
|||
case 'new_session_created':
|
||||
this.ackMessage(messageID);
|
||||
|
||||
this.log('new_session_created in my head');
|
||||
this.log.debug('new_session_created', message);
|
||||
//this.updateSession();
|
||||
|
||||
this.processMessageAck(message.first_msg_id);
|
||||
|
@ -1150,7 +1175,7 @@ class MTPNetworker {
|
|||
} else {
|
||||
if(deferred) {
|
||||
if(Modes.debug) {
|
||||
this.debug && this.log('Rpc response', message.result);
|
||||
this.log.debug('Rpc response', message.result);
|
||||
} else {
|
||||
var dRes = message.result._;
|
||||
if(!dRes) {
|
||||
|
@ -1160,7 +1185,7 @@ class MTPNetworker {
|
|||
dRes = message.result;
|
||||
}
|
||||
}
|
||||
this.debug && this.log('Rpc response', dRes, sentMessage);
|
||||
this.log.debug('Rpc response', dRes, sentMessage);
|
||||
}
|
||||
|
||||
sentMessage.deferred.resolve(message.result);
|
||||
|
@ -1179,7 +1204,7 @@ class MTPNetworker {
|
|||
default:
|
||||
this.ackMessage(messageID);
|
||||
|
||||
this.debug && this.log('Update', message);
|
||||
this.log.debug('Update', message);
|
||||
|
||||
if(NetworkerFactory.updatesProcessor !== null) {
|
||||
NetworkerFactory.updatesProcessor(message, true);
|
||||
|
|
|
@ -113,7 +113,7 @@ export class RSAKeysManager {
|
|||
})).then(() => {
|
||||
this.prepared = true;
|
||||
|
||||
console.log('[MT] Prepared keys');
|
||||
//console.log('[MT] Prepared keys');
|
||||
this.preparePromise = null;
|
||||
});
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ export class RSAKeysManager {
|
|||
fingerprintHex = new Array(16 - fingerprintHex.length).fill('0').join('') + fingerprintHex;
|
||||
}
|
||||
|
||||
console.log(fingerprintHex, this.publicKeysParsed);
|
||||
//console.log(fingerprintHex, this.publicKeysParsed);
|
||||
if(foundKey = this.publicKeysParsed[fingerprintHex]) {
|
||||
return Object.assign({
|
||||
fingerprint: fingerprints[i]
|
||||
|
|
|
@ -5,7 +5,7 @@ import {CTR} from '@cryptography/aes';
|
|||
//import abridgetPacketCodec from './abridged';
|
||||
import intermediatePacketCodec from './intermediate';
|
||||
import {MTPNetworker} from '../networker';
|
||||
import { logger } from '../../polyfill';
|
||||
import { logger, LogLevels } from '../../polyfill';
|
||||
import { bytesFromWordss } from '../../bin_utils';
|
||||
import { Codec } from './codec';
|
||||
|
||||
|
@ -108,9 +108,14 @@ export class Obfuscation {
|
|||
}
|
||||
|
||||
export default class Socket extends MTTransport {
|
||||
ws: WebSocket | undefined;
|
||||
ws: WebSocket;
|
||||
|
||||
pending: Array<{resolve?: any, reject?: any, body?: Uint8Array}> = [];
|
||||
pending: Array<Partial<{
|
||||
resolve: any,
|
||||
reject: any,
|
||||
body: Uint8Array,
|
||||
bodySent: boolean
|
||||
}>> = [];
|
||||
|
||||
connected = false;
|
||||
|
||||
|
@ -122,14 +127,12 @@ export default class Socket extends MTTransport {
|
|||
|
||||
log: ReturnType<typeof logger>;
|
||||
|
||||
debug = false;
|
||||
|
||||
codec = intermediatePacketCodec;
|
||||
|
||||
constructor(dcID: number, url: string) {
|
||||
super(dcID, url);
|
||||
|
||||
this.log = logger(`WS-${dcID}`);
|
||||
this.log = logger(`WS-${dcID}`, LogLevels.log | LogLevels.error);
|
||||
|
||||
this.log('constructor');
|
||||
|
||||
|
@ -142,7 +145,7 @@ export default class Socket extends MTTransport {
|
|||
this.ws.removeEventListener('close', this.handleClose);
|
||||
this.ws.removeEventListener('message', this.handleMessage);
|
||||
this.ws.close(1000);
|
||||
}
|
||||
}
|
||||
|
||||
this.ws = new WebSocket(this.url, 'binary');
|
||||
this.ws.binaryType = 'arraybuffer';
|
||||
|
@ -161,20 +164,34 @@ export default class Socket extends MTTransport {
|
|||
};
|
||||
|
||||
handleClose = (event: CloseEvent) => {
|
||||
this.log('closed', event);
|
||||
this.log('closed', event, this.pending);
|
||||
this.connected = false;
|
||||
|
||||
this.pending.length = 0;
|
||||
if(this.networker) {
|
||||
//this.pending.length = 0;
|
||||
/* if(this.networker) {
|
||||
this.networker.resend();
|
||||
this.networker.cleanupSent();
|
||||
}
|
||||
} */
|
||||
|
||||
this.log('trying to reconnect...');
|
||||
this.connect();
|
||||
|
||||
for(let pending of this.pending) {
|
||||
if(pending.bodySent) {
|
||||
pending.bodySent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.networker) {
|
||||
this.ws.addEventListener('open', () => {
|
||||
this.networker.resend();
|
||||
this.networker.cleanupSent();
|
||||
}, {once: true});
|
||||
}
|
||||
};
|
||||
|
||||
handleMessage = (event: MessageEvent) => {
|
||||
this.debug && this.log('<-', 'handleMessage', event);
|
||||
this.log.debug('<-', 'handleMessage', event);
|
||||
|
||||
let data = this.obfuscation.decode(new Uint8Array(event.data));
|
||||
data = this.codec.readPacket(data);
|
||||
|
@ -182,9 +199,9 @@ export default class Socket extends MTTransport {
|
|||
if(this.networker) { // authenticated!
|
||||
//this.pending = this.pending.filter(p => p.body); // clear pending
|
||||
|
||||
this.debug && this.log('redirecting to networker');
|
||||
this.log.debug('redirecting to networker');
|
||||
return this.networker.parseResponse(data).then(response => {
|
||||
this.debug && this.log('redirecting to networker response:', response);
|
||||
this.log.debug('redirecting to networker response:', response);
|
||||
this.networker.processMessage(response.response, response.messageID, response.sessionID);
|
||||
});
|
||||
}
|
||||
|
@ -192,14 +209,14 @@ export default class Socket extends MTTransport {
|
|||
//console.log('got hex:', data.hex);
|
||||
let pending = this.pending.shift();
|
||||
if(!pending) {
|
||||
return this.log('no pending for res:', data.hex);
|
||||
return this.log.debug('no pending for res:', data.hex);
|
||||
}
|
||||
|
||||
pending.resolve(data);
|
||||
};
|
||||
|
||||
send = (body: Uint8Array) => {
|
||||
this.debug && this.log('-> body length to pending:', body.length);
|
||||
this.log.debug('-> body length to pending:', body.length);
|
||||
|
||||
if(this.networker) {
|
||||
this.pending.push({body});
|
||||
|
@ -221,26 +238,28 @@ export default class Socket extends MTTransport {
|
|||
return;
|
||||
}
|
||||
|
||||
let length = this.pending.length;
|
||||
//this.log.error('Pending length:', this.pending.length);
|
||||
const length = this.pending.length;
|
||||
for(let i = length - 1; i >= 0; --i) {
|
||||
let pending = this.pending[i];
|
||||
let {body} = pending;
|
||||
if(body) {
|
||||
let toEncode = this.codec.encodePacket(body);
|
||||
const pending = this.pending[i];
|
||||
const {body, bodySent} = pending;
|
||||
if(body && !bodySent) {
|
||||
const toEncode = this.codec.encodePacket(body);
|
||||
|
||||
//console.log('send before obf:', /* body.hex, nonce.hex, */ toEncode.hex);
|
||||
let enc = this.obfuscation.encode(toEncode);
|
||||
//console.log('send after obf:', enc.hex);
|
||||
|
||||
this.debug && this.log('-> body length to send:', enc.length);
|
||||
//this.log('send before obf:', /* body.hex, nonce.hex, */ toEncode.hex);
|
||||
const enc = this.obfuscation.encode(toEncode);
|
||||
//this.log('send after obf:', enc.hex);
|
||||
|
||||
this.log.debug('-> body length to send:', enc.length);
|
||||
this.ws.send(enc);
|
||||
|
||||
|
||||
if(!pending.resolve) { // remove if no response needed
|
||||
this.pending.splice(i, 1);
|
||||
} else {
|
||||
pending.bodySent = true;
|
||||
}
|
||||
|
||||
delete pending.body;
|
||||
//delete pending.body;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user