Performance improvements
Supported SSL. Closes #71 Added setZeroTimeout. Now downloading files when tab in background and improved performance Multiple file parts download in parallel TLDeserialization.fetchBytes returns typed array
This commit is contained in:
parent
44d7747ade
commit
ceec0fce2a
@ -161,7 +161,8 @@ function convertToArrayBuffer(bytes) {
|
||||
if (bytes instanceof ArrayBuffer) {
|
||||
return bytes;
|
||||
}
|
||||
if (bytes.buffer !== undefined) {
|
||||
if (bytes.buffer !== undefined &&
|
||||
bytes.buffer.byteLength == bytes.length * bytes.BYTES_PER_ELEMENT) {
|
||||
return bytes.buffer;
|
||||
}
|
||||
return bytesToArrayBuffer(bytes);
|
||||
|
@ -10,17 +10,27 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
.factory('MtpDcConfigurator', function () {
|
||||
var dcOptions = Config.Modes.test
|
||||
? [
|
||||
{id: 1, host: '173.240.5.253', port: 80},
|
||||
{id: 2, host: '149.154.167.40', port: 80},
|
||||
{id: 3, host: '174.140.142.5', port: 80}
|
||||
{id: 1, url: 'http://173.240.5.253'},
|
||||
{id: 2, url: 'http://149.154.167.40'},
|
||||
{id: 3, url: 'http://174.140.142.5'}
|
||||
]
|
||||
: (location.protocol == 'https:'
|
||||
? [
|
||||
{id: 1, url: 'https://pluto.web.telegram.org'},
|
||||
{id: 2, url: 'https://venus.web.telegram.org'},
|
||||
{id: 3, url: 'https://aurora.web.telegram.org'},
|
||||
{id: 4, url: 'https://vesta.web.telegram.org'},
|
||||
{id: 5, url: 'https://flora.web.telegram.org'}
|
||||
]
|
||||
: [
|
||||
{id: 1, host: '173.240.5.1', port: 80},
|
||||
{id: 2, host: '149.154.167.51', port: 80},
|
||||
{id: 3, host: '174.140.142.6', port: 80},
|
||||
{id: 4, host: '149.154.167.91', port: 80},
|
||||
{id: 5, host: '149.154.171.5', port: 80}
|
||||
];
|
||||
{id: 1, url: 'http://173.240.5.1'},
|
||||
{id: 2, url: 'http://149.154.167.51'},
|
||||
{id: 3, url: 'http://174.140.142.6'},
|
||||
{id: 4, url: 'http://149.154.167.91'},
|
||||
{id: 5, url: 'http://149.154.171.5'}
|
||||
]);
|
||||
|
||||
var sslSubdomains = 'pluto,venus,aurora,vesta,flora';
|
||||
|
||||
var chosenServers = {};
|
||||
|
||||
@ -31,7 +41,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
for (i = 0; i < dcOptions.length; i++) {
|
||||
dcOption = dcOptions[i];
|
||||
if (dcOption.id == dcID) {
|
||||
chosenServer = dcOption.host + ':' + dcOption.port;
|
||||
chosenServer = dcOption.url;
|
||||
}
|
||||
}
|
||||
chosenServers[dcID] = chosenServer;
|
||||
@ -197,7 +207,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
var requestData = xhrSendBuffer ? resultBuffer : resultArray,
|
||||
requestPromise;
|
||||
try {
|
||||
requestPromise = $http.post('http://' + MtpDcConfigurator.chooseServer(dcID) + '/apiw1', requestData, {
|
||||
requestPromise = $http.post(MtpDcConfigurator.chooseServer(dcID) + '/apiw1', requestData, {
|
||||
responseType: 'arraybuffer',
|
||||
transformRequest: null
|
||||
});
|
||||
@ -791,7 +801,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
longPoll: true
|
||||
}).then(function () {
|
||||
delete self.longPollPending;
|
||||
$timeout(self.checkLongPoll.bind(self), 0);
|
||||
setZeroTimeout(self.checkLongPoll.bind(self));
|
||||
}, function () {
|
||||
console.log('Long-poll failed');
|
||||
});
|
||||
@ -948,7 +958,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
|
||||
|
||||
MtpNetworker.prototype.performSheduledRequest = function() {
|
||||
// console.trace('sheduled', this.dcID, this.iii);
|
||||
// console.log(dT(), 'sheduled', this.dcID, this.iii);
|
||||
if (this.offline) {
|
||||
console.log(dT(), 'Cancel sheduled');
|
||||
return false;
|
||||
@ -1126,7 +1136,9 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
};
|
||||
|
||||
MtpNetworker.prototype.getDecryptedMessage = function (msgKey, encryptedData) {
|
||||
// console.log(dT(), 'get decrypted start');
|
||||
return this.getMsgKeyIv(msgKey, false).then(function (keyIv) {
|
||||
// console.log(dT(), 'after msg key iv');
|
||||
return CryptoWorker.aesDecrypt(encryptedData, keyIv[0], keyIv[1]);
|
||||
});
|
||||
};
|
||||
@ -1162,7 +1174,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
responseType: 'arraybuffer',
|
||||
transformRequest: null
|
||||
});
|
||||
requestPromise = $http.post('http://' + MtpDcConfigurator.chooseServer(self.dcID) + '/apiw1', requestData, options);
|
||||
requestPromise = $http.post(MtpDcConfigurator.chooseServer(self.dcID) + '/apiw1', requestData, options);
|
||||
} catch (e) {
|
||||
requestPromise = $q.reject(e);
|
||||
}
|
||||
@ -1206,6 +1218,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
encryptedData = deserializer.fetchRawBytes(responseBuffer.byteLength - deserializer.getOffset(), true, 'encrypted_data');
|
||||
|
||||
return this.getDecryptedMessage(msgKey, encryptedData).then(function (dataWithPadding) {
|
||||
// console.log(dT(), 'after decrypt');
|
||||
var deserializer = new TLDeserialization(dataWithPadding, {mtproto: true});
|
||||
|
||||
var salt = deserializer.fetchIntBytes(64, false, 'salt');
|
||||
@ -1216,6 +1229,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
|
||||
var messageBody = deserializer.fetchRawBytes(false, true, 'message_data');
|
||||
|
||||
// console.log(dT(), 'before hash');
|
||||
var hashData = convertToUint8Array(dataWithPadding).subarray(0, deserializer.getOffset());
|
||||
|
||||
return CryptoWorker.sha1Hash(hashData).then(function (dataHash) {
|
||||
@ -1223,6 +1237,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
console.warn(msgKey, bytesFromArrayBuffer(dataHash));
|
||||
throw new Error('server msgKey mismatch');
|
||||
}
|
||||
// console.log(dT(), 'after hash check');
|
||||
|
||||
var buffer = bytesToArrayBuffer(messageBody);
|
||||
var deserializerOptions = {
|
||||
@ -1243,7 +1258,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
}
|
||||
if (this.offset != offset + result.bytes) {
|
||||
console.warn(dT(), 'set offset', this.offset, offset, result.bytes);
|
||||
console.log(dT(), result);
|
||||
// console.log(dT(), result);
|
||||
this.offset = offset + result.bytes;
|
||||
}
|
||||
// console.log(dT(), 'override message', result);
|
||||
@ -1262,6 +1277,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
var deserializer = new TLDeserialization(buffer, deserializerOptions);
|
||||
|
||||
var response = deserializer.fetchObject('', 'INPUT');
|
||||
// console.log(dT(), 'after fetch');
|
||||
|
||||
return {
|
||||
response: response,
|
||||
@ -1294,12 +1310,16 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
||||
return false;
|
||||
}
|
||||
|
||||
// console.log('shedule req', delay);
|
||||
// console.log(dT(), 'shedule req', delay);
|
||||
// console.trace();
|
||||
|
||||
$timeout.cancel(this.nextReqPromise);
|
||||
if (delay > 0) {
|
||||
this.nextReqPromise = $timeout(this.performSheduledRequest.bind(this), delay || 0);
|
||||
} else {
|
||||
setZeroTimeout(this.performSheduledRequest.bind(this))
|
||||
}
|
||||
|
||||
this.nextReqPromise = $timeout(this.performSheduledRequest.bind(this), delay || 0);
|
||||
this.nextReq = nextReq;
|
||||
};
|
||||
|
||||
|
@ -464,7 +464,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
|
||||
fileDownload: true,
|
||||
createNetworker: true
|
||||
});
|
||||
}, 6).then(function (result) {
|
||||
}, 2).then(function (result) {
|
||||
writeFilePromise.then(function () {
|
||||
if (canceled) {
|
||||
return $q.when();
|
||||
|
@ -33,7 +33,7 @@ angular.module('izhukov.utils', [])
|
||||
|
||||
})
|
||||
|
||||
.service('FileManager', function ($window, $timeout, $q) {
|
||||
.service('FileManager', function ($window, $q) {
|
||||
|
||||
$window.URL = $window.URL || $window.webkitURL;
|
||||
$window.BlobBuilder = $window.BlobBuilder || $window.WebKitBlobBuilder || $window.MozBlobBuilder;
|
||||
@ -98,10 +98,10 @@ angular.module('izhukov.utils', [])
|
||||
else {
|
||||
try {
|
||||
var blob = blobConstruct([bytesToArrayBuffer(bytes)]);
|
||||
fileWriter.write(blob);
|
||||
} catch (e) {
|
||||
deferred.reject(e);
|
||||
}
|
||||
fileWriter.write(blob);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
@ -150,7 +150,7 @@ angular.module('izhukov.utils', [])
|
||||
return false;
|
||||
}
|
||||
blobParts.push(blob);
|
||||
$timeout(function () {
|
||||
setZeroTimeout(function () {
|
||||
if (fakeFileWriter.onwriteend) {
|
||||
fakeFileWriter.onwriteend();
|
||||
}
|
||||
@ -493,7 +493,7 @@ angular.module('izhukov.utils', [])
|
||||
finalizeTask = function (taskID, result) {
|
||||
var deferred = awaiting[taskID];
|
||||
if (deferred !== undefined) {
|
||||
console.log(dT(), 'CW done');
|
||||
// console.log(dT(), 'CW done');
|
||||
deferred.resolve(result);
|
||||
delete awaiting[taskID];
|
||||
}
|
||||
@ -524,7 +524,7 @@ angular.module('izhukov.utils', [])
|
||||
}
|
||||
|
||||
function performTaskWorker (task, params, embed) {
|
||||
console.log(dT(), 'CW start', task);
|
||||
// console.log(dT(), 'CW start', task);
|
||||
var deferred = $q.defer();
|
||||
|
||||
awaiting[taskID] = deferred;
|
||||
@ -562,7 +562,6 @@ angular.module('izhukov.utils', [])
|
||||
},
|
||||
aesEncrypt: function (bytes, keyBytes, ivBytes) {
|
||||
if (aesNaClEmbed) {
|
||||
// aesEncryptSync(bytes, keyBytes, ivBytes);
|
||||
return performTaskWorker('aes-encrypt', {
|
||||
bytes: addPadding(convertToArrayBuffer(bytes)),
|
||||
keyBytes: convertToArrayBuffer(keyBytes),
|
||||
@ -575,7 +574,6 @@ angular.module('izhukov.utils', [])
|
||||
},
|
||||
aesDecrypt: function (encryptedBytes, keyBytes, ivBytes) {
|
||||
if (aesNaClEmbed) {
|
||||
// aesDecryptSync(encryptedBytes, keyBytes, ivBytes);
|
||||
return performTaskWorker('aes-decrypt', {
|
||||
encryptedBytes: addPadding(convertToArrayBuffer(encryptedBytes)),
|
||||
keyBytes: convertToArrayBuffer(keyBytes),
|
||||
|
@ -95,4 +95,37 @@ if (!Function.prototype.bind) {
|
||||
|
||||
return fBound;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* setZeroTimeout polyfill, from http://dbaron.org/log/20100309-faster-timeouts */
|
||||
(function(global) {
|
||||
var timeouts = [];
|
||||
var messageName = 'zero-timeout-message';
|
||||
|
||||
function setZeroTimeout(fn) {
|
||||
timeouts.push(fn);
|
||||
global.postMessage(messageName, '*');
|
||||
}
|
||||
|
||||
function handleMessage(event) {
|
||||
if (event.source == global && event.data == messageName) {
|
||||
event.stopPropagation();
|
||||
if (timeouts.length > 0) {
|
||||
var fn = timeouts.shift();
|
||||
fn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global.addEventListener('message', handleMessage, true);
|
||||
|
||||
var originalSetTimeout = global.setTimeout;
|
||||
global.setTimeout = function (callback, delay) {
|
||||
if (!delay || delay <= 5) {
|
||||
return setZeroTimeout(callback);
|
||||
}
|
||||
return originalSetTimeout(callback, delay);
|
||||
};
|
||||
|
||||
global.setZeroTimeout = setZeroTimeout;
|
||||
})(this);
|
@ -402,10 +402,8 @@ TLDeserialization.prototype.fetchBytes = function (field) {
|
||||
(this.byteView[this.offset++] << 16);
|
||||
}
|
||||
|
||||
var bytes = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes.push(this.byteView[this.offset++]);
|
||||
}
|
||||
var bytes = this.byteView.subarray(this.offset, this.offset + len);
|
||||
this.offset += len;
|
||||
|
||||
// Padding
|
||||
while (this.offset % 4) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user