session-ios/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m

541 lines
24 KiB
Mathematica
Raw Normal View History

//
// TSMessagesManager+sendMessages.m
// TextSecureKit
//
// Created by Frederic Jacobs on 17/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSMessagesManager+sendMessages.h"
2014-11-27 03:10:00 +01:00
#import <AxolotlKit/AxolotlExceptions.h>
#import <AxolotlKit/SessionCipher.h>
2014-11-27 03:10:00 +01:00
#import <AxolotlKit/SessionBuilder.h>
2014-11-25 16:38:33 +01:00
#import <Mantle/Mantle.h>
#import "Environment.h"
#import "ContactsManager+updater.h"
#import "PreferencesUtil.h"
2015-02-26 19:15:46 +01:00
#import "NSData+messagePadding.h"
#import "TSStorageManager.h"
2014-11-27 03:10:00 +01:00
#import "PreKeyBundle+jsonDict.h"
#import "SignalKeyingStorage.h"
2014-11-27 03:10:00 +01:00
#import "TSNetworkManager.h"
#import "TSServerMessage.h"
2014-12-11 00:05:41 +01:00
#import "TSInfoMessage.h"
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
#import "CollapsingFutures.h"
#define RETRY_ATTEMPTS 3
#define InvalidDeviceException @"InvalidDeviceException"
2014-11-27 03:10:00 +01:00
@interface TSMessagesManager ()
dispatch_queue_t sendingQueue(void);
@end
typedef void (^messagesQueue)(NSArray *messages);
@implementation TSMessagesManager (sendMessages)
2014-11-27 03:10:00 +01:00
dispatch_queue_t sendingQueue() {
static dispatch_once_t queueCreationGuard;
static dispatch_queue_t queue;
dispatch_once(&queueCreationGuard, ^{
queue = dispatch_queue_create("org.whispersystems.signal.sendQueue", NULL);
});
return queue;
}
- (void)getRecipients:(NSArray<NSString*> *)identifiers
success:(void (^)(NSArray<SignalRecipient*>*))success
failure:(void (^)(NSError *error))failure
{
NSMutableArray<SignalRecipient*> *recipients = [NSMutableArray array];
for(NSString *recipientId in identifiers) {
__block SignalRecipient *recipient;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
recipient = [SignalRecipient recipientWithTextSecureIdentifier:recipientId withTransaction:transaction];
}];
if (!recipient){
[[self contactManager] synchronousLookup:recipientId success:^(SignalRecipient * newRecipient) {
[recipients addObject:newRecipient];
} failure:^(NSError *error) {
failure(error);
return;
}];
}
}
success(recipients);
return;
}
- (ContactsManager*)contactManager {
return [Environment getCurrent].contactsManager;
}
- (void)sendMessage:(TSOutgoingMessage*)message
inThread:(TSThread*)thread
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
success:(successSendingCompletionBlock)successCompletionBlock
failure:(failedSendingCompletionBlock)failedCompletionBlock
{
[Environment.preferences setHasSentAMessage:YES];
2014-11-27 03:10:00 +01:00
dispatch_async(sendingQueue(), ^{
if ([thread isKindOfClass:[TSGroupThread class]]) {
TSGroupThread* groupThread = (TSGroupThread*)thread;
[self saveGroupMessage:message inThread:thread];
[self getRecipients:groupThread.groupModel.groupMemberIds success:^(NSArray<SignalRecipient *> *recipients) {
[self groupSend:recipients Message:message inThread:thread success:successCompletionBlock failure:failedCompletionBlock];
} failure:^(NSError *error) {
DDLogError(@"Failure to retreive group recipient.");
[self saveMessage:message withState:TSOutgoingMessageStateUnsent];
}];
} else if([thread isKindOfClass:[TSContactThread class]]){
2014-11-27 03:10:00 +01:00
TSContactThread *contactThread = (TSContactThread*)thread;
[self saveMessage:message withState:TSOutgoingMessageStateAttemptingOut];
2014-11-27 03:10:00 +01:00
if(![contactThread.contactIdentifier isEqualToString:[SignalKeyingStorage.localNumber toE164]]) {
__block SignalRecipient *recipient;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
//recipient = [SignalRecipient recipientWithTextSecureIdentifier:contactThread.contactIdentifier
// withTransaction:transaction];
}];
if (!recipient) {
[[self contactManager] synchronousLookup:contactThread.contactIdentifier
success:^(SignalRecipient *recip) {
recipient = recip;
} failure:^(NSError *error) {
if (error.code == NOTFOUND_ERROR) {
[self unregisteredRecipient:recipient
message:message
inThread:thread];
return;
} else{
[self saveMessage:message withState:TSOutgoingMessageStateUnsent];
return;
}
}];
}
if (recipient) {
[self sendMessage:message
toRecipient:recipient
inThread:thread
withAttemps:RETRY_ATTEMPTS
success:successCompletionBlock
failure:failedCompletionBlock];
}
} else {
// Special situation: if we are sending to ourselves in a single thread, we treat this as an incoming message
[self handleMessageSent:message];
[[TSMessagesManager sharedManager] handleSendToMyself:message];
}
2014-11-27 03:10:00 +01:00
}
});
}
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
/// For group sends, we're using chained futures to make the code more readable.
- (TOCFuture*)sendMessageFuture:(TSOutgoingMessage*)message
recipient:(SignalRecipient*)recipient
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
inThread:(TSThread*)thread {
TOCFutureSource *futureSource = [[TOCFutureSource alloc] init];
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
[self sendMessage:message toRecipient:recipient inThread:thread withAttemps:RETRY_ATTEMPTS success:^{
[futureSource trySetResult:@1];
} failure:^{
[futureSource trySetFailure:@0];
}];
return futureSource.future;
}
- (void)groupSend:(NSArray<SignalRecipient*>*)recipients
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
Message:(TSOutgoingMessage*)message
inThread:(TSThread*)thread
success:(successSendingCompletionBlock)successBlock
failure:(failedSendingCompletionBlock)failureBlock {
NSMutableArray<TOCFuture*> *futures = [NSMutableArray array];
for(SignalRecipient *rec in recipients){
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
// we don't need to send the message to ourselves, but otherwise we send
if( ![[rec uniqueId] isEqualToString:[SignalKeyingStorage.localNumber toE164]]){
[futures addObject:[self sendMessageFuture:message recipient:rec inThread:thread]];
}
}
TOCFuture *completionFuture = futures.toc_thenAll;
[completionFuture thenDo:^(id value) {
BLOCK_SAFE_RUN(successBlock);
}];
[completionFuture catchDo:^(id failure) {
BLOCK_SAFE_RUN(failureBlock);
}];
}
- (void)unregisteredRecipient:(SignalRecipient*)recipient
message:(TSOutgoingMessage*)message
inThread:(TSThread*)thread{
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[recipient removeWithTransaction:transaction];
[[TSInfoMessage userNotRegisteredMessageInThread:thread transaction:transaction] saveWithTransaction:transaction];
}];
[self saveMessage:message withState:TSOutgoingMessageStateUnsent];
}
- (void)sendMessage:(TSOutgoingMessage*)message
toRecipient:(SignalRecipient*)recipient
inThread:(TSThread*)thread
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
withAttemps:(int)remainingAttempts
success:(successSendingCompletionBlock)successBlock
failure:(failedSendingCompletionBlock)failureBlock
{
if (remainingAttempts > 0) {
remainingAttempts -= 1;
[self outgoingMessages:message toRecipient:recipient inThread:thread completion:^(NSArray *messages) {
TSSubmitMessageRequest *request = [[TSSubmitMessageRequest alloc] initWithRecipient:recipient.uniqueId
messages:messages
relay:recipient.relay
timeStamp:message.timestamp];
2014-11-27 03:10:00 +01:00
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[recipient saveWithTransaction:transaction];
}];
[self handleMessageSent:message];
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
BLOCK_SAFE_RUN(successBlock);
2014-11-27 03:10:00 +01:00
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
long statuscode = response.statusCode;
NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
2014-11-27 03:10:00 +01:00
switch (statuscode) {
case 404:{
[self unregisteredRecipient:recipient
message:message
inThread:thread];
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
BLOCK_SAFE_RUN(failureBlock);
2014-11-27 03:10:00 +01:00
break;
}
2015-06-07 21:49:35 +02:00
case 409:{
2014-11-27 03:10:00 +01:00
// Mismatched devices
2015-06-07 21:49:35 +02:00
DDLogWarn(@"Mismatch Devices.");
NSError *e;
NSDictionary *serializedResponse = [NSJSONSerialization JSONObjectWithData:responseData
options:0
error:&e];
if (e) {
DDLogError(@"Failed to serialize response of mismatched devices: %@", e.description);
} else {
[self handleMismatchedDevices:serializedResponse
recipient:recipient];
}
dispatch_async(sendingQueue(), ^{
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
[self sendMessage:message
toRecipient:recipient
inThread:thread
withAttemps:remainingAttempts
success:successBlock
failure:failureBlock];
2015-06-07 21:49:35 +02:00
});
2014-11-27 03:10:00 +01:00
break;
2015-06-07 21:49:35 +02:00
}
case 410:{
2014-11-27 03:10:00 +01:00
// staledevices
DDLogWarn(@"Stale devices");
if (!responseData) {
DDLogWarn(@"Stale devices but server didn't specify devices in response.");
return;
}
[self handleStaleDevicesWithResponse:responseData recipientId:recipient.uniqueId];
dispatch_async(sendingQueue(), ^{
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
[self sendMessage:message
toRecipient:recipient
inThread:thread
withAttemps:remainingAttempts
success:successBlock
failure:failureBlock];
});
2014-11-27 03:10:00 +01:00
break;
}
2014-11-27 03:10:00 +01:00
default:
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
[self sendMessage:message
toRecipient:recipient
inThread:thread
withAttemps:remainingAttempts
success:successBlock
failure:failureBlock];
2014-11-27 03:10:00 +01:00
break;
}
}];
}];
} else{
[self saveMessage:message withState:TSOutgoingMessageStateUnsent];
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
BLOCK_SAFE_RUN(failureBlock);
}
}
- (void)handleMismatchedDevices:(NSDictionary*)dictionary recipient:(SignalRecipient*)recipient {
2015-06-07 21:49:35 +02:00
NSArray *extraDevices = [dictionary objectForKey:@"extraDevices"];
NSArray *missingDevices = [dictionary objectForKey:@"missingDevices"];
if (extraDevices && [extraDevices count] > 0) {
for (NSNumber *extraDeviceId in extraDevices) {
[[TSStorageManager sharedManager] deleteSessionForContact:recipient.uniqueId deviceId:[extraDeviceId intValue]];
}
[recipient removeDevices:[NSSet setWithArray:extraDevices]];
}
if (missingDevices && [missingDevices count] > 0) {
[recipient addDevices:[NSSet setWithArray:missingDevices]];
}
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[recipient saveWithTransaction:transaction];
}];
}
- (void)handleMessageSent:(TSOutgoingMessage*)message {
[self saveMessage:message withState:TSOutgoingMessageStateSent];
}
- (void)outgoingMessages:(TSOutgoingMessage*)message toRecipient:(SignalRecipient*)recipient inThread:(TSThread*)thread completion:(messagesQueue)sendMessages{
NSMutableArray *messagesArray = [NSMutableArray arrayWithCapacity:recipient.devices.count];
TSStorageManager *storage = [TSStorageManager sharedManager];
NSData *plainText = [self plainTextForMessage:message inThread:thread];
2014-11-27 03:10:00 +01:00
for (NSNumber *deviceNumber in recipient.devices) {
2014-11-27 03:10:00 +01:00
@try {
NSDictionary *messageDict = [self encryptedMessageWithPlaintext:plainText toRecipient:recipient.uniqueId deviceId:deviceNumber keyingStorage:storage];
if (messageDict) {
[messagesArray addObject:messageDict];
} else{
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Failed to encrypt message" userInfo:nil];
}
}
2014-11-27 03:10:00 +01:00
@catch (NSException *exception) {
if ([exception.name isEqualToString:InvalidDeviceException]){
[recipient removeDevices:[NSSet setWithObject:deviceNumber]];
} else {
[self processException:exception outgoingMessage:message inThread:thread];
return;
}
}
}
2014-11-27 03:10:00 +01:00
sendMessages(messagesArray);
}
- (NSDictionary*)encryptedMessageWithPlaintext:(NSData*)plainText toRecipient:(NSString*)identifier deviceId:(NSNumber*)deviceNumber keyingStorage:(TSStorageManager*)storage{
2014-11-27 03:10:00 +01:00
if (![storage containsSession:identifier deviceId:[deviceNumber intValue]]) {
__block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
2014-11-27 03:10:00 +01:00
__block PreKeyBundle *bundle;
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:[[TSRecipientPrekeyRequest alloc] initWithRecipient:identifier deviceId:[deviceNumber stringValue]] success:^(NSURLSessionDataTask *task, id responseObject) {
bundle = [PreKeyBundle preKeyBundleFromDictionary:responseObject forDeviceNumber:deviceNumber];
dispatch_semaphore_signal(sema);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"Server replied on PreKeyBundle request with error: %@", error);
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
if (response.statusCode == 404) {
@throw [NSException exceptionWithName:InvalidDeviceException reason:@"Device not registered" userInfo:nil];
}
2014-11-27 03:10:00 +01:00
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
if (!bundle) {
@throw [NSException exceptionWithName:InvalidVersionException reason:@"Can't get a prekey bundle from the server with required information" userInfo:nil];
} else{
SessionBuilder *builder = [[SessionBuilder alloc] initWithSessionStore:storage
preKeyStore:storage
signedPreKeyStore:storage
identityKeyStore:storage
recipientId:identifier
deviceId:[deviceNumber intValue]];
@try {
[builder processPrekeyBundle:bundle];
}
@catch (NSException *exception) {
if ([exception.name isEqualToString:UntrustedIdentityKeyException]) {
@throw [NSException exceptionWithName:UntrustedIdentityKeyException reason:nil userInfo:@{TSInvalidPreKeyBundleKey:bundle, TSInvalidRecipientKey:identifier}];
}
@throw exception;
}
2014-11-27 03:10:00 +01:00
}
}
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storage
preKeyStore:storage
signedPreKeyStore:storage
identityKeyStore:storage
recipientId:identifier
deviceId:[deviceNumber intValue]];
2015-02-26 19:15:46 +01:00
id<CipherMessage> encryptedMessage = [cipher encryptMessage:[plainText paddedMessageBody]];
2014-11-27 03:10:00 +01:00
NSData *serializedMessage = encryptedMessage.serialized;
TSWhisperMessageType messageType = [self messageTypeForCipherMessage:encryptedMessage];
TSServerMessage *serverMessage = [[TSServerMessage alloc] initWithType:messageType
destination:identifier
device:[deviceNumber intValue]
body:serializedMessage
registrationId:cipher.remoteRegistrationId];
2014-11-27 03:10:00 +01:00
2015-04-25 18:18:29 +02:00
NSError *error;
NSDictionary *jsonDict = [MTLJSONAdapter JSONDictionaryFromModel:serverMessage error:&error];
2014-11-27 03:10:00 +01:00
2015-04-25 18:18:29 +02:00
if (error) {
DDLogError(@"Error while making JSON dictionary of message: %@", error.debugDescription);
return nil;
}
return jsonDict;
}
- (TSWhisperMessageType)messageTypeForCipherMessage:(id<CipherMessage>)cipherMessage{
if ([cipherMessage isKindOfClass:[PreKeyWhisperMessage class]]) {
return TSPreKeyWhisperMessageType;
} else if ([cipherMessage isKindOfClass:[WhisperMessage class]]){
return TSEncryptedWhisperMessageType;
}
return TSUnknownMessageType;
}
- (void)saveMessage:(TSOutgoingMessage*)message withState:(TSOutgoingMessageState)state{
if(message.groupMetaMessage == TSGroupMessageDeliver || message.groupMetaMessage == TSGroupMessageNone) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message setMessageState:state];
[message saveWithTransaction:transaction];
}];
}
}
- (void)saveGroupMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{
if(message.groupMetaMessage==TSGroupMessageDeliver) {
[self saveMessage:message withState:message.messageState];
}
else if(message.groupMetaMessage==TSGroupMessageQuit) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[[TSInfoMessage alloc] initWithTimestamp:message.timestamp
inThread:thread
messageType:TSInfoMessageTypeGroupQuit] saveWithTransaction:transaction];
}];
}
else {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[[TSInfoMessage alloc] initWithTimestamp:message.timestamp
inThread:thread
messageType:TSInfoMessageTypeGroupUpdate] saveWithTransaction:transaction];
}];
}
}
- (NSData*)plainTextForMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{
PushMessageContentBuilder *builder = [PushMessageContentBuilder new];
[builder setBody:message.body];
BOOL processAttachments = YES;
if([thread isKindOfClass:[TSGroupThread class]]) {
TSGroupThread *gThread = (TSGroupThread*)thread;
PushMessageContentGroupContextBuilder *groupBuilder = [PushMessageContentGroupContextBuilder new];
switch (message.groupMetaMessage) {
case TSGroupMessageQuit:
[groupBuilder setType:PushMessageContentGroupContextTypeQuit];
break;
case TSGroupMessageUpdate:
case TSGroupMessageNew: {
if(gThread.groupModel.groupImage!=nil && [message.attachments count] == 1) {
id dbObject = [TSAttachmentStream fetchObjectWithUniqueID:[message.attachments firstObject]];
if ([dbObject isKindOfClass:[TSAttachmentStream class]]) {
TSAttachmentStream *attachment = (TSAttachmentStream*)dbObject;
PushMessageContentAttachmentPointerBuilder *attachmentbuilder = [PushMessageContentAttachmentPointerBuilder new];
[attachmentbuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentbuilder setContentType:attachment.contentType];
[attachmentbuilder setKey:attachment.encryptionKey];
[groupBuilder setAvatar:[attachmentbuilder build]];
processAttachments = NO;
}
}
[groupBuilder setMembersArray:gThread.groupModel.groupMemberIds];
[groupBuilder setName:gThread.groupModel.groupName];
[groupBuilder setType:PushMessageContentGroupContextTypeUpdate];
break;
}
default:
[groupBuilder setType:PushMessageContentGroupContextTypeDeliver];
break;
}
[groupBuilder setId:gThread.groupModel.groupId];
[builder setGroup:groupBuilder.build];
}
if(processAttachments) {
NSMutableArray *attachmentsArray = [NSMutableArray array];
for (NSString *attachmentId in message.attachments){
id dbObject = [TSAttachmentStream fetchObjectWithUniqueID:attachmentId];
2014-12-22 00:40:15 +01:00
if ([dbObject isKindOfClass:[TSAttachmentStream class]]) {
TSAttachmentStream *attachment = (TSAttachmentStream*)dbObject;
PushMessageContentAttachmentPointerBuilder *attachmentbuilder = [PushMessageContentAttachmentPointerBuilder new];
[attachmentbuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentbuilder setContentType:attachment.contentType];
[attachmentbuilder setKey:attachment.encryptionKey];
[attachmentsArray addObject:[attachmentbuilder build]];
}
2014-12-22 00:40:15 +01:00
}
[builder setAttachmentsArray:attachmentsArray];
2014-12-22 00:40:15 +01:00
}
return [builder.build data];
}
- (void)handleStaleDevicesWithResponse:(NSData*)responseData recipientId:(NSString*)identifier {
dispatch_async(sendingQueue(), ^{
NSDictionary *serialization = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSArray *devices = serialization[@"staleDevices"];
if (!([devices count] > 0)) {
return;
}
for (NSUInteger i = 0; i < [devices count]; i++) {
int deviceNumber = [devices[i] intValue];
[[TSStorageManager sharedManager] deleteSessionForContact:identifier deviceId:deviceNumber];
}
});
}
@end