161 lines
6.4 KiB
Objective-C
161 lines
6.4 KiB
Objective-C
#import "PhoneNumberDirectoryFilterManager.h"
|
|
|
|
#import "ContactsManager.h"
|
|
#import "Cryptography.h"
|
|
#import "Environment.h"
|
|
#import "NotificationManifest.h"
|
|
#import "PreferencesUtil.h"
|
|
#import "RPServerRequestsManager.h"
|
|
#import "SignalUtil.h"
|
|
#import "ThreadManager.h"
|
|
#import "TSContactsIntersectionRequest.h"
|
|
#import "TSStorageManager.h"
|
|
#import "TSRecipient.h"
|
|
#import "Util.h"
|
|
|
|
#define MINUTE (60.0)
|
|
#define HOUR (MINUTE*60.0)
|
|
|
|
#define DIRECTORY_UPDATE_TIMEOUT_PERIOD (1.0*MINUTE)
|
|
#define DIRECTORY_UPDATE_RETRY_PERIOD (1.0*HOUR)
|
|
|
|
@implementation PhoneNumberDirectoryFilterManager {
|
|
@private TOCCancelTokenSource* currentUpdateLifetime;
|
|
}
|
|
|
|
- (id)init {
|
|
if (self = [super init]) {
|
|
phoneNumberDirectoryFilter = PhoneNumberDirectoryFilter.phoneNumberDirectoryFilterDefault;
|
|
_isRefreshing = NO;
|
|
}
|
|
return self;
|
|
}
|
|
- (void)startUntilCancelled:(TOCCancelToken*)cancelToken {
|
|
lifetimeToken = cancelToken;
|
|
|
|
phoneNumberDirectoryFilter = [Environment.preferences tryGetSavedPhoneNumberDirectory];
|
|
if (phoneNumberDirectoryFilter == nil) {
|
|
phoneNumberDirectoryFilter = PhoneNumberDirectoryFilter.phoneNumberDirectoryFilterDefault;
|
|
}
|
|
|
|
[self scheduleUpdate];
|
|
}
|
|
|
|
- (PhoneNumberDirectoryFilter*)getCurrentFilter {
|
|
@synchronized(self) {
|
|
return phoneNumberDirectoryFilter;
|
|
}
|
|
}
|
|
- (void)forceUpdate {
|
|
[self scheduleUpdateAt:NSDate.date];
|
|
}
|
|
- (void)scheduleUpdate {
|
|
return [self scheduleUpdateAt:self.getCurrentFilter.getExpirationDate];
|
|
}
|
|
- (void)scheduleUpdateAt:(NSDate*)date {
|
|
void(^doUpdate)(void) = ^{
|
|
if (Environment.isRedPhoneRegistered) {
|
|
[self updateRedPhone];
|
|
|
|
}
|
|
};
|
|
|
|
[currentUpdateLifetime cancel];
|
|
currentUpdateLifetime = [TOCCancelTokenSource new];
|
|
[lifetimeToken whenCancelledDo:^{ [currentUpdateLifetime cancel]; }];
|
|
[TimeUtil scheduleRun:doUpdate
|
|
at:date
|
|
onRunLoop:[ThreadManager normalLatencyThreadRunLoop]
|
|
unlessCancelled:currentUpdateLifetime.token];
|
|
}
|
|
|
|
|
|
- (void) updateRedPhone {
|
|
_isRefreshing = YES;
|
|
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall fetchBloomFilter] success:^(NSURLSessionDataTask *task, id responseObject) {
|
|
PhoneNumberDirectoryFilter *directory = [PhoneNumberDirectoryFilter phoneNumberDirectoryFilterFromURLResponse:(NSHTTPURLResponse*)task.response body:responseObject];
|
|
|
|
@synchronized(self) {
|
|
phoneNumberDirectoryFilter = directory;
|
|
}
|
|
|
|
[Environment.preferences setSavedPhoneNumberDirectory:directory];
|
|
[self updateTextSecureWithRedPhoneSucces:YES];
|
|
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
|
DDLogError(@"Error to fetch contact interesection: %@", error.debugDescription);
|
|
NSString* desc = [NSString stringWithFormat:NSLocalizedString(@"FAILED_RETRYING_DIRECTORY_DOWNLOAD", @""),
|
|
DIRECTORY_UPDATE_RETRY_PERIOD/HOUR];
|
|
Environment.errorNoter(desc, error, false);
|
|
BloomFilter* filter = [phoneNumberDirectoryFilter bloomFilter];
|
|
NSDate* retryDate = [NSDate dateWithTimeInterval:DIRECTORY_UPDATE_RETRY_PERIOD
|
|
sinceDate:[NSDate date]];
|
|
@synchronized(self) {
|
|
phoneNumberDirectoryFilter = [PhoneNumberDirectoryFilter phoneNumberDirectoryFilterWithBloomFilter:filter
|
|
andExpirationDate:retryDate];
|
|
}
|
|
|
|
[self updateTextSecureWithRedPhoneSucces:NO];
|
|
}];
|
|
}
|
|
|
|
- (void)updateTextSecureWithRedPhoneSucces:(BOOL)redPhoneSuccess {
|
|
NSArray *allContacts = [[[Environment getCurrent] contactsManager] allContacts];
|
|
|
|
NSMutableDictionary *contactsByPhoneNumber = [NSMutableDictionary dictionary];
|
|
NSMutableDictionary *phoneNumbersByHashes = [NSMutableDictionary dictionary];
|
|
|
|
for (Contact *contact in allContacts) {
|
|
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
|
[phoneNumbersByHashes setObject:phoneNumber.toE164 forKey:[Cryptography truncatedSHA1Base64EncodedWithoutPadding:phoneNumber.toE164]];
|
|
[contactsByPhoneNumber setObject:contact forKey:phoneNumber.toE164];
|
|
}
|
|
}
|
|
|
|
NSArray *hashes = [phoneNumbersByHashes allKeys];
|
|
|
|
TSRequest *request = [[TSContactsIntersectionRequest alloc]initWithHashesArray:hashes];
|
|
|
|
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *tsTask, id responseDict) {
|
|
NSMutableArray *tsIdentifiers = [NSMutableArray array];
|
|
NSMutableDictionary *relayForIdentifier = [NSMutableDictionary dictionary];
|
|
NSArray *contactsArray = [(NSDictionary*)responseDict objectForKey:@"contacts"];
|
|
|
|
if (contactsArray) {
|
|
for (NSDictionary *dict in contactsArray) {
|
|
NSString *hash = [dict objectForKey:@"token"];
|
|
|
|
if (hash) {
|
|
[tsIdentifiers addObject:[phoneNumbersByHashes objectForKey:hash]];
|
|
|
|
NSString *relay = [dict objectForKey:@"relay"];
|
|
if (relay) {
|
|
[relayForIdentifier setObject:relay forKey:[phoneNumbersByHashes objectForKey:hash]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
for (NSString *identifier in tsIdentifiers) {
|
|
TSRecipient *recipient = [TSRecipient recipientWithTextSecureIdentifier:identifier withTransaction:transaction];
|
|
if (!recipient) {
|
|
NSString *relay = [relayForIdentifier objectForKey:recipient];
|
|
recipient = [[TSRecipient alloc] initWithTextSecureIdentifier:identifier relay:relay];
|
|
}
|
|
[recipient saveWithTransaction:transaction];
|
|
}
|
|
}];
|
|
|
|
_isRefreshing = NO;
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_WAS_UPDATED object:nil];
|
|
|
|
[self scheduleUpdate];
|
|
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
|
_isRefreshing = NO;
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_FAILED object:nil];
|
|
}];
|
|
}
|
|
|
|
|
|
@end
|