Merge branch 'charlesmchen/prekeyDoubleUpdate_'

This commit is contained in:
Matthew Chen 2017-04-14 14:34:31 -04:00
commit 2367ab7439
3 changed files with 45 additions and 9 deletions

View File

@ -26,7 +26,7 @@ typedef NS_ENUM(NSInteger, RefreshPreKeysMode) {
success:(void (^)())successHandler success:(void (^)())successHandler
failure:(void (^)(NSError *error))failureHandler; failure:(void (^)(NSError *error))failureHandler;
+ (void)refreshPreKeys; + (void)checkPreKeys;
+ (void)checkPreKeysIfNecessary; + (void)checkPreKeysIfNecessary;

View File

@ -95,9 +95,21 @@ static const CGFloat kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * 24 * 60
BOOL shouldCheck = (lastPreKeyCheckTimestamp == nil BOOL shouldCheck = (lastPreKeyCheckTimestamp == nil
|| fabs([lastPreKeyCheckTimestamp timeIntervalSinceNow]) >= kPreKeyCheckFrequencySeconds); || fabs([lastPreKeyCheckTimestamp timeIntervalSinceNow]) >= kPreKeyCheckFrequencySeconds);
if (shouldCheck) { if (shouldCheck) {
// Optimistically mark the prekeys as checked. This
// de-bounces prekey checks.
//
// If the check or key registration fails, the prekeys
// will be marked as _NOT_ checked.
//
// Note: [TSPreKeyManager checkPreKeys] will also
// optimistically mark them as checked. This
// redundancy is fine and precludes a race
// condition.
lastPreKeyCheckTimestamp = [NSDate date];
[[TSAccountManager sharedInstance] ifRegistered:YES [[TSAccountManager sharedInstance] ifRegistered:YES
runAsync:^{ runAsync:^{
[TSPreKeyManager refreshPreKeys]; [TSPreKeyManager checkPreKeys];
}]; }];
} }
}); });
@ -110,6 +122,9 @@ static const CGFloat kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * 24 * 60
// We use prekeyQueue to serialize this logic and ensure that only // We use prekeyQueue to serialize this logic and ensure that only
// one thread is "registering" or "clearing" prekeys at a time. // one thread is "registering" or "clearing" prekeys at a time.
dispatch_async(TSPreKeyManager.prekeyQueue, ^{ dispatch_async(TSPreKeyManager.prekeyQueue, ^{
// Mark the prekeys as checked every time we try to register prekeys.
lastPreKeyCheckTimestamp = [NSDate date];
RefreshPreKeysMode modeCopy = mode; RefreshPreKeysMode modeCopy = mode;
TSStorageManager *storageManager = [TSStorageManager sharedManager]; TSStorageManager *storageManager = [TSStorageManager sharedManager];
ECKeyPair *identityKeyPair = [storageManager identityKeyPair]; ECKeyPair *identityKeyPair = [storageManager identityKeyPair];
@ -165,6 +180,9 @@ static const CGFloat kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * 24 * 60
failure:^(NSURLSessionDataTask *task, NSError *error) { failure:^(NSURLSessionDataTask *task, NSError *error) {
OWSAnalyticsError(@"Prekey update failed (%@): %@", description, error); OWSAnalyticsError(@"Prekey update failed (%@): %@", description, error);
// Mark the prekeys as _NOT_ checked on failure.
[self markPreKeysAsNotChecked];
failureHandler(error); failureHandler(error);
NSInteger statusCode = 0; NSInteger statusCode = 0;
@ -181,7 +199,17 @@ static const CGFloat kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * 24 * 60
}); });
} }
+ (void)refreshPreKeys { + (void)checkPreKeys
{
// Optimistically mark the prekeys as checked. This
// de-bounces prekey checks.
//
// If the check or key registration fails, the prekeys
// will be marked as _NOT_ checked.
dispatch_async(TSPreKeyManager.prekeyQueue, ^{
lastPreKeyCheckTimestamp = [NSDate date];
});
// We want to update prekeys if either the one-time or signed prekeys need an update, so // We want to update prekeys if either the one-time or signed prekeys need an update, so
// we check the status of both. // we check the status of both.
// //
@ -242,11 +270,6 @@ static const CGFloat kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * 24 * 60
DDLogDebug(@"%@ Not updating prekeys.", self.tag); DDLogDebug(@"%@ Not updating prekeys.", self.tag);
} }
} }
// Update the prekey check timestamp on success.
dispatch_async(TSPreKeyManager.prekeyQueue, ^{
lastPreKeyCheckTimestamp = [NSDate date];
});
if (!didUpdatePreKeys) { if (!didUpdatePreKeys) {
// If we didn't update the prekeys, our local "current signed key" state should // If we didn't update the prekeys, our local "current signed key" state should
@ -273,14 +296,27 @@ static const CGFloat kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * 24 * 60
} }
failure:^(NSURLSessionDataTask *task, NSError *error) { failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogWarn(@"%@ Could not retrieve current signed key from the service.", self.tag); DDLogWarn(@"%@ Could not retrieve current signed key from the service.", self.tag);
// Mark the prekeys as _NOT_ checked on failure.
[self markPreKeysAsNotChecked];
}]; }];
} }
} }
failure:^(NSURLSessionDataTask *task, NSError *error) { failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"%@ Failed to retrieve the number of available prekeys.", self.tag); DDLogError(@"%@ Failed to retrieve the number of available prekeys.", self.tag);
// Mark the prekeys as _NOT_ checked on failure.
[self markPreKeysAsNotChecked];
}]; }];
} }
+ (void)markPreKeysAsNotChecked
{
dispatch_async(TSPreKeyManager.prekeyQueue, ^{
lastPreKeyCheckTimestamp = nil;
});
}
+ (void)clearSignedPreKeyRecords { + (void)clearSignedPreKeyRecords {
TSStorageManager *storageManager = [TSStorageManager sharedManager]; TSStorageManager *storageManager = [TSStorageManager sharedManager];
NSNumber *currentSignedPrekeyId = [storageManager currentSignedPrekeyId]; NSNumber *currentSignedPrekeyId = [storageManager currentSignedPrekeyId];

View File

@ -304,7 +304,7 @@ NS_ASSUME_NONNULL_BEGIN
NSData *plaintextData; NSData *plaintextData;
@try { @try {
// Check whether we need to refresh our PreKeys every time we receive a PreKeyWhisperMessage. // Check whether we need to refresh our PreKeys every time we receive a PreKeyWhisperMessage.
[TSPreKeyManager refreshPreKeys]; [TSPreKeyManager checkPreKeys];
PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:encryptedData]; PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:encryptedData];
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager