From 816a20689213c2663ddac45542e8fdda82d8a041 Mon Sep 17 00:00:00 2001 From: lilia Date: Sat, 10 Oct 2015 15:45:07 -0700 Subject: [PATCH] Refactor sendMessageToDevices Split into separate encrypt and transmit functions. Let the encryption function also handle all wire formatting (ie, jsonification and base64 encoding), which simplifes TextSecureServer.sendMessages, removes a TODO, and lets us save fewer params to make network errors replayable. // FREEBIE --- js/libtextsecure.js | 52 ++++++++++++++++++------------------ libtextsecure/api.js | 10 +------ libtextsecure/errors.js | 4 +-- libtextsecure/sendmessage.js | 38 +++++++++++++++----------- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/js/libtextsecure.js b/js/libtextsecure.js index da5e4599..e996a4e1 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -74,10 +74,10 @@ OutgoingMessageError.prototype = new ReplayableError(); OutgoingMessageError.prototype.constructor = OutgoingMessageError; - function SendMessageNetworkError(number, jsonData, legacy, httpError) { + function SendMessageNetworkError(number, jsonData, httpError) { ReplayableError.call(this, { functionCode : Type.TRANSMIT_MESSAGE, - args : [number, jsonData, legacy] + args : [number, jsonData] }); this.name = 'SendMessageNetworkError'; this.number = number; @@ -38954,15 +38954,7 @@ var TextSecureServer = (function() { return res; }); }, - sendMessages: function(destination, messageArray, legacy) { - //TODO: Do this conversion somewhere else? - for (var i = 0; i < messageArray.length; i++) { - messageArray[i].content = btoa(messageArray[i].content); - if (legacy) { - messageArray[i].body = messageArray[i].content; - delete messageArray[i].content; - } - } + sendMessages: function(destination, messageArray) { var jsonData = { messages: messageArray }; jsonData.timestamp = messageArray[0].timestamp; @@ -39627,8 +39619,9 @@ function MessageSender(url, username, password) { MessageSender.prototype = { constructor: MessageSender, - // message == DataMessage or ContentMessage proto - sendMessageToDevices: function(timestamp, number, deviceObjectList, message) { + // message == DataMessage or ContentMessage proto + encryptToDevices: function(timestamp, number, deviceObjectList, message) { + var legacy = (message instanceof textsecure.protobuf.DataMessage); var relay = deviceObjectList[0].relay; for (var i=1; i < deviceObjectList.length; ++i) { if (deviceObjectList[i].relay !== relay) { @@ -39643,7 +39636,6 @@ MessageSender.prototype = { type: encryptedMsg.type, destinationDeviceId: textsecure.utils.unencodeNumber(device.encodedNumber)[1], destinationRegistrationId: registrationId, - content: encryptedMsg.body, timestamp: timestamp }; @@ -39651,20 +39643,26 @@ MessageSender.prototype = { json.relay = device.relay; } + var content = btoa(encryptedMsg.body); + if (legacy) { + json.body = content; + } else { + json.content = content; + } + return json; }); }); }); - })).then(function(jsonData) { - var legacy = (message instanceof textsecure.protobuf.DataMessage); - return this.sendMessageRequest(number, jsonData, legacy); - }.bind(this)); + })); }, - sendMessageRequest: function(number, jsonData, legacy) { - return this.server.sendMessages(number, jsonData, legacy).catch(function(e) { + transmitMessage: function(number, jsonData) { + return this.server.sendMessages(number, jsonData).catch(function(e) { if (e.name === 'HTTPError' && (e.code !== 409 && e.code !== 410)) { - throw new textsecure.SendMessageNetworkError(number, jsonData, legacy, e); + // 409 and 410 should bubble and be handled by doSendMessage + // all other network errors can be retried later. + throw new textsecure.SendMessageNetworkError(number, jsonData, e); } throw e; }); @@ -39759,10 +39757,12 @@ MessageSender.prototype = { }.bind(this); var doSendMessage = function(number, devicesForNumber, recurse) { - return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) { - successfulNumbers[successfulNumbers.length] = number; - numberCompleted(); - }).catch(function(error) { + return this.encryptToDevices(timestamp, number, devicesForNumber, message).then(function(jsonData) { + return this.transmitMessage(number, jsonData).then(function() { + successfulNumbers[successfulNumbers.length] = number; + numberCompleted(); + }.bind(this)); + }.bind(this)).catch(function(error) { if (error instanceof Error && error.name == "HTTPError" && (error.code == 410 || error.code == 409)) { if (!recurse) return registerError(number, "Hit retry limit attempting to reload device list", error); @@ -40047,7 +40047,7 @@ window.textsecure = window.textsecure || {}; textsecure.MessageSender = function(url, username, password) { var sender = new MessageSender(url, username, password); textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE); - textsecure.replay.registerFunction(sender.sendMessageRequest.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE); + textsecure.replay.registerFunction(sender.transmitMessage.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE); this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender); this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender); diff --git a/libtextsecure/api.js b/libtextsecure/api.js index 99db98ab..2ec7f993 100644 --- a/libtextsecure/api.js +++ b/libtextsecure/api.js @@ -230,15 +230,7 @@ var TextSecureServer = (function() { return res; }); }, - sendMessages: function(destination, messageArray, legacy) { - //TODO: Do this conversion somewhere else? - for (var i = 0; i < messageArray.length; i++) { - messageArray[i].content = btoa(messageArray[i].content); - if (legacy) { - messageArray[i].body = messageArray[i].content; - delete messageArray[i].content; - } - } + sendMessages: function(destination, messageArray) { var jsonData = { messages: messageArray }; jsonData.timestamp = messageArray[0].timestamp; diff --git a/libtextsecure/errors.js b/libtextsecure/errors.js index 4f1d2c6f..95b8586c 100644 --- a/libtextsecure/errors.js +++ b/libtextsecure/errors.js @@ -73,10 +73,10 @@ OutgoingMessageError.prototype = new ReplayableError(); OutgoingMessageError.prototype.constructor = OutgoingMessageError; - function SendMessageNetworkError(number, jsonData, legacy, httpError) { + function SendMessageNetworkError(number, jsonData, httpError) { ReplayableError.call(this, { functionCode : Type.TRANSMIT_MESSAGE, - args : [number, jsonData, legacy] + args : [number, jsonData] }); this.name = 'SendMessageNetworkError'; this.number = number; diff --git a/libtextsecure/sendmessage.js b/libtextsecure/sendmessage.js index abd968e0..514a2c12 100644 --- a/libtextsecure/sendmessage.js +++ b/libtextsecure/sendmessage.js @@ -7,8 +7,9 @@ function MessageSender(url, username, password) { MessageSender.prototype = { constructor: MessageSender, - // message == DataMessage or ContentMessage proto - sendMessageToDevices: function(timestamp, number, deviceObjectList, message) { + // message == DataMessage or ContentMessage proto + encryptToDevices: function(timestamp, number, deviceObjectList, message) { + var legacy = (message instanceof textsecure.protobuf.DataMessage); var relay = deviceObjectList[0].relay; for (var i=1; i < deviceObjectList.length; ++i) { if (deviceObjectList[i].relay !== relay) { @@ -23,7 +24,6 @@ MessageSender.prototype = { type: encryptedMsg.type, destinationDeviceId: textsecure.utils.unencodeNumber(device.encodedNumber)[1], destinationRegistrationId: registrationId, - content: encryptedMsg.body, timestamp: timestamp }; @@ -31,20 +31,26 @@ MessageSender.prototype = { json.relay = device.relay; } + var content = btoa(encryptedMsg.body); + if (legacy) { + json.body = content; + } else { + json.content = content; + } + return json; }); }); }); - })).then(function(jsonData) { - var legacy = (message instanceof textsecure.protobuf.DataMessage); - return this.sendMessageRequest(number, jsonData, legacy); - }.bind(this)); + })); }, - sendMessageRequest: function(number, jsonData, legacy) { - return this.server.sendMessages(number, jsonData, legacy).catch(function(e) { + transmitMessage: function(number, jsonData) { + return this.server.sendMessages(number, jsonData).catch(function(e) { if (e.name === 'HTTPError' && (e.code !== 409 && e.code !== 410)) { - throw new textsecure.SendMessageNetworkError(number, jsonData, legacy, e); + // 409 and 410 should bubble and be handled by doSendMessage + // all other network errors can be retried later. + throw new textsecure.SendMessageNetworkError(number, jsonData, e); } throw e; }); @@ -139,10 +145,12 @@ MessageSender.prototype = { }.bind(this); var doSendMessage = function(number, devicesForNumber, recurse) { - return this.sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) { - successfulNumbers[successfulNumbers.length] = number; - numberCompleted(); - }).catch(function(error) { + return this.encryptToDevices(timestamp, number, devicesForNumber, message).then(function(jsonData) { + return this.transmitMessage(number, jsonData).then(function() { + successfulNumbers[successfulNumbers.length] = number; + numberCompleted(); + }.bind(this)); + }.bind(this)).catch(function(error) { if (error instanceof Error && error.name == "HTTPError" && (error.code == 410 || error.code == 409)) { if (!recurse) return registerError(number, "Hit retry limit attempting to reload device list", error); @@ -427,7 +435,7 @@ window.textsecure = window.textsecure || {}; textsecure.MessageSender = function(url, username, password) { var sender = new MessageSender(url, username, password); textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE); - textsecure.replay.registerFunction(sender.sendMessageRequest.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE); + textsecure.replay.registerFunction(sender.transmitMessage.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE); this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender); this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);