Add replayable error for signed key failure
Disable message sending if signed key updates fail too many times, but allow the user to retry sending. // FREEBIE
This commit is contained in:
parent
e0fd188d42
commit
cd0fe7037b
5 changed files with 77 additions and 7 deletions
|
@ -11,6 +11,7 @@
|
||||||
INIT_SESSION: 2,
|
INIT_SESSION: 2,
|
||||||
TRANSMIT_MESSAGE: 3,
|
TRANSMIT_MESSAGE: 3,
|
||||||
REBUILD_MESSAGE: 4,
|
REBUILD_MESSAGE: 4,
|
||||||
|
RETRY_SEND_MESSAGE_PROTO: 5
|
||||||
};
|
};
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.replay = {
|
window.textsecure.replay = {
|
||||||
|
@ -89,6 +90,17 @@
|
||||||
SendMessageNetworkError.prototype = new ReplayableError();
|
SendMessageNetworkError.prototype = new ReplayableError();
|
||||||
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
||||||
|
|
||||||
|
function SignedPreKeyRotationError(numbers, message, timestamp) {
|
||||||
|
ReplayableError.call(this, {
|
||||||
|
functionCode : Type.RETRY_SEND_MESSAGE_PROTO,
|
||||||
|
args : [numbers, message, timestamp]
|
||||||
|
});
|
||||||
|
this.name = 'SignedPreKeyRotationError';
|
||||||
|
this.message = "Too many signed prekey rotation failures";
|
||||||
|
}
|
||||||
|
SignedPreKeyRotationError.prototype = new ReplayableError();
|
||||||
|
SignedPreKeyRotationError.prototype.constructor = SignedPreKeyRotationError;
|
||||||
|
|
||||||
function MessageError(message, httpError) {
|
function MessageError(message, httpError) {
|
||||||
ReplayableError.call(this, {
|
ReplayableError.call(this, {
|
||||||
functionCode : Type.REBUILD_MESSAGE,
|
functionCode : Type.REBUILD_MESSAGE,
|
||||||
|
@ -119,6 +131,7 @@
|
||||||
window.textsecure.ReplayableError = ReplayableError;
|
window.textsecure.ReplayableError = ReplayableError;
|
||||||
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
||||||
window.textsecure.MessageError = MessageError;
|
window.textsecure.MessageError = MessageError;
|
||||||
|
window.textsecure.SignedPreKeyRotationError = SignedPreKeyRotationError;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -39014,6 +39027,11 @@ MessageSender.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
sendMessageProto: function(timestamp, numbers, message, callback) {
|
sendMessageProto: function(timestamp, numbers, message, callback) {
|
||||||
|
var rejections = textsecure.storage.get('signedKeyRotationRejected', 0);
|
||||||
|
if (rejections > 5) {
|
||||||
|
throw new textsecure.SignedPreKeyRotationError(numbers, message.toArrayBuffer(), timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
||||||
|
|
||||||
numbers.forEach(function(number) {
|
numbers.forEach(function(number) {
|
||||||
|
@ -39023,6 +39041,18 @@ MessageSender.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
retrySendMessageProto: function(numbers, encodedMessage, timestamp) {
|
||||||
|
var proto = textsecure.protobuf.DataMessage.decode(encodedMessage);
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
this.sendMessageProto(timestamp, numbers, proto, function(res) {
|
||||||
|
if (res.errors.length > 0)
|
||||||
|
reject(res);
|
||||||
|
else
|
||||||
|
resolve(res);
|
||||||
|
});
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
sendIndividualProto: function(number, proto, timestamp) {
|
sendIndividualProto: function(number, proto, timestamp) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
this.sendMessageProto(timestamp, [number], proto, function(res) {
|
this.sendMessageProto(timestamp, [number], proto, function(res) {
|
||||||
|
@ -39330,6 +39360,7 @@ textsecure.MessageSender = function(url, ports, username, password, attachment_s
|
||||||
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE);
|
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE);
|
||||||
textsecure.replay.registerFunction(sender.retransmitMessage.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE);
|
textsecure.replay.registerFunction(sender.retransmitMessage.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE);
|
||||||
textsecure.replay.registerFunction(sender.sendMessage.bind(sender), textsecure.replay.Type.REBUILD_MESSAGE);
|
textsecure.replay.registerFunction(sender.sendMessage.bind(sender), textsecure.replay.Type.REBUILD_MESSAGE);
|
||||||
|
textsecure.replay.registerFunction(sender.retrySendMessageProto.bind(sender), textsecure.replay.Type.RETRY_SEND_MESSAGE_PROTO);
|
||||||
|
|
||||||
this.sendExpirationTimerUpdateToNumber = sender.sendExpirationTimerUpdateToNumber.bind(sender);
|
this.sendExpirationTimerUpdateToNumber = sender.sendExpirationTimerUpdateToNumber.bind(sender);
|
||||||
this.sendExpirationTimerUpdateToGroup = sender.sendExpirationTimerUpdateToGroup .bind(sender);
|
this.sendExpirationTimerUpdateToGroup = sender.sendExpirationTimerUpdateToGroup .bind(sender);
|
||||||
|
|
|
@ -211,6 +211,9 @@
|
||||||
if (result instanceof Error) {
|
if (result instanceof Error) {
|
||||||
errors = [result];
|
errors = [result];
|
||||||
this.saveErrors(errors);
|
this.saveErrors(errors);
|
||||||
|
if (result.name === 'SignedPreKeyRotationError') {
|
||||||
|
getAccountManager().rotateSignedPreKey();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errors = result.errors;
|
errors = result.errors;
|
||||||
this.saveErrors(errors);
|
this.saveErrors(errors);
|
||||||
|
@ -283,7 +286,8 @@
|
||||||
var error = _.find(this.get('errors'), function(e) {
|
var error = _.find(this.get('errors'), function(e) {
|
||||||
return (e.name === 'MessageError' ||
|
return (e.name === 'MessageError' ||
|
||||||
e.name === 'OutgoingMessageError' ||
|
e.name === 'OutgoingMessageError' ||
|
||||||
e.name === 'SendMessageNetworkError');
|
e.name === 'SendMessageNetworkError' ||
|
||||||
|
e.name === 'SignedPreKeyRotationError');
|
||||||
});
|
});
|
||||||
return !!error;
|
return !!error;
|
||||||
},
|
},
|
||||||
|
@ -292,11 +296,18 @@
|
||||||
return e.number === number &&
|
return e.number === number &&
|
||||||
(e.name === 'MessageError' ||
|
(e.name === 'MessageError' ||
|
||||||
e.name === 'OutgoingMessageError' ||
|
e.name === 'OutgoingMessageError' ||
|
||||||
e.name === 'SendMessageNetworkError');
|
e.name === 'SendMessageNetworkError' ||
|
||||||
|
e.name === 'SignedPreKeyRotationError');
|
||||||
});
|
});
|
||||||
this.set({errors: errors[1]});
|
this.set({errors: errors[1]});
|
||||||
return errors[0][0];
|
return errors[0][0];
|
||||||
},
|
},
|
||||||
|
isReplayableError: function(e) {
|
||||||
|
return (e.name === 'MessageError' ||
|
||||||
|
e.name === 'OutgoingMessageError' ||
|
||||||
|
e.name === 'SendMessageNetworkError' ||
|
||||||
|
e.name === 'SignedPreKeyRotationError');
|
||||||
|
},
|
||||||
|
|
||||||
resend: function(number) {
|
resend: function(number) {
|
||||||
var error = this.removeOutgoingErrors(number);
|
var error = this.removeOutgoingErrors(number);
|
||||||
|
|
|
@ -131,11 +131,8 @@
|
||||||
'click .error-message': 'select'
|
'click .error-message': 'select'
|
||||||
},
|
},
|
||||||
retryMessage: function() {
|
retryMessage: function() {
|
||||||
var retrys = _.filter(this.model.get('errors'), function(e) {
|
var retrys = _.filter(this.model.get('errors'),
|
||||||
return (e.name === 'MessageError' ||
|
this.model.isReplayableError.bind(this.model));
|
||||||
e.name === 'OutgoingMessageError' ||
|
|
||||||
e.name === 'SendMessageNetworkError');
|
|
||||||
});
|
|
||||||
_.map(retrys, 'number').forEach(function(number) {
|
_.map(retrys, 'number').forEach(function(number) {
|
||||||
this.model.resend(number);
|
this.model.resend(number);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
INIT_SESSION: 2,
|
INIT_SESSION: 2,
|
||||||
TRANSMIT_MESSAGE: 3,
|
TRANSMIT_MESSAGE: 3,
|
||||||
REBUILD_MESSAGE: 4,
|
REBUILD_MESSAGE: 4,
|
||||||
|
RETRY_SEND_MESSAGE_PROTO: 5
|
||||||
};
|
};
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.replay = {
|
window.textsecure.replay = {
|
||||||
|
@ -88,6 +89,17 @@
|
||||||
SendMessageNetworkError.prototype = new ReplayableError();
|
SendMessageNetworkError.prototype = new ReplayableError();
|
||||||
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
||||||
|
|
||||||
|
function SignedPreKeyRotationError(numbers, message, timestamp) {
|
||||||
|
ReplayableError.call(this, {
|
||||||
|
functionCode : Type.RETRY_SEND_MESSAGE_PROTO,
|
||||||
|
args : [numbers, message, timestamp]
|
||||||
|
});
|
||||||
|
this.name = 'SignedPreKeyRotationError';
|
||||||
|
this.message = "Too many signed prekey rotation failures";
|
||||||
|
}
|
||||||
|
SignedPreKeyRotationError.prototype = new ReplayableError();
|
||||||
|
SignedPreKeyRotationError.prototype.constructor = SignedPreKeyRotationError;
|
||||||
|
|
||||||
function MessageError(message, httpError) {
|
function MessageError(message, httpError) {
|
||||||
ReplayableError.call(this, {
|
ReplayableError.call(this, {
|
||||||
functionCode : Type.REBUILD_MESSAGE,
|
functionCode : Type.REBUILD_MESSAGE,
|
||||||
|
@ -118,5 +130,6 @@
|
||||||
window.textsecure.ReplayableError = ReplayableError;
|
window.textsecure.ReplayableError = ReplayableError;
|
||||||
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
||||||
window.textsecure.MessageError = MessageError;
|
window.textsecure.MessageError = MessageError;
|
||||||
|
window.textsecure.SignedPreKeyRotationError = SignedPreKeyRotationError;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -183,6 +183,11 @@ MessageSender.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
sendMessageProto: function(timestamp, numbers, message, callback) {
|
sendMessageProto: function(timestamp, numbers, message, callback) {
|
||||||
|
var rejections = textsecure.storage.get('signedKeyRotationRejected', 0);
|
||||||
|
if (rejections > 5) {
|
||||||
|
throw new textsecure.SignedPreKeyRotationError(numbers, message.toArrayBuffer(), timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
||||||
|
|
||||||
numbers.forEach(function(number) {
|
numbers.forEach(function(number) {
|
||||||
|
@ -192,6 +197,18 @@ MessageSender.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
retrySendMessageProto: function(numbers, encodedMessage, timestamp) {
|
||||||
|
var proto = textsecure.protobuf.DataMessage.decode(encodedMessage);
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
this.sendMessageProto(timestamp, numbers, proto, function(res) {
|
||||||
|
if (res.errors.length > 0)
|
||||||
|
reject(res);
|
||||||
|
else
|
||||||
|
resolve(res);
|
||||||
|
});
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
sendIndividualProto: function(number, proto, timestamp) {
|
sendIndividualProto: function(number, proto, timestamp) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
this.sendMessageProto(timestamp, [number], proto, function(res) {
|
this.sendMessageProto(timestamp, [number], proto, function(res) {
|
||||||
|
@ -499,6 +516,7 @@ textsecure.MessageSender = function(url, ports, username, password, attachment_s
|
||||||
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE);
|
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE);
|
||||||
textsecure.replay.registerFunction(sender.retransmitMessage.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE);
|
textsecure.replay.registerFunction(sender.retransmitMessage.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE);
|
||||||
textsecure.replay.registerFunction(sender.sendMessage.bind(sender), textsecure.replay.Type.REBUILD_MESSAGE);
|
textsecure.replay.registerFunction(sender.sendMessage.bind(sender), textsecure.replay.Type.REBUILD_MESSAGE);
|
||||||
|
textsecure.replay.registerFunction(sender.retrySendMessageProto.bind(sender), textsecure.replay.Type.RETRY_SEND_MESSAGE_PROTO);
|
||||||
|
|
||||||
this.sendExpirationTimerUpdateToNumber = sender.sendExpirationTimerUpdateToNumber.bind(sender);
|
this.sendExpirationTimerUpdateToNumber = sender.sendExpirationTimerUpdateToNumber.bind(sender);
|
||||||
this.sendExpirationTimerUpdateToGroup = sender.sendExpirationTimerUpdateToGroup .bind(sender);
|
this.sendExpirationTimerUpdateToGroup = sender.sendExpirationTimerUpdateToGroup .bind(sender);
|
||||||
|
|
Loading…
Reference in a new issue