Merge branch 'charlesmchen/sendWebSocketFailureBodies'

pull/1/head
Matthew Chen 7 years ago
commit e142aa43e3

@ -125,7 +125,7 @@ public class ProfileFetcherJob: NSObject {
reject(error) reject(error)
} }
}, },
failure: { (_: NSInteger, error: Error) in failure: { (_: NSInteger, _:Data?, error: Error) in
reject(error) reject(error)
}) })
} else { } else {

@ -35,7 +35,12 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
@interface TSAccountManager () @interface TSAccountManager ()
@property (nonatomic, readonly) BOOL isRegistered; @property (nonatomic, readonly) BOOL isRegistered;
// This property is exposed publicly for testing purposes only.
#ifndef DEBUG
@property (nonatomic, nullable) NSString *phoneNumberAwaitingVerification; @property (nonatomic, nullable) NSString *phoneNumberAwaitingVerification;
#endif
@property (nonatomic, nullable) NSString *cachedLocalNumber; @property (nonatomic, nullable) NSString *cachedLocalNumber;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (nonatomic, readonly) YapDatabaseConnection *dbConnection;

@ -985,7 +985,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
deviceMessages:deviceMessages deviceMessages:deviceMessages
success:successHandler]; success:successHandler];
} }
failure:^(NSInteger statusCode, NSError *error) { failure:^(NSInteger statusCode, NSData *_Nullable responseData, NSError *error) {
[self messageSendDidFail:message [self messageSendDidFail:message
recipient:recipient recipient:recipient
thread:thread thread:thread
@ -994,6 +994,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
remainingAttempts:remainingAttempts remainingAttempts:remainingAttempts
statusCode:statusCode statusCode:statusCode
error:error error:error
responseData:responseData
success:successHandler success:successHandler
failure:failureHandler]; failure:failureHandler];
}]; }];
@ -1009,6 +1010,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
failure:^(NSURLSessionDataTask *task, NSError *error) { failure:^(NSURLSessionDataTask *task, NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response; NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
NSInteger statusCode = response.statusCode; NSInteger statusCode = response.statusCode;
NSData *_Nullable responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
[self messageSendDidFail:message [self messageSendDidFail:message
recipient:recipient recipient:recipient
@ -1018,6 +1020,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
remainingAttempts:remainingAttempts remainingAttempts:remainingAttempts
statusCode:statusCode statusCode:statusCode
error:error error:error
responseData:responseData
success:successHandler success:successHandler
failure:failureHandler]; failure:failureHandler];
}]; }];
@ -1067,7 +1070,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
deviceMessages:(NSArray<NSDictionary *> *)deviceMessages deviceMessages:(NSArray<NSDictionary *> *)deviceMessages
remainingAttempts:(int)remainingAttempts remainingAttempts:(int)remainingAttempts
statusCode:(NSInteger)statusCode statusCode:(NSInteger)statusCode
error:(NSError *)error error:(NSError *)responseError
responseData:(nullable NSData *)responseData
success:(void (^)(void))successHandler success:(void (^)(void))successHandler
failure:(RetryableFailureHandler)failureHandler failure:(RetryableFailureHandler)failureHandler
{ {
@ -1075,21 +1079,18 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSAssert(recipient); OWSAssert(recipient);
OWSAssert(thread); OWSAssert(thread);
OWSAssert(deviceMessages); OWSAssert(deviceMessages);
OWSAssert(error); OWSAssert(responseError);
OWSAssert(successHandler); OWSAssert(successHandler);
OWSAssert(failureHandler); OWSAssert(failureHandler);
DDLogInfo(@"%@ sending to recipient: %@, failed with error.", self.logTag, recipient.uniqueId); DDLogInfo(@"%@ sending to recipient: %@, failed with error.", self.logTag, recipient.uniqueId);
[DDLog flushLog];
NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
void (^retrySend)(void) = ^void() { void (^retrySend)(void) = ^void() {
if (remainingAttempts <= 0) { if (remainingAttempts <= 0) {
// Since we've already repeatedly failed to send to the messaging API, // Since we've already repeatedly failed to send to the messaging API,
// it's unlikely that repeating the whole process will succeed. // it's unlikely that repeating the whole process will succeed.
[error setIsRetryable:NO]; [responseError setIsRetryable:NO];
return failureHandler(error); return failureHandler(responseError);
} }
dispatch_async([OWSDispatch sendingQueue], ^{ dispatch_async([OWSDispatch sendingQueue], ^{
@ -1130,32 +1131,39 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} }
case 409: { case 409: {
// Mismatched devices // Mismatched devices
DDLogWarn(@"%@ Mismatch Devices for recipient: %@", self.logTag, recipient.uniqueId); DDLogWarn(@"%@ Mismatched devices for recipient: %@", self.logTag, recipient.uniqueId);
NSError *error; NSError *_Nullable error = nil;
NSDictionary *serializedResponse = NSDictionary *_Nullable responseJson = nil;
[NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error]; if (responseData) {
if (error) { responseJson = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
}
if (error || !responseJson) {
OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotParseMismatchedDevicesJson]); OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotParseMismatchedDevicesJson]);
[error setIsRetryable:YES]; [error setIsRetryable:YES];
return failureHandler(error); return failureHandler(error);
} }
[self handleMismatchedDevices:serializedResponse recipient:recipient completion:retrySend]; [self handleMismatchedDevicesWithResponseJson:responseJson recipient:recipient completion:retrySend];
break; break;
} }
case 410: { case 410: {
// Stale devices // Stale devices
DDLogWarn(@"%@ Stale devices for recipient: %@", self.logTag, recipient.uniqueId); DDLogWarn(@"%@ Stale devices for recipient: %@", self.logTag, recipient.uniqueId);
if (!responseData) { NSError *_Nullable error = nil;
NSDictionary *_Nullable responseJson = nil;
if (responseData) {
responseJson = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
}
if (error || !responseJson) {
DDLogWarn(@"Stale devices but server didn't specify devices in response."); DDLogWarn(@"Stale devices but server didn't specify devices in response.");
NSError *error = OWSErrorMakeUnableToProcessServerResponseError(); NSError *error = OWSErrorMakeUnableToProcessServerResponseError();
[error setIsRetryable:YES]; [error setIsRetryable:YES];
return failureHandler(error); return failureHandler(error);
} }
[self handleStaleDevicesWithResponse:responseData recipientId:recipient.uniqueId completion:retrySend]; [self handleStaleDevicesWithResponseJson:responseJson recipientId:recipient.uniqueId completion:retrySend];
break; break;
} }
default: default:
@ -1164,12 +1172,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} }
} }
- (void)handleMismatchedDevices:(NSDictionary *)dictionary - (void)handleMismatchedDevicesWithResponseJson:(NSDictionary *)responseJson
recipient:(SignalRecipient *)recipient recipient:(SignalRecipient *)recipient
completion:(void (^)(void))completionHandler completion:(void (^)(void))completionHandler
{ {
NSArray *extraDevices = [dictionary objectForKey:@"extraDevices"]; OWSAssert(responseJson);
NSArray *missingDevices = [dictionary objectForKey:@"missingDevices"]; OWSAssert(recipient);
OWSAssert(completionHandler);
NSArray *extraDevices = responseJson[@"extraDevices"];
NSArray *missingDevices = responseJson[@"missingDevices"];
if (missingDevices.count > 0) { if (missingDevices.count > 0) {
NSString *localNumber = [TSAccountManager localNumber]; NSString *localNumber = [TSAccountManager localNumber];
@ -1442,13 +1454,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} }
// Called when the server indicates that the devices no longer exist - e.g. when the remote recipient has reinstalled. // Called when the server indicates that the devices no longer exist - e.g. when the remote recipient has reinstalled.
- (void)handleStaleDevicesWithResponse:(NSData *)responseData - (void)handleStaleDevicesWithResponseJson:(NSDictionary *)responseJson
recipientId:(NSString *)identifier recipientId:(NSString *)identifier
completion:(void (^)(void))completionHandler completion:(void (^)(void))completionHandler
{ {
dispatch_async([OWSDispatch sendingQueue], ^{ dispatch_async([OWSDispatch sendingQueue], ^{
NSDictionary *serialization = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil]; NSArray *devices = responseJson[@"staleDevices"];
NSArray *devices = serialization[@"staleDevices"];
if (!([devices count] > 0)) { if (!([devices count] > 0)) {
return; return;

@ -18,7 +18,7 @@ typedef NS_ENUM(NSUInteger, SocketManagerState) {
typedef void (^TSSocketMessageSuccess)(id _Nullable responseObject); typedef void (^TSSocketMessageSuccess)(id _Nullable responseObject);
// statusCode is zero by default, if request never made or failed. // statusCode is zero by default, if request never made or failed.
typedef void (^TSSocketMessageFailure)(NSInteger statusCode, NSError *error); typedef void (^TSSocketMessageFailure)(NSInteger statusCode, NSData *_Nullable responseData, NSError *error);
@class TSRequest; @class TSRequest;

@ -102,10 +102,10 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageRequestFailed, NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageRequestFailed,
NSLocalizedString(@"ERROR_DESCRIPTION_REQUEST_FAILED", @"Error indicating that a socket request failed.")); NSLocalizedString(@"ERROR_DESCRIPTION_REQUEST_FAILED", @"Error indicating that a socket request failed."));
[self didFailWithStatusCode:0 error:error]; [self didFailWithStatusCode:0 responseData:nil error:error];
} }
- (void)didFailWithStatusCode:(NSInteger)statusCode error:(NSError *)error - (void)didFailWithStatusCode:(NSInteger)statusCode responseData:(nullable NSData *)responseData error:(NSError *)error
{ {
OWSAssert(error); OWSAssert(error);
@ -117,12 +117,14 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
self.hasCompleted = YES; self.hasCompleted = YES;
} }
DDLogError(@"%@ %s didFailWithStatusCode: %zd, %@", self.logTag, __PRETTY_FUNCTION__, statusCode, error);
OWSAssert(self.success); OWSAssert(self.success);
OWSAssert(self.failure); OWSAssert(self.failure);
TSSocketMessageFailure failure = self.failure; TSSocketMessageFailure failure = self.failure;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
failure(statusCode, error); failure(statusCode, responseData, error);
}); });
self.success = nil; self.success = nil;
@ -568,18 +570,18 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
if (message.hasMessage) { if (message.hasMessage) {
responseMessage = message.message; responseMessage = message.message;
} }
NSData *_Nullable responseBody; NSData *_Nullable responseData;
if (message.hasBody) { if (message.hasBody) {
responseBody = message.body; responseData = message.body;
} }
NSArray<NSString *> *_Nullable responseHeaders = message.headers; NSArray<NSString *> *_Nullable responseHeaders = message.headers;
BOOL hasValidResponse = YES; BOOL hasValidResponse = YES;
id responseObject = responseBody; id responseObject = responseData;
if (responseBody) { if (responseData) {
NSError *error; NSError *error;
id _Nullable responseJson = id _Nullable responseJson =
[NSJSONSerialization JSONObjectWithData:responseBody options:(NSJSONReadingOptions)0 error:&error]; [NSJSONSerialization JSONObjectWithData:responseData options:(NSJSONReadingOptions)0 error:&error];
if (!responseJson || error) { if (!responseJson || error) {
OWSProdLogAndFail(@"%@ could not parse WebSocket response JSON: %@.", self.logTag, error); OWSProdLogAndFail(@"%@ could not parse WebSocket response JSON: %@.", self.logTag, error);
hasValidResponse = NO; hasValidResponse = NO;
@ -606,7 +608,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageResponseFailed, NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageResponseFailed,
NSLocalizedString( NSLocalizedString(
@"ERROR_DESCRIPTION_RESPONSE_FAILED", @"Error indicating that a socket response failed.")); @"ERROR_DESCRIPTION_RESPONSE_FAILED", @"Error indicating that a socket response failed."));
[socketMessage didFailWithStatusCode:(NSInteger)responseStatus error:error]; [socketMessage didFailWithStatusCode:(NSInteger)responseStatus responseData:responseData error:error];
} }
} }
@ -615,7 +617,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
(unsigned long long)requestId, (unsigned long long)requestId,
(NSInteger)responseStatus, (NSInteger)responseStatus,
responseMessage, responseMessage,
responseBody.length, responseData.length,
responseHeaders, responseHeaders,
socketMessage != nil, socketMessage != nil,
responseObject); responseObject);

Loading…
Cancel
Save