Handle attachment upload errors
Adds a new kind of replayable error that handles retry of pre-encryption failures, e.g., attachment upload. Fixes #485 // FREEBIE
This commit is contained in:
parent
910e37649a
commit
7e82d1295c
5 changed files with 64 additions and 17 deletions
|
@ -10,6 +10,7 @@
|
||||||
ENCRYPT_MESSAGE: 1,
|
ENCRYPT_MESSAGE: 1,
|
||||||
INIT_SESSION: 2,
|
INIT_SESSION: 2,
|
||||||
TRANSMIT_MESSAGE: 3,
|
TRANSMIT_MESSAGE: 3,
|
||||||
|
REBUILD_MESSAGE: 4,
|
||||||
};
|
};
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.replay = {
|
window.textsecure.replay = {
|
||||||
|
@ -88,11 +89,26 @@
|
||||||
SendMessageNetworkError.prototype = new ReplayableError();
|
SendMessageNetworkError.prototype = new ReplayableError();
|
||||||
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
||||||
|
|
||||||
|
function MessageError(message, httpError) {
|
||||||
|
ReplayableError.call(this, {
|
||||||
|
functionCode : Type.REBUILD_MESSAGE,
|
||||||
|
args : [message]
|
||||||
|
});
|
||||||
|
this.name = 'MessageError';
|
||||||
|
this.code = httpError.code;
|
||||||
|
this.message = httpError.message;
|
||||||
|
this.stack = httpError.stack;
|
||||||
|
}
|
||||||
|
MessageError.prototype = new ReplayableError();
|
||||||
|
MessageError.prototype.constructor = MessageError;
|
||||||
|
|
||||||
|
|
||||||
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
|
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
|
||||||
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
|
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
|
||||||
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
|
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
|
||||||
window.textsecure.ReplayableError = ReplayableError;
|
window.textsecure.ReplayableError = ReplayableError;
|
||||||
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
||||||
|
window.textsecure.MessageError = MessageError;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -37432,6 +37448,7 @@ function Message(options) {
|
||||||
this.timestamp = options.timestamp;
|
this.timestamp = options.timestamp;
|
||||||
this.needsSync = options.needsSync;
|
this.needsSync = options.needsSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message.prototype = {
|
Message.prototype = {
|
||||||
constructor: Message,
|
constructor: Message,
|
||||||
toProto: function() {
|
toProto: function() {
|
||||||
|
@ -37502,7 +37519,8 @@ MessageSender.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
sendMessage: function(message) {
|
sendMessage: function(attrs) {
|
||||||
|
var message = new Message(attrs);
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
message.attachments.map(this.makeAttachmentPointer.bind(this))
|
message.attachments.map(this.makeAttachmentPointer.bind(this))
|
||||||
).then(function(attachmentPointers) {
|
).then(function(attachmentPointers) {
|
||||||
|
@ -37522,7 +37540,13 @@ MessageSender.prototype = {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}.bind(this));
|
}.bind(this)).catch(function(error) {
|
||||||
|
if (error instanceof Error && error.name === 'HTTPError') {
|
||||||
|
throw new textsecure.MessageError(attrs, error);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
sendMessageProto: function(timestamp, numbers, message, callback) {
|
sendMessageProto: function(timestamp, numbers, message, callback) {
|
||||||
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
||||||
|
@ -37616,15 +37640,13 @@ MessageSender.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
sendMessageToNumber: function(number, messageText, attachments, timestamp) {
|
sendMessageToNumber: function(number, messageText, attachments, timestamp) {
|
||||||
var message = new Message({
|
return this.sendMessage({
|
||||||
recipients : [number],
|
recipients : [number],
|
||||||
body : messageText,
|
body : messageText,
|
||||||
timestamp : timestamp,
|
timestamp : timestamp,
|
||||||
attachments : attachments,
|
attachments : attachments,
|
||||||
needsSync : true
|
needsSync : true
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.sendMessage(message);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
closeSession: function(number, timestamp) {
|
closeSession: function(number, timestamp) {
|
||||||
|
@ -37655,7 +37677,7 @@ MessageSender.prototype = {
|
||||||
return Promise.reject(new Error('No other members in the group'));
|
return Promise.reject(new Error('No other members in the group'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = new Message({
|
return this.sendMessage({
|
||||||
recipients : numbers,
|
recipients : numbers,
|
||||||
body : messageText,
|
body : messageText,
|
||||||
timestamp : timestamp,
|
timestamp : timestamp,
|
||||||
|
@ -37666,7 +37688,6 @@ MessageSender.prototype = {
|
||||||
type: textsecure.protobuf.GroupContext.Type.DELIVER
|
type: textsecure.protobuf.GroupContext.Type.DELIVER
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return this.sendMessage(message);
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -37785,6 +37806,7 @@ textsecure.MessageSender = function(url, username, password, attachment_server_u
|
||||||
var sender = new MessageSender(url, username, password, attachment_server_url);
|
var sender = new MessageSender(url, username, password, attachment_server_url);
|
||||||
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);
|
||||||
|
|
||||||
this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender);
|
this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender);
|
||||||
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);
|
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);
|
||||||
|
|
|
@ -212,7 +212,8 @@
|
||||||
removeOutgoingErrors: function(number) {
|
removeOutgoingErrors: function(number) {
|
||||||
var errors = _.partition(this.get('errors'), function(e) {
|
var errors = _.partition(this.get('errors'), function(e) {
|
||||||
return e.number === number &&
|
return e.number === number &&
|
||||||
(e.name === 'OutgoingMessageError' ||
|
(e.name === 'MessageError' ||
|
||||||
|
e.name === 'OutgoingMessageError' ||
|
||||||
e.name === 'SendMessageNetworkError');
|
e.name === 'SendMessageNetworkError');
|
||||||
});
|
});
|
||||||
this.set({errors: errors[1]});
|
this.set({errors: errors[1]});
|
||||||
|
|
|
@ -86,7 +86,8 @@
|
||||||
},
|
},
|
||||||
retryMessage: function() {
|
retryMessage: function() {
|
||||||
var retrys = _.filter(this.model.get('errors'), function(e) {
|
var retrys = _.filter(this.model.get('errors'), function(e) {
|
||||||
return (e.name === 'OutgoingMessageError' ||
|
return (e.name === 'MessageError' ||
|
||||||
|
e.name === 'OutgoingMessageError' ||
|
||||||
e.name === 'SendMessageNetworkError');
|
e.name === 'SendMessageNetworkError');
|
||||||
});
|
});
|
||||||
_.map(retrys, 'number').forEach(function(number) {
|
_.map(retrys, 'number').forEach(function(number) {
|
||||||
|
@ -105,7 +106,8 @@
|
||||||
render: function() {
|
render: function() {
|
||||||
this.errors = _.groupBy(this.model.get('errors'), 'number');
|
this.errors = _.groupBy(this.model.get('errors'), 'number');
|
||||||
var hasRetry = _.find(this.model.get('errors'), function(e) {
|
var hasRetry = _.find(this.model.get('errors'), function(e) {
|
||||||
return (e.name === 'OutgoingMessageError' ||
|
return (e.name === 'MessageError' ||
|
||||||
|
e.name === 'OutgoingMessageError' ||
|
||||||
e.name === 'SendMessageNetworkError');
|
e.name === 'SendMessageNetworkError');
|
||||||
});
|
});
|
||||||
this.$el.html(Mustache.render(_.result(this, 'template', ''), {
|
this.$el.html(Mustache.render(_.result(this, 'template', ''), {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
ENCRYPT_MESSAGE: 1,
|
ENCRYPT_MESSAGE: 1,
|
||||||
INIT_SESSION: 2,
|
INIT_SESSION: 2,
|
||||||
TRANSMIT_MESSAGE: 3,
|
TRANSMIT_MESSAGE: 3,
|
||||||
|
REBUILD_MESSAGE: 4,
|
||||||
};
|
};
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.replay = {
|
window.textsecure.replay = {
|
||||||
|
@ -87,10 +88,25 @@
|
||||||
SendMessageNetworkError.prototype = new ReplayableError();
|
SendMessageNetworkError.prototype = new ReplayableError();
|
||||||
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
||||||
|
|
||||||
|
function MessageError(message, httpError) {
|
||||||
|
ReplayableError.call(this, {
|
||||||
|
functionCode : Type.REBUILD_MESSAGE,
|
||||||
|
args : [message]
|
||||||
|
});
|
||||||
|
this.name = 'MessageError';
|
||||||
|
this.code = httpError.code;
|
||||||
|
this.message = httpError.message;
|
||||||
|
this.stack = httpError.stack;
|
||||||
|
}
|
||||||
|
MessageError.prototype = new ReplayableError();
|
||||||
|
MessageError.prototype.constructor = MessageError;
|
||||||
|
|
||||||
|
|
||||||
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
|
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
|
||||||
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
|
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
|
||||||
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
|
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
|
||||||
window.textsecure.ReplayableError = ReplayableError;
|
window.textsecure.ReplayableError = ReplayableError;
|
||||||
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
||||||
|
window.textsecure.MessageError = MessageError;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -11,6 +11,7 @@ function Message(options) {
|
||||||
this.timestamp = options.timestamp;
|
this.timestamp = options.timestamp;
|
||||||
this.needsSync = options.needsSync;
|
this.needsSync = options.needsSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message.prototype = {
|
Message.prototype = {
|
||||||
constructor: Message,
|
constructor: Message,
|
||||||
toProto: function() {
|
toProto: function() {
|
||||||
|
@ -81,7 +82,8 @@ MessageSender.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
sendMessage: function(message) {
|
sendMessage: function(attrs) {
|
||||||
|
var message = new Message(attrs);
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
message.attachments.map(this.makeAttachmentPointer.bind(this))
|
message.attachments.map(this.makeAttachmentPointer.bind(this))
|
||||||
).then(function(attachmentPointers) {
|
).then(function(attachmentPointers) {
|
||||||
|
@ -101,7 +103,13 @@ MessageSender.prototype = {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}.bind(this));
|
}.bind(this)).catch(function(error) {
|
||||||
|
if (error instanceof Error && error.name === 'HTTPError') {
|
||||||
|
throw new textsecure.MessageError(attrs, error);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
sendMessageProto: function(timestamp, numbers, message, callback) {
|
sendMessageProto: function(timestamp, numbers, message, callback) {
|
||||||
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
var outgoing = new OutgoingMessage(this.server, timestamp, numbers, message, callback);
|
||||||
|
@ -195,15 +203,13 @@ MessageSender.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
sendMessageToNumber: function(number, messageText, attachments, timestamp) {
|
sendMessageToNumber: function(number, messageText, attachments, timestamp) {
|
||||||
var message = new Message({
|
return this.sendMessage({
|
||||||
recipients : [number],
|
recipients : [number],
|
||||||
body : messageText,
|
body : messageText,
|
||||||
timestamp : timestamp,
|
timestamp : timestamp,
|
||||||
attachments : attachments,
|
attachments : attachments,
|
||||||
needsSync : true
|
needsSync : true
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.sendMessage(message);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
closeSession: function(number, timestamp) {
|
closeSession: function(number, timestamp) {
|
||||||
|
@ -234,7 +240,7 @@ MessageSender.prototype = {
|
||||||
return Promise.reject(new Error('No other members in the group'));
|
return Promise.reject(new Error('No other members in the group'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = new Message({
|
return this.sendMessage({
|
||||||
recipients : numbers,
|
recipients : numbers,
|
||||||
body : messageText,
|
body : messageText,
|
||||||
timestamp : timestamp,
|
timestamp : timestamp,
|
||||||
|
@ -245,7 +251,6 @@ MessageSender.prototype = {
|
||||||
type: textsecure.protobuf.GroupContext.Type.DELIVER
|
type: textsecure.protobuf.GroupContext.Type.DELIVER
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return this.sendMessage(message);
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -364,6 +369,7 @@ textsecure.MessageSender = function(url, username, password, attachment_server_u
|
||||||
var sender = new MessageSender(url, username, password, attachment_server_url);
|
var sender = new MessageSender(url, username, password, attachment_server_url);
|
||||||
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);
|
||||||
|
|
||||||
this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender);
|
this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender);
|
||||||
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);
|
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);
|
||||||
|
|
Loading…
Reference in a new issue