diff --git a/js/libtextsecure.js b/js/libtextsecure.js index 749d2e80..c13c4b5e 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -39634,6 +39634,7 @@ textsecure.MessageReceiver.prototype = { */ function MessageSender(url, username, password) { this.server = new TextSecureServer(url, username, password); + this.pendingMessages = {}; } MessageSender.prototype = { @@ -39736,7 +39737,7 @@ MessageSender.prototype = { return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { if (devicesForNumber.length == 0) return registerError(number, "Got empty device list when loading device keys", null); - doSendMessage(number, devicesForNumber, recurse); + return doSendMessage(number, devicesForNumber, recurse); }); } }; @@ -39795,9 +39796,9 @@ MessageSender.prototype = { })); } - p.then(function() { + return p.then(function() { var resetDevices = ((error.code == 410) ? error.response.staleDevices : error.response.missingDevices); - getKeysForNumber(number, resetDevices) + return getKeysForNumber(number, resetDevices) .then(reloadDevicesAndSend(number, (error.code == 409))) .catch(function(error) { registerError(number, "Failed to reload device keys", error); @@ -39809,8 +39810,8 @@ MessageSender.prototype = { }); }.bind(this); - numbers.forEach(function(number) { - textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { + function sendToNumber(number) { + return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { return Promise.all(devicesForNumber.map(function(device) { return textsecure.protocol_wrapper.hasOpenSession(device.encodedNumber).then(function(result) { if (!result) @@ -39819,17 +39820,31 @@ MessageSender.prototype = { })).then(function() { return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { if (devicesForNumber.length == 0) { - getKeysForNumber(number, [1]) + return getKeysForNumber(number, [1]) .then(reloadDevicesAndSend(number, true)) .catch(function(error) { registerError(number, "Failed to retreive new device keys for number " + number, error); }); } else - doSendMessage(number, devicesForNumber, true); + return doSendMessage(number, devicesForNumber, true); }); }); }); - }); + } + + numbers.forEach(function(number) { + var sendPrevious = this.pendingMessages[number] || Promise.resolve(); + var sendCurrent = this.pendingMessages[number] = sendPrevious.then(function() { + return sendToNumber(number); + }).catch(function() { + return sendToNumber(number); + }); + sendCurrent.then(function() { + if (this.pendingMessages[number] === sendCurrent) { + delete this.pendingMessages[number]; + } + }.bind(this)); + }.bind(this)); }, sendIndividualProto: function(number, proto, timestamp) { diff --git a/libtextsecure/sendmessage.js b/libtextsecure/sendmessage.js index 514a2c12..9ef7eda2 100644 --- a/libtextsecure/sendmessage.js +++ b/libtextsecure/sendmessage.js @@ -3,6 +3,7 @@ */ function MessageSender(url, username, password) { this.server = new TextSecureServer(url, username, password); + this.pendingMessages = {}; } MessageSender.prototype = { @@ -105,7 +106,7 @@ MessageSender.prototype = { return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { if (devicesForNumber.length == 0) return registerError(number, "Got empty device list when loading device keys", null); - doSendMessage(number, devicesForNumber, recurse); + return doSendMessage(number, devicesForNumber, recurse); }); } }; @@ -164,9 +165,9 @@ MessageSender.prototype = { })); } - p.then(function() { + return p.then(function() { var resetDevices = ((error.code == 410) ? error.response.staleDevices : error.response.missingDevices); - getKeysForNumber(number, resetDevices) + return getKeysForNumber(number, resetDevices) .then(reloadDevicesAndSend(number, (error.code == 409))) .catch(function(error) { registerError(number, "Failed to reload device keys", error); @@ -178,8 +179,8 @@ MessageSender.prototype = { }); }.bind(this); - numbers.forEach(function(number) { - textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { + function sendToNumber(number) { + return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { return Promise.all(devicesForNumber.map(function(device) { return textsecure.protocol_wrapper.hasOpenSession(device.encodedNumber).then(function(result) { if (!result) @@ -188,17 +189,31 @@ MessageSender.prototype = { })).then(function() { return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devicesForNumber) { if (devicesForNumber.length == 0) { - getKeysForNumber(number, [1]) + return getKeysForNumber(number, [1]) .then(reloadDevicesAndSend(number, true)) .catch(function(error) { registerError(number, "Failed to retreive new device keys for number " + number, error); }); } else - doSendMessage(number, devicesForNumber, true); + return doSendMessage(number, devicesForNumber, true); }); }); }); - }); + } + + numbers.forEach(function(number) { + var sendPrevious = this.pendingMessages[number] || Promise.resolve(); + var sendCurrent = this.pendingMessages[number] = sendPrevious.then(function() { + return sendToNumber(number); + }).catch(function() { + return sendToNumber(number); + }); + sendCurrent.then(function() { + if (this.pendingMessages[number] === sendCurrent) { + delete this.pendingMessages[number]; + } + }.bind(this)); + }.bind(this)); }, sendIndividualProto: function(number, proto, timestamp) {