Browse Source

Merge branch 'crypto-performance' into UI-update

master
Igor Zhukov 10 years ago
parent
commit
7ea9ee30ae
  1. 4
      app/js/controllers.js
  2. 12
      app/js/lib/bin_utils.js
  3. 2
      app/js/lib/crypto_worker.js
  4. 80
      app/js/lib/mtproto.js
  5. 126
      app/js/lib/mtproto_wrapper.js
  6. 40
      app/js/lib/ng_utils.js
  7. 4
      app/js/lib/tl_utils.js
  8. 2
      app/js/lib/utils.js
  9. 11
      app/js/services.js

4
app/js/controllers.js

@ -467,7 +467,6 @@ angular.module('myApp.controllers', ['myApp.i18n'])
peersInDialogs = {}, peersInDialogs = {},
contactsShown; contactsShown;
MtpApiManager.invokeApi('account.updateStatus', {offline: false});
$scope.$on('dialogs_need_more', function () { $scope.$on('dialogs_need_more', function () {
// console.log('on need more'); // console.log('on need more');
showMoreDialogs(); showMoreDialogs();
@ -629,7 +628,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
if (error.code == 401) { if (error.code == 401) {
MtpApiManager.logOut()['finally'](function () { MtpApiManager.logOut()['finally'](function () {
$location.url('/login'); location.hash = '/login';
AppRuntimeManager.reload();
}); });
error.handled = true; error.handled = true;
} }

12
app/js/lib/bin_utils.js

@ -175,6 +175,18 @@ function convertToUint8Array(bytes) {
return new Uint8Array(bytes); return new Uint8Array(bytes);
} }
function convertToByteArray(bytes) {
if (Array.isArray(bytes)) {
return bytes;
}
bytes = convertToUint8Array(bytes);
var newBytes = [];
for (var i = 0, len = bytes.length; i < len; i++) {
newBytes.push(bytes[i]);
}
return newBytes;
}
function bytesFromArrayBuffer (buffer) { function bytesFromArrayBuffer (buffer) {
var len = buffer.byteLength, var len = buffer.byteLength,
byteView = new Uint8Array(buffer), byteView = new Uint8Array(buffer),

2
app/js/lib/crypto_worker.js

@ -46,3 +46,5 @@ onmessage = function (e) {
postMessage({taskID: taskID, result: result}); postMessage({taskID: taskID, result: result});
} }
postMessage('ready');

80
app/js/lib/mtproto.js

@ -9,29 +9,33 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
.factory('MtpDcConfigurator', function () { .factory('MtpDcConfigurator', function () {
var dcOptions = Config.Modes.test var dcOptions = Config.Modes.test
? (location.protocol == 'https:'
? [ ? [
{id: 1, url: 'http://173.240.5.253'}, {id: 1, url: 'https://pluto.web.telegram.org/apiw_test1'},
{id: 2, url: 'http://149.154.167.40'}, {id: 2, url: 'https://venus.web.telegram.org/apiw_test1'},
{id: 3, url: 'http://174.140.142.5'} {id: 3, url: 'https://aurora.web.telegram.org/apiw_test1'}
] ]
: [
{id: 1, url: 'http://173.240.5.253/apiw1'},
{id: 2, url: 'http://149.154.167.40/apiw1'},
{id: 3, url: 'http://174.140.142.5/apiw1'}
])
: (location.protocol == 'https:' : (location.protocol == 'https:'
? [ ? [
{id: 1, url: 'https://pluto.web.telegram.org'}, {id: 1, url: 'https://pluto.web.telegram.org/apiw1'},
{id: 2, url: 'https://venus.web.telegram.org'}, {id: 2, url: 'https://venus.web.telegram.org/apiw1'},
{id: 3, url: 'https://aurora.web.telegram.org'}, {id: 3, url: 'https://aurora.web.telegram.org/apiw1'},
{id: 4, url: 'https://vesta.web.telegram.org'}, {id: 4, url: 'https://vesta.web.telegram.org/apiw1'},
{id: 5, url: 'https://flora.web.telegram.org'} {id: 5, url: 'https://flora.web.telegram.org/apiw1'}
] ]
: [ : [
{id: 1, url: 'http://173.240.5.1'}, {id: 1, url: 'http://173.240.5.1/apiw1'},
{id: 2, url: 'http://149.154.167.51'}, {id: 2, url: 'http://149.154.167.51/apiw1'},
{id: 3, url: 'http://174.140.142.6'}, {id: 3, url: 'http://174.140.142.6/apiw1'},
{id: 4, url: 'http://149.154.167.91'}, {id: 4, url: 'http://149.154.167.91/apiw1'},
{id: 5, url: 'http://149.154.171.5'} {id: 5, url: 'http://149.154.171.5/apiw1'}
]); ]);
var sslSubdomains = 'pluto,venus,aurora,vesta,flora';
var chosenServers = {}; var chosenServers = {};
function chooseServer(dcID) { function chooseServer(dcID) {
@ -153,7 +157,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
lastMessageID = messageID; lastMessageID = messageID;
// console.log('generated msg id', messageID); // console.log('generated msg id', messageID, timeOffset);
return longFromInts(messageID[0], messageID[1]); return longFromInts(messageID[0], messageID[1]);
}; };
@ -207,7 +211,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
var requestData = xhrSendBuffer ? resultBuffer : resultArray, var requestData = xhrSendBuffer ? resultBuffer : resultArray,
requestPromise; requestPromise;
try { try {
requestPromise = $http.post(MtpDcConfigurator.chooseServer(dcID) + '/apiw1', requestData, { requestPromise = $http.post(MtpDcConfigurator.chooseServer(dcID), requestData, {
responseType: 'arraybuffer', responseType: 'arraybuffer',
transformRequest: null transformRequest: null
}); });
@ -990,13 +994,32 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
currentTime = tsNow(), currentTime = tsNow(),
hasApiCall = false, hasApiCall = false,
hasHttpWait = false, hasHttpWait = false,
lengthOverflow = false,
singlesCount = 0,
self = this; self = this;
angular.forEach(this.pendingMessages, function (value, messageID) { angular.forEach(this.pendingMessages, function (value, messageID) {
if (!value || value >= currentTime) { if (!value || value >= currentTime) {
if (message = self.sentMessages[messageID]) { if (message = self.sentMessages[messageID]) {
var messageByteLength = (message.body.byteLength || message.body.length) + 32;
if (!message.notContentRelated &&
lengthOverflow) {
return;
}
if (!message.notContentRelated &&
messagesByteLen &&
messagesByteLen + messageByteLength > 655360) { // 640 Kb
lengthOverflow = true;
return;
}
if (message.singleInRequest) {
singlesCount++;
if (singlesCount > 1) {
return;
}
}
messages.push(message); messages.push(message);
messagesByteLen += (message.body.byteLength || message.body.length) + 32; messagesByteLen += messageByteLength;
if (message.isAPI) { if (message.isAPI) {
hasApiCall = true; hasApiCall = true;
} }
@ -1113,6 +1136,10 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
self.toggleOffline(true); self.toggleOffline(true);
}); });
if (lengthOverflow || singlesCount > 1) {
this.sheduleRequest()
}
}; };
MtpNetworker.prototype.getEncryptedMessage = function (bytes) { MtpNetworker.prototype.getEncryptedMessage = function (bytes) {
@ -1174,7 +1201,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
responseType: 'arraybuffer', responseType: 'arraybuffer',
transformRequest: null transformRequest: null
}); });
requestPromise = $http.post(MtpDcConfigurator.chooseServer(self.dcID) + '/apiw1', requestData, options); requestPromise = $http.post(MtpDcConfigurator.chooseServer(self.dcID), requestData, options);
} catch (e) { } catch (e) {
requestPromise = $q.reject(e); requestPromise = $q.reject(e);
} }
@ -1237,7 +1264,6 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
console.warn(msgKey, bytesFromArrayBuffer(dataHash)); console.warn(msgKey, bytesFromArrayBuffer(dataHash));
throw new Error('server msgKey mismatch'); throw new Error('server msgKey mismatch');
} }
// console.log(dT(), 'after hash check');
var buffer = bytesToArrayBuffer(messageBody); var buffer = bytesToArrayBuffer(messageBody);
var deserializerOptions = { var deserializerOptions = {
@ -1275,9 +1301,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
} }
}; };
var deserializer = new TLDeserialization(buffer, deserializerOptions); var deserializer = new TLDeserialization(buffer, deserializerOptions);
var response = deserializer.fetchObject('', 'INPUT'); var response = deserializer.fetchObject('', 'INPUT');
// console.log(dT(), 'after fetch');
return { return {
response: response, response: response,
@ -1323,10 +1347,6 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
this.nextReq = nextReq; this.nextReq = nextReq;
}; };
MtpNetworker.prototype.onSessionCreate = function (sessionID, messageID) {
// console.log(dT(), 'New session created', bytesToHex(sessionID));
};
MtpNetworker.prototype.ackMessage = function (msgID) { MtpNetworker.prototype.ackMessage = function (msgID) {
// console.log('ack message', msgID); // console.log('ack message', msgID);
this.pendingAcks.push(msgID); this.pendingAcks.push(msgID);
@ -1447,7 +1467,13 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
this.processMessageAck(message.first_msg_id); this.processMessageAck(message.first_msg_id);
this.applyServerSalt(message.server_salt); this.applyServerSalt(message.server_salt);
this.onSessionCreate(sessionID, messageID);
var self = this;
Storage.get('dc').then(function (baseDcID) {
if (baseDcID == self.dcID && !self.upload && updatesProcessor) {
updatesProcessor(message);
}
});
break; break;
case 'msgs_ack': case 'msgs_ack':

126
app/js/lib/mtproto_wrapper.js

@ -54,7 +54,9 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
} }
if (cache[dcID] !== undefined) { if (cache[dcID] !== undefined) {
return $q.when(cache[dcID]); return {then: function (cb) {
cb(cache[dcID]);
}};
} }
var akk = 'dc' + dcID + '_auth_key', var akk = 'dc' + dcID + '_auth_key',
@ -120,24 +122,17 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
dcID, dcID,
networkerPromise; networkerPromise;
if (dcID = options.dcID) { var cachedNetworker;
networkerPromise = mtpGetNetworker(dcID, options); var stack = (new Error()).stack;
} else { if (!stack) {
networkerPromise = Storage.get('dc').then(function (baseDcID) { try {window.unexistingFunction();} catch (e) {
return mtpGetNetworker(dcID = baseDcID || 2, options); stack = e.stack || '';
}); }
} }
var performRequest = function (networker) {
var cachedNetworker,
stack = false;
networkerPromise.then(function (networker) {
return (cachedNetworker = networker).wrapApiCall(method, params, options).then( return (cachedNetworker = networker).wrapApiCall(method, params, options).then(
function (result) { function (result) {
deferred.resolve(result); deferred.resolve(result);
// $timeout(function () {
// deferred.resolve(result);
// }, 1000);
}, },
function (error) { function (error) {
console.error(dT(), 'Error', error.code, error.type, baseDcID, dcID); console.error(dT(), 'Error', error.code, error.type, baseDcID, dcID);
@ -168,12 +163,8 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
cachedExportPromise[dcID].then(function () { cachedExportPromise[dcID].then(function () {
(cachedNetworker = networker).wrapApiCall(method, params, options).then(function (result) { (cachedNetworker = networker).wrapApiCall(method, params, options).then(function (result) {
deferred.resolve(result); deferred.resolve(result);
}, function (error) { }, rejectPromise);
rejectPromise(error); }, rejectPromise);
});
}, function (error) {
rejectPromise(error);
});
} }
else if (error.code == 303) { else if (error.code == 303) {
var newDcID = error.type.match(/^(PHONE_MIGRATE_|NETWORK_MIGRATE_|USER_MIGRATE_)(\d+)/)[2]; var newDcID = error.type.match(/^(PHONE_MIGRATE_|NETWORK_MIGRATE_|USER_MIGRATE_)(\d+)/)[2];
@ -187,9 +178,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
mtpGetNetworker(newDcID, options).then(function (networker) { mtpGetNetworker(newDcID, options).then(function (networker) {
networker.wrapApiCall(method, params, options).then(function (result) { networker.wrapApiCall(method, params, options).then(function (result) {
deferred.resolve(result); deferred.resolve(result);
}, function (error) { }, rejectPromise);
rejectPromise(error);
});
}); });
} }
} }
@ -197,14 +186,14 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
rejectPromise(error); rejectPromise(error);
} }
}); });
}, function (error) { };
rejectPromise(error);
});
if (!(stack = (stack || (new Error()).stack))) { if (dcID = (options.dcID || baseDcID)) {
try {window.unexistingFunction();} catch (e) { mtpGetNetworker(dcID, options).then(performRequest, rejectPromise);
stack = e.stack || ''; } else {
} Storage.get('dc').then(function (baseDcID) {
mtpGetNetworker(dcID = baseDcID || 2, options).then(performRequest, rejectPromise);
});
} }
return deferred.promise; return deferred.promise;
@ -234,14 +223,12 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
var cachedFs = false; var cachedFs = false;
var cachedFsPromise = false; var cachedFsPromise = false;
var apiUploadPromise = $q.when();
var cachedSavePromises = {}; var cachedSavePromises = {};
var cachedDownloadPromises = {}; var cachedDownloadPromises = {};
var cachedDownloads = {}; var cachedDownloads = {};
var downloadPulls = {}; var downloadPulls = {};
var downloadActives = {}; var downloadActives = {};
var downloadLimit = 5;
function downloadRequest(dcID, cb, activeDelta) { function downloadRequest(dcID, cb, activeDelta) {
if (downloadPulls[dcID] === undefined) { if (downloadPulls[dcID] === undefined) {
@ -251,7 +238,9 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
var downloadPull = downloadPulls[dcID]; var downloadPull = downloadPulls[dcID];
var deferred = $q.defer(); var deferred = $q.defer();
downloadPull.push({cb: cb, deferred: deferred, activeDelta: activeDelta}); downloadPull.push({cb: cb, deferred: deferred, activeDelta: activeDelta});
downloadCheck(dcID); setZeroTimeout(function () {
downloadCheck(dcID);
});
return deferred.promise; return deferred.promise;
}; };
@ -260,6 +249,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
function downloadCheck(dcID) { function downloadCheck(dcID) {
var downloadPull = downloadPulls[dcID]; var downloadPull = downloadPulls[dcID];
var downloadLimit = dcID == 'upload' ? 17 : 5;
if (downloadActives[dcID] >= downloadLimit || !downloadPull || !downloadPull.length) { if (downloadActives[dcID] >= downloadLimit || !downloadPull || !downloadPull.length) {
return false; return false;
@ -514,15 +504,23 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
} }
function uploadFile (file) { function uploadFile (file) {
var fileSize = file.size, var fileSize = file.size,
// partSize = fileSize > 102400 ? 65536 : 4096, isBigFile = fileSize >= 10485760,
// partSize = fileSize > 102400 ? 524288 : 4096, canceled = false,
partSize = fileSize > 102400 ? 524288 : 32768, resolved = false,
isBigFile = fileSize >= 10485760, doneParts = 0,
totalParts = Math.ceil(fileSize / partSize), partSize = 262144, // 256 Kb
canceled = false, activeDelta = 2;
resolved = false,
doneParts = 0; if (fileSize > 67108864) {
partSize = 524288;
activeDelta = 4;
}
else if (fileSize < 102400) {
partSize = 32768;
activeDelta = 1;
}
var totalParts = Math.ceil(fileSize / partSize);
if (totalParts > 1500) { if (totalParts > 1500) {
return $q.reject({type: 'FILE_TOO_BIG'}); return $q.reject({type: 'FILE_TOO_BIG'});
@ -533,6 +531,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
errorHandler = function (error) { errorHandler = function (error) {
// console.error('Up Error', error); // console.error('Up Error', error);
deferred.reject(error); deferred.reject(error);
canceled = true;
errorHandler = angular.noop; errorHandler = angular.noop;
}, },
part = 0, part = 0,
@ -546,35 +545,34 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
}; };
var fileReadPromise = $q.when();
for (offset = 0; offset < fileSize; offset += partSize) { for (offset = 0; offset < fileSize; offset += partSize) {
(function (offset, part) { (function (offset, part) {
fileReadPromise = fileReadPromise.then(function () { downloadRequest('upload', function () {
var fileReadDeferred = $q.defer(); var uploadDeferred = $q.defer();
var reader = new FileReader(); var reader = new FileReader();
var blob = file.slice(offset, offset + partSize); var blob = file.slice(offset, offset + partSize);
reader.onloadend = function (e) { reader.onloadend = function (e) {
if (canceled || e.target.readyState != FileReader.DONE) { if (canceled) {
uploadDeferred.reject();
return; return;
} }
var apiCurPromise = apiUploadPromise = apiUploadPromise.then(function () { if (e.target.readyState != FileReader.DONE) {
return MtpApiManager.invokeApi(isBigFile ? 'upload.saveBigFilePart' : 'upload.saveFilePart', { return;
file_id: fileID, }
file_part: part, MtpApiManager.invokeApi(isBigFile ? 'upload.saveBigFilePart' : 'upload.saveFilePart', {
file_total_parts: totalParts, file_id: fileID,
bytes: e.target.result file_part: part,
}, { file_total_parts: totalParts,
startMaxLength: partSize + 256, bytes: e.target.result
fileUpload: true }, {
}); startMaxLength: partSize + 256,
}, errorHandler); fileUpload: true,
singleInRequest: true
apiCurPromise.then(function (result) { }).then(function (result) {
doneParts++; doneParts++;
fileReadDeferred.resolve(); uploadDeferred.resolve();
if (doneParts >= totalParts) { if (doneParts >= totalParts) {
deferred.resolve(resultInputFile); deferred.resolve(resultInputFile);
resolved = true; resolved = true;
@ -587,8 +585,8 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
reader.readAsArrayBuffer(blob); reader.readAsArrayBuffer(blob);
return fileReadDeferred.promise; return uploadDeferred.promise;
}); }, activeDelta);
})(offset, part++); })(offset, part++);
} }

40
app/js/lib/ng_utils.js

@ -484,12 +484,12 @@ angular.module('izhukov.utils', [])
.service('CryptoWorker', function ($timeout, $q) { .service('CryptoWorker', function ($timeout, $q) {
var worker = window.Worker && new Worker('js/lib/crypto_worker.js') || false, var webWorker = false,
naClEmbed = false,
taskID = 0, taskID = 0,
awaiting = {}, awaiting = {},
webCrypto = window.crypto && (window.crypto.subtle || window.crypto.webkitSubtle) || window.msCrypto && window.msCrypto.subtle, webCrypto = window.crypto && (window.crypto.subtle || window.crypto.webkitSubtle) || window.msCrypto && window.msCrypto.subtle,
useSha1Crypto = webCrypto && webCrypto.digest !== undefined, useSha1Crypto = webCrypto && webCrypto.digest !== undefined,
aesNaClEmbed = false,
finalizeTask = function (taskID, result) { finalizeTask = function (taskID, result) {
var deferred = awaiting[taskID]; var deferred = awaiting[taskID];
if (deferred !== undefined) { if (deferred !== undefined) {
@ -502,7 +502,7 @@ angular.module('izhukov.utils', [])
if (navigator.mimeTypes['application/x-pnacl'] !== undefined) { if (navigator.mimeTypes['application/x-pnacl'] !== undefined) {
var listener = $('<div id="nacl_listener"><embed id="mtproto_crypto" width="0" height="0" src="nacl/mtproto_crypto.nmf?'+Math.random()+'" type="application/x-pnacl" /></div>').appendTo($('body'))[0]; var listener = $('<div id="nacl_listener"><embed id="mtproto_crypto" width="0" height="0" src="nacl/mtproto_crypto.nmf?'+Math.random()+'" type="application/x-pnacl" /></div>').appendTo($('body'))[0];
listener.addEventListener('load', function (e) { listener.addEventListener('load', function (e) {
aesNaClEmbed = listener.firstChild; naClEmbed = listener.firstChild;
console.log(dT(), 'NaCl ready'); console.log(dT(), 'NaCl ready');
}, true); }, true);
listener.addEventListener('message', function (e) { listener.addEventListener('message', function (e) {
@ -513,13 +513,18 @@ angular.module('izhukov.utils', [])
}, true); }, true);
} }
if (worker) { if (window.Worker) {
worker.onmessage = function (e) { var tmpWorker = new Worker('js/lib/crypto_worker.js');
finalizeTask(e.data.taskID, e.data.result); tmpWorker.onmessage = function (e) {
if (!webWorker) {
webWorker = tmpWorker;
} else {
finalizeTask(e.data.taskID, e.data.result);
}
}; };
worker.onerror = function(error) { tmpWorker.onerror = function(error) {
console.error('CW error', error, error.stack); console.error('CW error', error, error.stack);
worker = false; webWorker = false;
}; };
} }
@ -531,7 +536,7 @@ angular.module('izhukov.utils', [])
params.task = task; params.task = task;
params.taskID = taskID; params.taskID = taskID;
(embed || worker).postMessage(params); (embed || webWorker).postMessage(params);
taskID++; taskID++;
@ -561,34 +566,35 @@ angular.module('izhukov.utils', [])
}); });
}, },
aesEncrypt: function (bytes, keyBytes, ivBytes) { aesEncrypt: function (bytes, keyBytes, ivBytes) {
if (aesNaClEmbed) { if (naClEmbed) {
return performTaskWorker('aes-encrypt', { return performTaskWorker('aes-encrypt', {
bytes: addPadding(convertToArrayBuffer(bytes)), bytes: addPadding(convertToArrayBuffer(bytes)),
keyBytes: convertToArrayBuffer(keyBytes), keyBytes: convertToArrayBuffer(keyBytes),
ivBytes: convertToArrayBuffer(ivBytes) ivBytes: convertToArrayBuffer(ivBytes)
}, aesNaClEmbed); }, naClEmbed);
} }
return $timeout(function () { return $timeout(function () {
return convertToArrayBuffer(aesEncryptSync(bytes, keyBytes, ivBytes)); return convertToArrayBuffer(aesEncryptSync(bytes, keyBytes, ivBytes));
}); });
}, },
aesDecrypt: function (encryptedBytes, keyBytes, ivBytes) { aesDecrypt: function (encryptedBytes, keyBytes, ivBytes) {
if (aesNaClEmbed) { if (naClEmbed) {
return performTaskWorker('aes-decrypt', { return performTaskWorker('aes-decrypt', {
encryptedBytes: addPadding(convertToArrayBuffer(encryptedBytes)), encryptedBytes: addPadding(convertToArrayBuffer(encryptedBytes)),
keyBytes: convertToArrayBuffer(keyBytes), keyBytes: convertToArrayBuffer(keyBytes),
ivBytes: convertToArrayBuffer(ivBytes) ivBytes: convertToArrayBuffer(ivBytes)
}, aesNaClEmbed); }, naClEmbed);
} }
return $timeout(function () { return $timeout(function () {
return convertToArrayBuffer(aesDecryptSync(encryptedBytes, keyBytes, ivBytes)); return convertToArrayBuffer(aesDecryptSync(encryptedBytes, keyBytes, ivBytes));
}); });
}, },
factorize: function (bytes) { factorize: function (bytes) {
if (aesNaClEmbed && bytes.length <= 8) { bytes = convertToByteArray(bytes);
return performTaskWorker('factorize', {bytes: bytes}, aesNaClEmbed); if (naClEmbed && bytes.length <= 8) {
return performTaskWorker('factorize', {bytes: bytes}, naClEmbed);
} }
if (worker) { if (webWorker) {
return performTaskWorker('factorize', {bytes: bytes}); return performTaskWorker('factorize', {bytes: bytes});
} }
return $timeout(function () { return $timeout(function () {
@ -596,7 +602,7 @@ angular.module('izhukov.utils', [])
}); });
}, },
modPow: function (x, y, m) { modPow: function (x, y, m) {
if (worker) { if (webWorker) {
return performTaskWorker('mod-pow', { return performTaskWorker('mod-pow', {
x: x, x: x,
y: y, y: y,

4
app/js/lib/tl_utils.js

@ -148,6 +148,9 @@ TLSerialization.prototype.storeString = function (s, field) {
TLSerialization.prototype.storeBytes = function (bytes, field) { TLSerialization.prototype.storeBytes = function (bytes, field) {
if (bytes instanceof ArrayBuffer) {
bytes = new Uint8Array(bytes);
}
this.debug && console.log('>>>', bytesToHex(bytes), (field || '') + ':bytes'); this.debug && console.log('>>>', bytesToHex(bytes), (field || '') + ':bytes');
var len = bytes.byteLength || bytes.length; var len = bytes.byteLength || bytes.length;
@ -160,6 +163,7 @@ TLSerialization.prototype.storeBytes = function (bytes, field) {
this.byteView[this.offset++] = (len & 0xFF00) >> 8; this.byteView[this.offset++] = (len & 0xFF00) >> 8;
this.byteView[this.offset++] = (len & 0xFF0000) >> 16; this.byteView[this.offset++] = (len & 0xFF0000) >> 16;
} }
this.byteView.set(bytes, this.offset); this.byteView.set(bytes, this.offset);
this.offset += len; this.offset += len;

2
app/js/lib/utils.js

@ -63,7 +63,7 @@ function onContentLoaded (cb) {
}; };
function tsNow (seconds) { function tsNow (seconds) {
var t = +new Date(); var t = +new Date() + (window.tsOffset || 0);
return seconds ? Math.floor(t / 1000) : t; return seconds ? Math.floor(t / 1000) : t;
} }

11
app/js/services.js

@ -401,7 +401,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
phones: [] phones: []
}; };
if (this.result.tel !== undefined) { if (this.result.tel != undefined) {
for (var i = 0; i < this.result.tel.length; i++) { for (var i = 0; i < this.result.tel.length; i++) {
contact.phones.push(this.result.tel[i].value); contact.phones.push(this.result.tel[i].value);
} }
@ -741,7 +741,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
offset: offset || 0, offset: offset || 0,
limit: limit || 0, limit: limit || 0,
max_id: maxID || 0 max_id: maxID || 0
}).then(function (historyResult) { }, {noErrorBox: true}).then(function (historyResult) {
AppUsersManager.saveApiUsers(historyResult.users); AppUsersManager.saveApiUsers(historyResult.users);
AppChatsManager.saveApiChats(historyResult.chats); AppChatsManager.saveApiChats(historyResult.chats);
saveMessages(historyResult.messages); saveMessages(historyResult.messages);
@ -2810,6 +2810,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
switch (updateMessage._) { switch (updateMessage._) {
case 'updatesTooLong': case 'updatesTooLong':
case 'new_session_created':
forceGetDifference(); forceGetDifference();
break; break;
@ -3003,11 +3004,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function attach () { function attach () {
MtpNetworkerFactory.setUpdatesProcessor(processUpdateMessage); MtpNetworkerFactory.setUpdatesProcessor(processUpdateMessage);
MtpApiManager.invokeApi('updates.getState', {noErrorBox: true}).then(function (stateResult) { MtpApiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then(function (stateResult) {
curState.seq = stateResult.seq; curState.seq = stateResult.seq;
curState.pts = stateResult.pts; curState.pts = stateResult.pts;
curState.date = stateResult.date; curState.date = stateResult.date;
isSynchronizing = false; setTimeout(function () {
isSynchronizing = false;
}, 1000);
}) })
} }

Loading…
Cancel
Save