Instrument errors in message manager.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent bf82d2e2e0
commit e168db79aa

@ -42,6 +42,23 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
#define kOWSProdAssertParameterEnvelopeIsLegacy @"envelope_is_legacy"
#define kOWSProdAssertParameterEnvelopeDescription @"envelope_description"
#define kOWSProdAssertParameterEnvelopeEncryptedLength @"encrypted_length"
#define AnalyticsParametersFromEnvelope(__envelope) \
^{ \
NSData *__encryptedData = __envelope.hasContent ? __envelope.content : __envelope.legacyMessage; \
return (@{ \
kOWSProdAssertParameterEnvelopeIsLegacy : @(__envelope.hasLegacyMessage), \
kOWSProdAssertParameterEnvelopeDescription : [self descriptionForEnvelopeType:__envelope], \
kOWSProdAssertParameterEnvelopeEncryptedLength : @(__encryptedData.length), \
}); \
}
#define OWSProdErrorWEnvelope(__analyticsEventName, __envelope) \
OWSProdErrorWParams(__analyticsEventName, AnalyticsParametersFromEnvelope(__envelope))
@interface TSMessagesManager () @interface TSMessagesManager ()
@property (nonatomic, readonly) id<OWSCallMessageHandler> callMessageHandler; @property (nonatomic, readonly) id<OWSCallMessageHandler> callMessageHandler;
@ -135,39 +152,37 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Debugging #pragma mark - Debugging
- (NSString *)descriptionForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope - (NSString *)descriptionForEnvelopeType:(OWSSignalServiceProtosEnvelope *)envelope
{ {
OWSAssert(envelope != nil); OWSAssert(envelope != nil);
NSString *envelopeType;
switch (envelope.type) { switch (envelope.type) {
case OWSSignalServiceProtosEnvelopeTypeReceipt: case OWSSignalServiceProtosEnvelopeTypeReceipt:
envelopeType = @"DeliveryReceipt"; return @"DeliveryReceipt";
break;
case OWSSignalServiceProtosEnvelopeTypeUnknown: case OWSSignalServiceProtosEnvelopeTypeUnknown:
// Shouldn't happen // Shouldn't happen
OWSAssert(NO); OWSProdFail(@"message_manager_error_envelope_type_unknown");
envelopeType = @"Unknown"; return @"Unknown";
break;
case OWSSignalServiceProtosEnvelopeTypeCiphertext: case OWSSignalServiceProtosEnvelopeTypeCiphertext:
envelopeType = @"SignalEncryptedMessage"; return @"SignalEncryptedMessage";
break;
case OWSSignalServiceProtosEnvelopeTypeKeyExchange: case OWSSignalServiceProtosEnvelopeTypeKeyExchange:
// Unsupported // Unsupported
OWSAssert(NO); OWSProdFail(@"message_manager_error_envelope_type_key_exchange");
envelopeType = @"KeyExchange"; return @"KeyExchange";
break;
case OWSSignalServiceProtosEnvelopeTypePrekeyBundle: case OWSSignalServiceProtosEnvelopeTypePrekeyBundle:
envelopeType = @"PreKeyEncryptedMessage"; return @"PreKeyEncryptedMessage";
break;
default: default:
// Shouldn't happen // Shouldn't happen
OWSAssert(NO); OWSProdFail(@"message_manager_error_envelope_type_other");
envelopeType = @"Other"; return @"Other";
break;
} }
}
- (NSString *)descriptionForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
{
OWSAssert(envelope != nil);
return [NSString stringWithFormat:@"<Envelope type: %@, source: %@.%d, timestamp: %llu content.length: %lu />", return [NSString stringWithFormat:@"<Envelope type: %@, source: %@.%d, timestamp: %llu content.length: %lu />",
envelopeType, [self descriptionForEnvelopeType:envelope],
envelope.source, envelope.source,
(unsigned int)envelope.sourceDevice, (unsigned int)envelope.sourceDevice,
envelope.timestamp, envelope.timestamp,
@ -189,7 +204,9 @@ NS_ASSUME_NONNULL_BEGIN
} else if (content.hasNullMessage) { } else if (content.hasNullMessage) {
return [NSString stringWithFormat:@"<NullMessage: %@ />", content.nullMessage]; return [NSString stringWithFormat:@"<NullMessage: %@ />", content.nullMessage];
} else { } else {
OWSAssert(NO); // Don't fire an analytics event; if we ever add a new content type, we'd generate a ton of
// analytics traffic.
OWSFail(@"Unknown content type.");
return @"UnknownContent"; return @"UnknownContent";
} }
} }
@ -233,9 +250,11 @@ NS_ASSUME_NONNULL_BEGIN
[description appendString:@"ContactRequest"]; [description appendString:@"ContactRequest"];
} else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeGroups) { } else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeGroups) {
[description appendString:@"GroupRequest"]; [description appendString:@"GroupRequest"];
} else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeBlocked) {
[description appendString:@"BlockedRequest"];
} else { } else {
// Shouldn't happen // Shouldn't happen
OWSAssert(NO); OWSFail(@"Unknown sync message request type");
[description appendString:@"UnknownRequest"]; [description appendString:@"UnknownRequest"];
} }
} else if (syncMessage.hasBlocked) { } else if (syncMessage.hasBlocked) {
@ -248,7 +267,7 @@ NS_ASSUME_NONNULL_BEGIN
[description appendString:verifiedString]; [description appendString:verifiedString];
} else { } else {
// Shouldn't happen // Shouldn't happen
OWSAssert(NO); OWSFail(@"Unknown sync message type");
[description appendString:@"Unknown"]; [description appendString:@"Unknown"];
} }
@ -295,6 +314,7 @@ NS_ASSUME_NONNULL_BEGIN
envelope.source, envelope.source,
(unsigned int)envelope.sourceDevice, (unsigned int)envelope.sourceDevice,
error); error);
OWSProdError(@"message_manager_error_could_not_handle_secure_message");
} }
completion(); completion();
}]; }];
@ -312,6 +332,7 @@ NS_ASSUME_NONNULL_BEGIN
envelope.source, envelope.source,
(unsigned int)envelope.sourceDevice, (unsigned int)envelope.sourceDevice,
error); error);
OWSProdError(@"message_manager_error_could_not_handle_prekey_bundle");
} }
completion(); completion();
}]; }];
@ -336,6 +357,7 @@ NS_ASSUME_NONNULL_BEGIN
} }
} @catch (NSException *exception) { } @catch (NSException *exception) {
DDLogError(@"Received an incorrectly formatted protocol buffer: %@", exception.debugDescription); DDLogError(@"Received an incorrectly formatted protocol buffer: %@", exception.debugDescription);
OWSProdFailWNSException(@"message_manager_error_invalid_protocol_message", exception);
} }
completion(); completion();
@ -367,15 +389,18 @@ NS_ASSUME_NONNULL_BEGIN
NSData *encryptedData NSData *encryptedData
= messageEnvelope.hasContent ? messageEnvelope.content : messageEnvelope.legacyMessage; = messageEnvelope.hasContent ? messageEnvelope.content : messageEnvelope.legacyMessage;
if (!encryptedData) { if (!encryptedData) {
DDLogError(@"Skipping message envelope which had no encrypted data."); OWSProdFail(@"message_manager_error_message_envelope_has_no_content");
completion(nil); completion(nil);
return; return;
} }
NSUInteger kMaxEncryptedDataLength = 250 * 1024; NSUInteger kMaxEncryptedDataLength = 250 * 1024;
if (encryptedData.length > kMaxEncryptedDataLength) { if (encryptedData.length > kMaxEncryptedDataLength) {
DDLogError(@"Skipping message envelope with oversize encrypted data: %lu.", OWSProdErrorWParams(@"message_manager_error_oversize_message", ^{
(unsigned long)encryptedData.length); return (@{
@"message_size" : @(encryptedData.length),
});
});
completion(nil); completion(nil);
return; return;
} }
@ -424,7 +449,7 @@ NS_ASSUME_NONNULL_BEGIN
// DEPRECATED - Remove after all clients have been upgraded. // DEPRECATED - Remove after all clients have been upgraded.
NSData *encryptedData = preKeyEnvelope.hasContent ? preKeyEnvelope.content : preKeyEnvelope.legacyMessage; NSData *encryptedData = preKeyEnvelope.hasContent ? preKeyEnvelope.content : preKeyEnvelope.legacyMessage;
if (!encryptedData) { if (!encryptedData) {
DDLogError(@"Skipping message envelope which had no encrypted data"); OWSProdFail(@"message_manager_error_prekey_bundle_envelope_has_no_content");
completion(nil); completion(nil);
return; return;
} }
@ -816,7 +841,7 @@ NS_ASSUME_NONNULL_BEGIN
NSData *groupId = dataMessage.hasGroup ? dataMessage.group.id : nil; NSData *groupId = dataMessage.hasGroup ? dataMessage.group.id : nil;
if (!groupId) { if (!groupId) {
OWSAssert(groupId); OWSFail(@"Group info request is missing group id.");
return; return;
} }
@ -1009,24 +1034,30 @@ NS_ASSUME_NONNULL_BEGIN
__block TSErrorMessage *errorMessage; __block TSErrorMessage *errorMessage;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if ([exception.name isEqualToString:NoSessionException]) { if ([exception.name isEqualToString:NoSessionException]) {
OWSProdErrorWEnvelope(@"message_manager_error_no_session", envelope);
errorMessage = [TSErrorMessage missingSessionWithEnvelope:envelope withTransaction:transaction]; errorMessage = [TSErrorMessage missingSessionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:InvalidKeyException]) { } else if ([exception.name isEqualToString:InvalidKeyException]) {
OWSProdErrorWEnvelope(@"message_manager_error_invalid_key", envelope);
errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction]; errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:InvalidKeyIdException]) { } else if ([exception.name isEqualToString:InvalidKeyIdException]) {
OWSProdErrorWEnvelope(@"message_manager_error_invalid_key_id", envelope);
errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction]; errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:DuplicateMessageException]) { } else if ([exception.name isEqualToString:DuplicateMessageException]) {
// Duplicate messages are dismissed // Duplicate messages are dismissed
return; return;
} else if ([exception.name isEqualToString:InvalidVersionException]) { } else if ([exception.name isEqualToString:InvalidVersionException]) {
OWSProdErrorWEnvelope(@"message_manager_error_invalid_message_version", envelope);
errorMessage = [TSErrorMessage invalidVersionWithEnvelope:envelope withTransaction:transaction]; errorMessage = [TSErrorMessage invalidVersionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { } else if ([exception.name isEqualToString:UntrustedIdentityKeyException]) {
// Should no longer get here, since we now record the new identity for incoming messages. // Should no longer get here, since we now record the new identity for incoming messages.
OWSProdErrorWEnvelope(@"message_manager_error_untrusted_identity_key_exception", envelope);
OWSFail(@"%@ Failed to trust identity on incoming message from: %@.%d", OWSFail(@"%@ Failed to trust identity on incoming message from: %@.%d",
self.tag, self.tag,
envelope.source, envelope.source,
envelope.sourceDevice); envelope.sourceDevice);
return; return;
} else { } else {
OWSProdErrorWEnvelope(@"message_manager_error_corrupt_message", envelope);
errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction]; errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction];
} }

@ -56,6 +56,9 @@ typedef NSDictionary<NSString *, id> *_Nonnull (^OWSProdAssertParametersBlock)()
#define kOWSProdAssertParameterNSErrorDomain @"nserror_domain" #define kOWSProdAssertParameterNSErrorDomain @"nserror_domain"
#define kOWSProdAssertParameterNSErrorCode @"nserror_code" #define kOWSProdAssertParameterNSErrorCode @"nserror_code"
#define kOWSProdAssertParameterNSErrorDescription @"nserror_description" #define kOWSProdAssertParameterNSErrorDescription @"nserror_description"
#define kOWSProdAssertParameterNSExceptionName @"nsexception_name"
#define kOWSProdAssertParameterNSExceptionReason @"nsexception_reason"
#define kOWSProdAssertParameterNSExceptionClassName @"nsexception_classname"
// These methods should be used to assert errors for which we want to fire analytics events. // These methods should be used to assert errors for which we want to fire analytics events.
// //
@ -121,9 +124,21 @@ typedef NSDictionary<NSString *, id> *_Nonnull (^OWSProdAssertParametersBlock)()
}); \ }); \
} }
#define AnalyticsParametersFromNSException(__exception) \
^{ \
return (@{ \
kOWSProdAssertParameterNSExceptionName : __exception.name, \
kOWSProdAssertParameterNSExceptionReason : __exception.reason, \
kOWSProdAssertParameterNSExceptionClassName : NSStringFromClass([__exception class]), \
}); \
}
#define OWSProdFailWNSError(__analyticsEventName, __nserror) \ #define OWSProdFailWNSError(__analyticsEventName, __nserror) \
OWSProdFailWParams(__analyticsEventName, AnalyticsParametersFromNSError(__nserror)) OWSProdFailWParams(__analyticsEventName, AnalyticsParametersFromNSError(__nserror))
#define OWSProdFailWNSException(__analyticsEventName, __exception) \
OWSProdFailWParams(__analyticsEventName, AnalyticsParametersFromNSException(__exception))
#define OWSProdEventWParams(__severityLevel, __analyticsEventName, __parametersBlock) \ #define OWSProdEventWParams(__severityLevel, __analyticsEventName, __parametersBlock) \
{ \ { \
NSDictionary<NSString *, id> *__eventParameters \ NSDictionary<NSString *, id> *__eventParameters \
@ -150,4 +165,7 @@ typedef NSDictionary<NSString *, id> *_Nonnull (^OWSProdAssertParametersBlock)()
#define OWSProdErrorWNSError(__analyticsEventName, __nserror) \ #define OWSProdErrorWNSError(__analyticsEventName, __nserror) \
OWSProdErrorWParams(__analyticsEventName, AnalyticsParametersFromNSError(__nserror)) OWSProdErrorWParams(__analyticsEventName, AnalyticsParametersFromNSError(__nserror))
#define OWSProdErrorWNSException(__analyticsEventName, __exception) \
OWSProdErrorWParams(__analyticsEventName, AnalyticsParametersFromNSException(__exception))
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

Loading…
Cancel
Save