Rewriting outgoing pipeline with GCD.

This commit is contained in:
Frederic Jacobs 2014-11-27 03:10:00 +01:00
parent 8514836032
commit 1eff2b3ad5
31 changed files with 415 additions and 207 deletions

View File

@ -8,7 +8,7 @@ pod 'UICKeyChainStore', :podspec => 'Podspecs/UICKeyChainStore.podspec
pod 'SocketRocket', :git => 'https://github.com/square/SocketRocket.git', :commit => 'd0585af165'
pod 'OpenSSL', '~> 1.0.110'
pod 'libPhoneNumber-iOS', '~> 0.7'
pod 'AxolotlKit', '~> 0.1'
pod 'AxolotlKit', '~> 0.3'
pod 'PastelogKit', '~> 1.2'
pod 'TwistedOakCollapsingFutures','~> 1.0'
pod 'YapDatabase/SQLCipher'

View File

@ -21,7 +21,7 @@ PODS:
- AFNetworking/UIKit (2.5.0):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
- AxolotlKit (0.1):
- AxolotlKit (0.3):
- 25519 (~> 1.8)
- HKDFKit (~> 0.0.3)
- ProtocolBuffers (~> 1.9.2)
@ -32,7 +32,7 @@ PODS:
- CocoaLumberjack/Core
- DJWActionSheet (1.0.4)
- HKDFKit (0.0.3)
- JSQMessagesViewController (6.0.0):
- JSQMessagesViewController (6.1.0):
- JSQSystemSoundPlayer (~> 2.0.0)
- JSQSystemSoundPlayer (2.0.0)
- libPhoneNumber-iOS (0.7.3)
@ -51,15 +51,15 @@ PODS:
- UnionFind (~> 1.0)
- UICKeyChainStore (1.0.7)
- UnionFind (1.0.1)
- YapDatabase/common (2.5.3):
- YapDatabase/common (2.5.4):
- CocoaLumberjack (~> 1)
- YapDatabase/SQLCipher (2.5.3):
- YapDatabase/SQLCipher (2.5.4):
- SQLCipher/fts
- YapDatabase/common
DEPENDENCIES:
- AFNetworking (~> 2.5)
- AxolotlKit (~> 0.1)
- AxolotlKit (~> 0.3)
- DJWActionSheet
- JSQMessagesViewController (from `https://github.com/dtsbourg/JSQMessagesViewController`, branch `JSignalQ`)
- libPhoneNumber-iOS (~> 0.7)
@ -83,7 +83,7 @@ EXTERNAL SOURCES:
CHECKOUT OPTIONS:
JSQMessagesViewController:
:commit: 597670e44663c9fa70b6a2deec2b19147c763048
:commit: 5fc12f5cba461203046a6f0b2c62d1b1470197a4
:git: https://github.com/dtsbourg/JSQMessagesViewController
SocketRocket:
:commit: d0585af165
@ -92,11 +92,11 @@ CHECKOUT OPTIONS:
SPEC CHECKSUMS:
25519: 601ffb5d258aa33d642062d6fa4096db210e02e7
AFNetworking: 0f54cb5d16ce38c1b76948faffb8d5fb705021c7
AxolotlKit: 395c3302e840a1b9f053e9733002d586d4b10ce0
AxolotlKit: 19a7a6482e3deb6621e0f81a1733f60301802d40
CocoaLumberjack: 205769c032b5fef85b92472046bcc8b7e7c8a817
DJWActionSheet: d88b302d7c29523e1e9fb9b62cfac46f59bb90d9
HKDFKit: 5998cf1bbb611e7ecc6bd3eaaef8c7a7da7be949
JSQMessagesViewController: 49f449221a8f1da43403e6468ae2015fa0114a9e
JSQMessagesViewController: fb0f6e71c0a8009d210d6c7d73ba2b94bb77dc9b
JSQSystemSoundPlayer: c98443b1cbb3b45db09d0d3d6c2355cf78294981
libPhoneNumber-iOS: 98fc07d70c8fdb5e6a8e3442c37e97353065c20e
Mantle: d7c5ac734579ec751c58fecbf56189853056c58c
@ -108,6 +108,6 @@ SPEC CHECKSUMS:
TwistedOakCollapsingFutures: 07aab84fd3958dc94d55ef705b12857d9fbe61d1
UICKeyChainStore: eef407137f0397e95a3df32cdf05f7e2ddd99647
UnionFind: 45777a8b6878d3a602af3654cc3a09b87389d356
YapDatabase: 096e860167b04e629b88bea33dfb7a4153279bb0
YapDatabase: c1d6912df1b4a160f7373ee7657d360e29bb00fd
COCOAPODS: 0.35.0

View File

@ -327,6 +327,8 @@
B63761ED19E1FBE8005735D1 /* HttpRequestOrResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E719E1FBE8005735D1 /* HttpRequestOrResponse.m */; };
B63761EE19E1FBE8005735D1 /* HttpRequestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E919E1FBE8005735D1 /* HttpRequestUtil.m */; };
B63761EF19E1FBE8005735D1 /* HttpResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761EB19E1FBE8005735D1 /* HttpResponse.m */; };
B63885CD1A26772D00A226A6 /* TSMessagesManager+callRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = B63885CC1A26772D00A226A6 /* TSMessagesManager+callRecorder.m */; };
B63885D01A2685D700A226A6 /* PreKeyBundle+jsonDict.m in Sources */ = {isa = PBXBuildFile; fileRef = B63885CF1A2685D700A226A6 /* PreKeyBundle+jsonDict.m */; };
B63AF5C71A1F757900D01AAD /* TSContactsIntersectionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */; };
B63AF5C81A1F757900D01AAD /* TSUnregisterAccountRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5AF1A1F757900D01AAD /* TSUnregisterAccountRequest.m */; };
B63AF5C91A1F757900D01AAD /* TSRecipientPrekeyRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B11A1F757900D01AAD /* TSRecipientPrekeyRequest.m */; };
@ -905,6 +907,10 @@
B63761E919E1FBE8005735D1 /* HttpRequestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpRequestUtil.m; sourceTree = "<group>"; };
B63761EA19E1FBE8005735D1 /* HttpResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpResponse.h; sourceTree = "<group>"; };
B63761EB19E1FBE8005735D1 /* HttpResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpResponse.m; sourceTree = "<group>"; };
B63885CB1A26772D00A226A6 /* TSMessagesManager+callRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSMessagesManager+callRecorder.h"; sourceTree = "<group>"; };
B63885CC1A26772D00A226A6 /* TSMessagesManager+callRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSMessagesManager+callRecorder.m"; sourceTree = "<group>"; };
B63885CE1A2685D700A226A6 /* PreKeyBundle+jsonDict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PreKeyBundle+jsonDict.h"; sourceTree = "<group>"; };
B63885CF1A2685D700A226A6 /* PreKeyBundle+jsonDict.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PreKeyBundle+jsonDict.m"; sourceTree = "<group>"; };
B63AF5AC1A1F757900D01AAD /* TSContactsIntersectionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContactsIntersectionRequest.h; sourceTree = "<group>"; };
B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSContactsIntersectionRequest.m; sourceTree = "<group>"; };
B63AF5AE1A1F757900D01AAD /* TSUnregisterAccountRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSUnregisterAccountRequest.h; sourceTree = "<group>"; };
@ -1829,6 +1835,8 @@
76EB04F018170B33006006FC /* protocols */ = {
isa = PBXGroup;
children = (
B63885CE1A2685D700A226A6 /* PreKeyBundle+jsonDict.h */,
B63885CF1A2685D700A226A6 /* PreKeyBundle+jsonDict.m */,
76EB04F118170B33006006FC /* Terminable.h */,
76EB04F218170B33006006FC /* utilities */,
);
@ -2671,6 +2679,8 @@
B6B096101A1D25ED008BFAA6 /* TSInteraction.m */,
B6B096111A1D25ED008BFAA6 /* TSMessage.h */,
B6B096121A1D25ED008BFAA6 /* TSMessage.m */,
B63885CB1A26772D00A226A6 /* TSMessagesManager+callRecorder.h */,
B63885CC1A26772D00A226A6 /* TSMessagesManager+callRecorder.m */,
B6B096131A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.h */,
B6B096141A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m */,
B6B096151A1D25ED008BFAA6 /* TSMessagesManager.h */,
@ -3498,6 +3508,7 @@
FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */,
76EB061418170B33006006FC /* AnonymousConditionLogger.m in Sources */,
76EB05C018170B33006006FC /* DhPacket.m in Sources */,
B63885D01A2685D700A226A6 /* PreKeyBundle+jsonDict.m in Sources */,
765052A1182945EF008313E1 /* LocalizableCustomFontLabel.m in Sources */,
FC3196301A0814130094C78E /* SettingsTableViewController.m in Sources */,
7038632818F70C0700D4A43F /* EvpSymetricUtil.m in Sources */,
@ -3594,6 +3605,7 @@
B97CBFAE1886100E008E0DE9 /* CountryCodeTableViewCell.m in Sources */,
B63761E319E1F487005735D1 /* AFHTTPSessionManager+SignalMethods.m in Sources */,
76EB05CC18170B33006006FC /* ShortAuthenticationStringGenerator.m in Sources */,
B63885CD1A26772D00A226A6 /* TSMessagesManager+callRecorder.m in Sources */,
E16E5BEF18AAC40200B7C403 /* EC25KeyAgreementProtocol.m in Sources */,
B6B096901A1D25ED008BFAA6 /* Cryptography.m in Sources */,
76EB064018170B33006006FC /* AnonymousTerminator.m in Sources */,

View File

@ -136,7 +136,7 @@
}
}];
}
[self.window.rootViewController dismissViewControllerAnimated:NO completion:nil];
[self.window.rootViewController presentViewController:callViewController animated:NO completion:nil];
} onThread:NSThread.mainThread untilCancelled:nil];

View File

@ -51,7 +51,7 @@ typedef BOOL (^SearchTermConditionalBlock)(RecentCall*, NSUInteger, BOOL*);
require(phoneManager != nil);
[phoneManager.currentCallObservable watchLatestValue:^(CallState* latestCall) {
if (latestCall != nil && Environment.preferences.getHistoryLogEnabled) {
if (latestCall != nil) {
[self addCall:latestCall];
}
} onThread:NSThread.mainThread untilCancelled:untilCancelledToken];
@ -101,7 +101,6 @@ typedef BOOL (^SearchTermConditionalBlock)(RecentCall*, NSUInteger, BOOL*);
- (void)addRecentCall:(RecentCall *)recentCall {
[_allRecents insertObject:recentCall atIndex:0];
[Environment.preferences setFreshInstallTutorialsEnabled:NO];
[observableRecentsController updateValue:_allRecents.copy];
[self saveContactsToDefaults];
}

View File

@ -75,11 +75,7 @@ static NSString *const DEFAULTS_KEY_DATE = @"DefaultsKeyDate";
}
- (UIImage *)image {
if (Environment.preferences.getContactImagesEnabled) {
return image;
} else {
return nil;
}
return image;
}
- (BOOL)isTextSecureContact{

View File

@ -12,18 +12,6 @@
-(NSTimeInterval) getCachedOrDefaultDesiredBufferDepth;
-(void) setCachedDesiredBufferDepth:(double)value;
-(BOOL) getFreshInstallTutorialsEnabled;
-(BOOL) getContactImagesEnabled;
-(BOOL) getAutocorrectEnabled;
-(BOOL) getHistoryLogEnabled;
-(void) setFreshInstallTutorialsEnabled:(BOOL)enabled;
-(void) setContactImagesEnabled:(BOOL)enabled;
-(void) setAutocorrectEnabled:(BOOL)enabled;
-(void) setHistoryLogEnabled:(BOOL)enabled;
-(BOOL) encounteredRevokedPushPermission;
-(void) setRevokedPushPermission:(BOOL)revoked;
-(BOOL)loggingIsEnabled;
-(void)setLoggingEnabled:(BOOL)flag;

View File

@ -156,6 +156,7 @@
[NSUserDefaults.standardUserDefaults setObject:[NSString stringWithFormat:@"%@", NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]]
forKey:kSignalVersionKey];
[NSUserDefaults.standardUserDefaults synchronize];
return lastVersion;
}

View File

@ -7,7 +7,4 @@
-(id) adjustAndTryGetNewValueForKey:(NSString*)key afterAdjuster:(id (^)(id oldValue))adjuster;
-(void) clear;
-(NSData*) secureDataStoreAdjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster;
-(NSString*) secureStringStoreAdjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster;
@end

View File

@ -34,61 +34,6 @@
}
}
#pragma mark KeyChain store
-(void) secureTrySetValueForKey:(NSString *)key toValue:(id)value {
require(key != nil);
@synchronized(self) {
if (value == nil) {
[UICKeyChainStore removeItemForKey:key];
DDLogWarn(@"Removing object for key: %@", key);
} else {
if ([value isKindOfClass:NSData.class]) {
[UICKeyChainStore setData:value forKey:key];
} else if ([value isKindOfClass:NSString.class]){
[UICKeyChainStore setString:value forKey:key];
} else{
DDLogError(@"Unexpected class stored in the Keychain.");
}
}
}
}
-(NSData*) secureTryGetDataForKey:(NSString *)key {
require(key != nil);
@synchronized(self) {
return [UICKeyChainStore dataForKey:key];
}
}
-(NSString*) secureTryGetStringForKey:(NSString *)key {
require(key != nil);
@synchronized(self) {
return [UICKeyChainStore stringForKey:key];
}
}
-(NSData*) secureDataStoreAdjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster {
require(key != nil);
require(adjuster != nil);
@synchronized(self) {
NSData* oldValue = [self secureTryGetDataForKey:key];
NSData* newValue = adjuster(oldValue);
[UICKeyChainStore setData:newValue forKey:key];
return newValue;
}
}
-(NSString*) secureStringStoreAdjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster {
require(key != nil);
require(adjuster != nil);
@synchronized(self) {
NSString *oldValue = [self secureTryGetStringForKey:key];
NSString *newValue = adjuster(oldValue);
[UICKeyChainStore setString:newValue forKey:key];
return newValue;
}
}
@end

View File

@ -82,7 +82,7 @@
RPAPICall *apiCall = [self defaultAPICall];
apiCall.method = HTTP_GET;
apiCall.endPoint = @"/users/directory";
apiCall.requestSerializer = [self otpAuthenticationSerializer];
apiCall.requestSerializer = [self basicAuthenticationSerializer];
return apiCall;
}
@ -90,7 +90,6 @@
RPAPICall *apiCall = [self defaultAPICall];
apiCall.method = HTTP_DELETE;
apiCall.endPoint = @"/apn";
apiCall.requestSerializer = [self otpAuthenticationSerializer];
return apiCall;
}

View File

@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>
#import "TSInteraction.h"
#import "Contact.h"
@interface TSCall : TSInteraction
@ -22,9 +23,11 @@ typedef NS_ENUM(NSInteger, TSCallType) {
@property (nonatomic, readonly) NSNumber *duration;
@property (nonatomic, readonly) BOOL wasCaller;
@property (nonatomic, readonly) TSCallType callType;
@property (nonatomic) NSString *redPhoneNumber;
- (instancetype)initWithTimestamp:(uint64_t)timeStamp inThread:(TSThread*)thread
wasCaller:(BOOL)caller callType:(TSCallType)callType
duration:(NSNumber*)duration;
- (instancetype)initWithTimestamp:(uint64_t)timeStamp
withCallNumber:(NSString*)contactNumber
wasCaller:(BOOL)caller callType:(TSCallType)callType
duration:(NSNumber*)duration;
@end

View File

@ -10,15 +10,18 @@
@implementation TSCall
- (instancetype)initWithTimestamp:(uint64_t)timeStamp inThread:(TSThread*)thread
- (instancetype)initWithTimestamp:(uint64_t)timeStamp
withCallNumber:(NSString*)contactNumber
wasCaller:(BOOL)caller callType:(TSCallType)callType
duration:(NSNumber*)duration{
self = [super initWithTimestamp:timeStamp inThread:thread];
duration:(NSNumber*)duration
{
self = [super initWithTimestamp:timeStamp inThread:nil];
if (self) {
_wasCaller = caller;
_callType = callType;
_duration = duration;
_wasCaller = caller;
_callType = callType;
_duration = duration;
_redPhoneNumber = contactNumber;
}
return self;

View File

@ -22,13 +22,11 @@ typedef NS_ENUM(int32_t, TSErrorMessageType){
TSErrorMessageInvalidVersion
};
+ (instancetype)invalidProtocolBufferWithException:(NSException*)exception;
+ (instancetype)duplicateMessageWithSignal:(IncomingPushMessageSignal*)preKeyMessage;
+ (instancetype)invalidVersionWithSignal:(IncomingPushMessageSignal*)preKeyMessage;
+ (instancetype)missingKeyIdWithSignal:(IncomingPushMessageSignal*)preKeyMessage;
+ (instancetype)invalidKeyExceptionWithSignal:(IncomingPushMessageSignal*)preKeyMessage;
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage;
+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)preKeyMessage;
+ (instancetype)invalidVersionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
+ (instancetype)missingKeyIdWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
+ (instancetype)invalidKeyExceptionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType;

View File

@ -7,11 +7,12 @@
//
#import "TSErrorMessage.h"
#import "NSDate+millisecondTimeStamp.h"
@implementation TSErrorMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType{
self = [super initWithTimestamp:timestamp inThread:thread messageBody:@"Error Message" attachements:nil];
self = [super initWithTimestamp:timestamp inThread:thread messageBody:@"" attachements:nil];
if (self) {
_errorType = errorMessageType;
@ -20,4 +21,34 @@
return self;
}
+ (instancetype)invalidVersionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
TSContactThread *contactThread = [TSContactThread threadWithContactId:preKeyMessage.source transaction:transaction];
TSErrorMessage *errorMessage = [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:contactThread failedMessageType:TSErrorMessageInvalidVersion];
return errorMessage;
}
+ (instancetype)missingKeyIdWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
TSContactThread *contactThread = [TSContactThread threadWithContactId:preKeyMessage.source transaction:transaction];
TSErrorMessage *errorMessage = [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:contactThread failedMessageType:TSErrorMessageMissingKeyId];
return errorMessage;
}
+ (instancetype)invalidKeyExceptionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
TSContactThread *contactThread = [TSContactThread threadWithContactId:preKeyMessage.source transaction:transaction];
TSErrorMessage *errorMessage = [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:contactThread failedMessageType:TSErrorMessageInvalidKeyException];
return errorMessage;
}
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
TSContactThread *contactThread = [TSContactThread threadWithContactId:preKeyMessage.source transaction:transaction];
TSErrorMessage *errorMessage = [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:contactThread failedMessageType:TSErrorMessageWrongTrustedIdentityKey];
return errorMessage;
}
+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
TSContactThread *contactThread = [TSContactThread threadWithContactId:preKeyMessage.source transaction:transaction];
TSErrorMessage *errorMessage = [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:contactThread failedMessageType:TSErrorMessageNoSession];
return errorMessage;
}
@end

View File

@ -17,6 +17,5 @@ typedef NS_ENUM(NSInteger, TSInfoMessageType){
@property TSInfoMessageType messageType;
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSContactThread *)contact messageType:(TSInfoMessageType)infoMessage;
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSGroupThread *)thread authorId:(NSString *)authorId messageType:(TSInfoMessageType)infoMessage;
@end

View File

@ -10,4 +10,14 @@
@implementation TSInfoMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSContactThread *)contact messageType:(TSInfoMessageType)infoMessage{
self = [super initWithTimestamp:timestamp inThread:contact messageBody:nil attachements:nil];
if (self) {
_messageType = infoMessage;
}
return self;
}
@end

View File

@ -0,0 +1,16 @@
//
// TSMessagesManager+callRecorder.h
// Signal
//
// Created by Frederic Jacobs on 26/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSMessagesManager.h"
#import "TSCall.h"
@interface TSMessagesManager (callRecorder)
- (void)storePhoneCall:(TSCall*)call;
@end

View File

@ -0,0 +1,24 @@
//
// TSMessagesManager+callRecorder.m
// Signal
//
// Created by Frederic Jacobs on 26/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSMessagesManager+callRecorder.h"
#import <YapDatabase/YapDatabaseConnection.h>
#import "Environment.h"
#import "ContactsManager.h"
@implementation TSMessagesManager (callRecorder)
- (void)storePhoneCall:(TSCall*)call{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[call saveWithTransaction:transaction];
}];
}
@end

View File

@ -8,7 +8,9 @@
#import "TSMessagesManager+sendMessages.h"
#import <AxolotlKit/AxolotlExceptions.h>
#import <AxolotlKit/SessionCipher.h>
#import <AxolotlKit/SessionBuilder.h>
#import <Mantle/Mantle.h>
#import "IncomingPushMessageSignal.pb.h"
@ -18,33 +20,53 @@
#import "TSStorageManager+PreKeyStore.h"
#import "TSStorageManager+SignedPreKeyStore.h"
#import "PreKeyBundle+jsonDict.h"
#import "TSErrorMessage.h"
#import "TSNetworkManager.h"
#import "TSServerMessage.h"
#import "TSSubmitMessageRequest.h"
#import "TSRecipientPrekeyRequest.h"
#import "TSContactThread.h"
#import "TSGroupThread.h"
#import "TSRecipient.h"
@interface TSMessagesManager ()
dispatch_queue_t sendingQueue(void);
@end
typedef void (^messagesQueue)(NSArray *messages);
@implementation TSMessagesManager (sendMessages)
- (void)sendMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{
if ([thread isKindOfClass:[TSGroupThread class]]) {
NSLog(@"Currently unsupported");
} else if([thread isKindOfClass:[TSContactThread class]]){
TSContactThread *contactThread = (TSContactThread*)thread;
__block TSRecipient *recipient;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
recipient = [contactThread recipientWithTransaction:transaction];
}];
[self sendMessage:message
toRecipient:recipient
inThread:thread
withAttemps:3];
}
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)sendMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{
dispatch_async(sendingQueue(), ^{
if ([thread isKindOfClass:[TSGroupThread class]]) {
NSLog(@"Currently unsupported");
} else if([thread isKindOfClass:[TSContactThread class]]){
TSContactThread *contactThread = (TSContactThread*)thread;
__block TSRecipient *recipient;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
recipient = [contactThread recipientWithTransaction:transaction];
}];
[self sendMessage:message
toRecipient:recipient
inThread:thread
withAttemps:3];
}
});
}
- (void)sendMessage:(TSOutgoingMessage*)message
toRecipient:(TSRecipient*)recipient
@ -54,35 +76,32 @@
if (remainingAttempts > 0) {
remainingAttempts -= 1;
NSArray *outgoingMessages = [self outgoingMessages:message toRecipient:recipient];
TSSubmitMessageRequest *request = [[TSSubmitMessageRequest alloc] initWithRecipient:recipient.uniqueId messages:outgoingMessages relay:recipient.relay timeStamp:message.timeStamp];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) {
[self handleMessageSent:message inThread:thread];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
long statuscode = response.statusCode;
//TODO: Handle failures
switch (statuscode) {
case 404:
// Recipient not found
break;
case 409:
// Mismatched devices
break;
case 410:
// staledevices
break;
default:
break;
}
[self outgoingMessages:message toRecipient:recipient completion:^(NSArray *messages) {
TSSubmitMessageRequest *request = [[TSSubmitMessageRequest alloc] initWithRecipient:recipient.uniqueId messages:messages relay:recipient.relay timeStamp:message.timeStamp];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) {
[self handleMessageSent:message inThread:thread];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
long statuscode = response.statusCode;
switch (statuscode) {
case 404:
// Recipient not found
DDLogError(@"Recipient not found");
break;
case 409:
// Mismatched devices
DDLogError(@"Missing some devices");
break;
case 410:
// staledevices
DDLogWarn(@"Stale devices");
break;
default:
break;
}
}];
}];
}
}
@ -97,44 +116,75 @@
}];
}
- (NSArray*)outgoingMessages:(TSOutgoingMessage*)message toRecipient:(TSRecipient*)recipient{
- (void)outgoingMessages:(TSOutgoingMessage*)message toRecipient:(TSRecipient*)recipient completion:(messagesQueue)sendMessages{
NSMutableArray *messagesArray = [NSMutableArray arrayWithCapacity:recipient.devices.count];
TSStorageManager *storage = [TSStorageManager sharedManager];
NSData *plainText = [self plainTextForMessage:message];
for (NSNumber *deviceNumber in recipient.devices) {
if (![storage containsSession:recipient.uniqueId deviceId:[deviceNumber intValue]]) {
// Needs to fetch prekey;
}
@try{
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storage
preKeyStore:storage
signedPreKeyStore:storage
identityKeyStore:storage
recipientId:recipient.uniqueId
deviceId:[deviceNumber intValue]];
id<CipherMessage> encryptedMessage = [cipher encryptMessage:plainText];
NSData *serializedMessage = encryptedMessage.serialized;
TSWhisperMessageType messageType = [self messageTypeForCipherMessage:encryptedMessage];
TSServerMessage *serverMessage = [[TSServerMessage alloc] initWithType:messageType
destination:recipient.uniqueId
device:[deviceNumber intValue]
body:serializedMessage];
[messagesArray addObject:[MTLJSONAdapter JSONDictionaryFromModel:serverMessage]];
}@catch (NSException *exception) {
for (NSNumber *deviceNumber in recipient.devices) {
@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];
}
}
@catch (NSException *exception) {
[self processException:exception outgoingMessage:message];
return;
}
}
return messagesArray;
sendMessages(messagesArray);
}
- (NSDictionary*)encryptedMessageWithPlaintext:(NSData*)plainText toRecipient:(NSString*)identifier deviceId:(NSNumber*)deviceNumber keyingStorage:(TSStorageManager*)storage{
if (![storage containsSession:identifier deviceId:[deviceNumber intValue]]) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__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) {
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]];
[builder processPrekeyBundle:bundle];
}
}
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storage
preKeyStore:storage
signedPreKeyStore:storage
identityKeyStore:storage
recipientId:identifier
deviceId:[deviceNumber intValue]];
id<CipherMessage> encryptedMessage = [cipher encryptMessage:plainText];
NSData *serializedMessage = encryptedMessage.serialized;
TSWhisperMessageType messageType = [self messageTypeForCipherMessage:encryptedMessage];
TSServerMessage *serverMessage = [[TSServerMessage alloc] initWithType:messageType
destination:identifier
device:[deviceNumber intValue]
body:serializedMessage];
return [MTLJSONAdapter JSONDictionaryFromModel:serverMessage];
}
- (TSWhisperMessageType)messageTypeForCipherMessage:(id<CipherMessage>)cipherMessage{
@ -151,7 +201,6 @@
PushMessageContentBuilder *builder = [PushMessageContentBuilder new];
[builder setBody:message.body];
return [builder.build data];
//TO-DO: DEAL WITH ATTACHEMENTS AND GROUPS STUFF

View File

@ -104,9 +104,10 @@
if (![storageManager containsSession:recipientId deviceId:deviceId]) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage = [TSErrorMessage missingSessionWithSignal:secureMessage];
TSErrorMessage *errorMessage = [TSErrorMessage missingSessionWithSignal:secureMessage withTransaction:transaction];
[errorMessage saveWithTransaction:transaction];
}];
return;
}
PushMessageContent *content;
@ -237,9 +238,12 @@
}
- (void)processException:(NSException*)exception outgoingMessage:(TSOutgoingMessage*)message{
NSLog(@"Got exception: %@", exception.description);
DDLogWarn(@"Got exception: %@", exception.description);
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message setMessageState:TSOutgoingMessageStateUnsent];
[message saveWithTransaction:transaction];
}];
}
@end

View File

@ -9,5 +9,7 @@
#import "TSRequest.h"
@class TSContact;
@interface TSRecipientPrekeyRequest : TSRequest
-(TSRequest*) initWithRecipient:(TSContact*) contact;
-(TSRequest*) initWithRecipient:(NSString*)recipientNumber deviceId:(NSString*)deviceId;
@end

View File

@ -11,14 +11,14 @@
@implementation TSRecipientPrekeyRequest
-(TSRequest*) initWithRecipient:(NSString*)recipientNumber {
NSString* recipientInformation = recipientNumber;
self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/*", textSecureKeysAPI, recipientInformation]]];
-(TSRequest*) initWithRecipient:(NSString*)recipientNumber deviceId:(NSString*)deviceId{
NSString* recipientInformation = recipientNumber;
[self setHTTPMethod:@"GET"];
return self;
self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/%@", textSecureKeysAPI, recipientInformation, deviceId]]];
[self setHTTPMethod:@"GET"];
return self;
}
@end

View File

@ -20,8 +20,8 @@
self = [super initWithURL:[NSURL URLWithString:textSecureKeysAPI]];
self.HTTPMethod = @"PUT";
NSString *publicIdentityKey = [[identityKeyPublic prependKeyType] base64EncodedStringWithOptions:0];
NSMutableArray *serializedPrekeyList = [NSMutableArray array];
NSString *publicIdentityKey = [[identityKeyPublic prependKeyType] base64EncodedStringWithOptions:0];
NSMutableArray *serializedPrekeyList = [NSMutableArray array];
for (PreKeyRecord *preKey in prekeys) {
[serializedPrekeyList addObject:[self dictionaryFromPreKey:preKey]];

View File

@ -43,4 +43,5 @@ extern NSString *const TSUIDatabaseConnectionDidUpdateNotification;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
- (void)wipe;
@end

View File

@ -16,7 +16,17 @@
// returns the NSData representation of the base64 string
//
+ (NSData *)dataFromBase64String:(NSString *)aString {
return [[NSData alloc] initWithBase64EncodedString:aString options:NSDataBase64DecodingIgnoreUnknownCharacters];
int padding = aString.length%4;
NSMutableString *strResult = [aString mutableCopy];
if (padding != 0) {
int charsToAdd = 4 - padding;
for (int i = 0; i < charsToAdd; i++) {
[strResult appendString:@"="];
}
}
return [[NSData alloc] initWithBase64EncodedString:strResult options:NSDataBase64DecodingIgnoreUnknownCharacters];
}
//

View File

@ -0,0 +1,15 @@
//
// PreKeyBundle+jsonDict.h
// Signal
//
// Created by Frederic Jacobs on 26/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "PreKeyBundle.h"
@interface PreKeyBundle (jsonDict)
+ (PreKeyBundle*)preKeyBundleFromDictionary:(NSDictionary*)dictionary forDeviceNumber:(NSNumber*)number;
@end

View File

@ -0,0 +1,99 @@
//
// PreKeyBundle+jsonDict.m
// Signal
//
// Created by Frederic Jacobs on 26/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "Constraints.h"
#import "PreKeyBundle+jsonDict.h"
#import "NSData+Base64.h"
@implementation PreKeyBundle (jsonDict)
+ (PreKeyBundle*)preKeyBundleFromDictionary:(NSDictionary*)dictionary forDeviceNumber:(NSNumber*)number{
PreKeyBundle *bundle = nil;
NSString *identityKeyString = [dictionary objectForKey:@"identityKey"];
NSArray *devicesArray = [dictionary objectForKey:@"devices"];
if (!(identityKeyString && [devicesArray isKindOfClass:[NSArray class]])) {
DDLogError(@"Failed to get identity key or messages array from server request");
return nil;
}
NSData *identityKey = [NSData dataFromBase64String:identityKeyString];
NSLog(@"IDentityKey %@", identityKey);
for (NSDictionary *deviceDict in devicesArray) {
NSNumber *registrationIdString = [deviceDict objectForKey:@"registrationId"];
NSNumber *deviceIdString = [deviceDict objectForKey:@"deviceId"];
if (!(registrationIdString && deviceIdString)) {
DDLogError(@"Failed to get the registration id and device id");
return nil;
}
if (![deviceIdString isEqualToNumber:number]) {
DDLogWarn(@"Got a keyid for another device");
return nil;
}
int registrationId = [registrationIdString intValue];
int deviceId = [deviceIdString intValue];
NSDictionary *preKey = [deviceDict objectForKey:@"preKey"];
int prekeyId;
NSData *preKeyPublic = nil;
if (!preKey) {
prekeyId = -1;
} else{
prekeyId = [[preKey objectForKey:@"keyId"] intValue];
NSString *preKeyPublicString = [preKey objectForKey:@"publicKey"];
preKeyPublic = [NSData dataFromBase64String:preKeyPublicString];
}
NSDictionary *signedPrekey = [deviceDict objectForKey:@"signedPreKey"];
if (![signedPrekey isKindOfClass:[NSDictionary class]]) {
DDLogError(@"Device doesn't have signed prekeys registered");
return nil;
}
NSNumber *signedKeyIdNumber = [signedPrekey objectForKey:@"keyId"];
NSString *signedSignatureString = [signedPrekey objectForKey:@"signature"];
NSString *signedPublicKeyString = [signedPrekey objectForKey:@"publicKey"];
if (!(signedKeyIdNumber && signedPublicKeyString && signedSignatureString)) {
DDLogError(@"Missing signed key material");
return nil;
}
NSData *signedPrekeyPublic = [NSData dataFromBase64String:signedPublicKeyString];
NSData *signedPreKeySignature = [NSData dataFromBase64String:signedSignatureString];
if (!(signedPrekeyPublic && signedPreKeySignature)) {
DDLogError(@"Failed to parse signed keying material");
return nil;
}
int signedPreKeyId = [signedKeyIdNumber intValue];
bundle = [[self alloc] initWithRegistrationId:registrationId
deviceId:deviceId
preKeyId:prekeyId
preKeyPublic:preKeyPublic
signedPreKeyPublic:signedPrekeyPublic
signedPreKeyId:signedPreKeyId
signedPreKeySignature:signedPreKeySignature
identityKey:identityKey];
}
return bundle;
}
@end

View File

@ -8,6 +8,8 @@
#import "CodeVerificationViewController.h"
#import "Environment.h"
#import "PhoneNumberDirectoryFilterManager.h"
#import "RPServerRequestsManager.h"
#import "LocalizableText.h"
#import "PushManager.h"
@ -39,11 +41,11 @@
//TODO: Lock UI interactions
[self registerWithSuccess:^{
[Environment.getCurrent.phoneDirectoryManager forceUpdate];
[self performSegueWithIdentifier:@"verifiedSegue" sender:self];
} failure:^(NSError *error) {
// TODO: Unlock UI
NSLog(@"Failed to register");
[self showAlertForError:error];
}];
}

View File

@ -11,6 +11,7 @@
#import "SettingsTableViewCell.h"
#import "TSAccountManager.h"
#import "TSStorageManager.h"
#import "RPServerRequestsManager.h"
@ -119,11 +120,11 @@ typedef enum {
break;
case kUnregisterCell:
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall unregister] success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"YEAH!");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"Fail");
NSLog(@"error: %@ ", error.debugDescription);
[TSAccountManager unregisterTextSecureWithSuccess:^{
[[TSStorageManager sharedManager] wipe];
exit(0);
} failure:^(NSError *error) {
SignalAlertView(@"Failed to unregister", @"");
}];
break;
@ -133,6 +134,4 @@ typedef enum {
}
}
@end

View File

@ -29,6 +29,8 @@
@property (nonatomic, copy) NSDate *messageDate;
@property (nonatomic, retain) NSString *messageBody;
@property NSUInteger identifier;
@end
@ -38,7 +40,8 @@
TSMessageAdapter *adapter = [[TSMessageAdapter alloc] init];
adapter.messageDate = interaction.date;
adapter.identifier = (NSUInteger)interaction.uniqueId;
if ([thread isKindOfClass:[TSContactThread class]]) {
adapter.thread = (TSContactThread*)thread;
if ([interaction isKindOfClass:[TSIncomingMessage class]]) {
@ -60,7 +63,7 @@
}
}
if ([interaction isKindOfClass:[TSMessage class]]) {
if ([interaction isKindOfClass:[TSIncomingMessage class]] || [interaction isKindOfClass:[TSOutgoingMessage class]]) {
TSMessage *message = (TSMessage*)interaction;
adapter.messageBody = message.body;
} else if ([interaction isKindOfClass:[TSCall class]]){
@ -74,7 +77,6 @@
return adapter;
}
- (NSString*)senderId{
if (_senderId) {
return _senderId;
@ -103,4 +105,8 @@
return self.messageBody;
}
- (NSUInteger)hash{
return self.identifier;
}
@end