restore PreKey upload failure tracking

pull/1/head
Michael Kirk 7 years ago
parent 39b691b697
commit 85d35b52d6

@ -80,6 +80,7 @@ public class RotateSignedPreKeyOperation: OWSOperation {
self.primaryStorage.storeSignedPreKey(signedPreKeyRecord.id, signedPreKeyRecord: signedPreKeyRecord) self.primaryStorage.storeSignedPreKey(signedPreKeyRecord.id, signedPreKeyRecord: signedPreKeyRecord)
self.primaryStorage.setCurrentSignedPrekeyId(signedPreKeyRecord.id) self.primaryStorage.setCurrentSignedPrekeyId(signedPreKeyRecord.id)
TSPreKeyManager.clearPreKeyUpdateFailureCount()
TSPreKeyManager.clearSignedPreKeyRecords() TSPreKeyManager.clearSignedPreKeyRecords()
}.then { () -> Void in }.then { () -> Void in
Logger.debug("done") Logger.debug("done")
@ -88,6 +89,25 @@ public class RotateSignedPreKeyOperation: OWSOperation {
self.reportError(error) self.reportError(error)
}.retainUntilComplete() }.retainUntilComplete()
} }
override public func didFail(error: Error) {
switch error {
case let networkManagerError as NetworkManagerError:
guard !networkManagerError.isNetworkError else {
Logger.debug("don't report SPK rotation failure w/ network error")
return
}
guard networkManagerError.statusCode >= 400 && networkManagerError.statusCode <= 599 else {
Logger.debug("don't report SPK rotation failure w/ non application error")
return
}
TSPreKeyManager.incrementPreKeyUpdateFailureCount()
default:
Logger.debug("don't report SPK rotation failure w/ non NetworkManager error: \(error)")
}
}
} }
@objc(SSKRefreshPreKeysOperation) @objc(SSKRefreshPreKeysOperation)
@ -136,6 +156,7 @@ public class RefreshPreKeysOperation: OWSOperation {
self.primaryStorage.setCurrentSignedPrekeyId(signedPreKeyRecord.id) self.primaryStorage.setCurrentSignedPrekeyId(signedPreKeyRecord.id)
self.primaryStorage.storePreKeyRecords(preKeyRecords) self.primaryStorage.storePreKeyRecords(preKeyRecords)
TSPreKeyManager.clearPreKeyUpdateFailureCount()
TSPreKeyManager.clearSignedPreKeyRecords() TSPreKeyManager.clearSignedPreKeyRecords()
} }
}.then { () -> Void in }.then { () -> Void in
@ -145,4 +166,23 @@ public class RefreshPreKeysOperation: OWSOperation {
self.reportError(error) self.reportError(error)
}.retainUntilComplete() }.retainUntilComplete()
} }
override public func didFail(error: Error) {
switch error {
case let networkManagerError as NetworkManagerError:
guard !networkManagerError.isNetworkError else {
Logger.debug("don't report SPK rotation failure w/ network error")
return
}
guard networkManagerError.statusCode >= 400 && networkManagerError.statusCode <= 599 else {
Logger.debug("don't report SPK rotation failure w/ non application error")
return
}
TSPreKeyManager.incrementPreKeyUpdateFailureCount()
default:
Logger.debug("don't report SPK rotation failure w/ non NetworkManager error: \(error)")
}
}
} }

@ -19,8 +19,18 @@ typedef NS_ENUM(NSInteger, RefreshPreKeysMode) {
@interface TSPreKeyManager : NSObject @interface TSPreKeyManager : NSObject
#pragma mark - State Tracking
+ (BOOL)isAppLockedDueToPreKeyUpdateFailures; + (BOOL)isAppLockedDueToPreKeyUpdateFailures;
+ (void)incrementPreKeyUpdateFailureCount;
+ (void)clearPreKeyUpdateFailureCount;
+ (void)clearSignedPreKeyRecords;
#pragma mark - Check/Request Initiation
+ (void)rotateSignedPreKeyWithSuccess:(void (^)(void))successHandler failure:(void (^)(NSError *error))failureHandler; + (void)rotateSignedPreKeyWithSuccess:(void (^)(void))successHandler failure:(void (^)(NSError *error))failureHandler;
+ (void)createPreKeysWithSuccess:(void (^)(void))successHandler failure:(void (^)(NSError *error))failureHandler; + (void)createPreKeysWithSuccess:(void (^)(void))successHandler failure:(void (^)(NSError *error))failureHandler;
@ -28,6 +38,5 @@ typedef NS_ENUM(NSInteger, RefreshPreKeysMode) {
+ (void)checkPreKeys; + (void)checkPreKeys;
+ (void)checkPreKeysIfNecessary; + (void)checkPreKeysIfNecessary;
+ (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber *)keyId;
@end @end

@ -37,6 +37,8 @@ static const NSUInteger kMaxPrekeyUpdateFailureCount = 5;
@implementation TSPreKeyManager @implementation TSPreKeyManager
#pragma mark - State Tracking
+ (BOOL)isAppLockedDueToPreKeyUpdateFailures + (BOOL)isAppLockedDueToPreKeyUpdateFailures
{ {
// Only disable message sending if we have failed more than N times // Only disable message sending if we have failed more than N times
@ -53,6 +55,8 @@ static const NSUInteger kMaxPrekeyUpdateFailureCount = 5;
// Record a prekey update failure. // Record a prekey update failure.
OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager]; OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager];
int failureCount = [primaryStorage incrementPrekeyUpdateFailureCount]; int failureCount = [primaryStorage incrementPrekeyUpdateFailureCount];
OWSLogInfo(@"new failureCount: %d", failureCount);
if (failureCount == 1 || ![primaryStorage firstPrekeyUpdateFailureDate]) { if (failureCount == 1 || ![primaryStorage firstPrekeyUpdateFailureDate]) {
// If this is the "first" failure, record the timestamp of that // If this is the "first" failure, record the timestamp of that
// failure. // failure.
@ -67,6 +71,8 @@ static const NSUInteger kMaxPrekeyUpdateFailureCount = 5;
[primaryStorage clearPrekeyUpdateFailureCount]; [primaryStorage clearPrekeyUpdateFailureCount];
} }
#pragma mark - Check/Request Initiation
+ (NSOperationQueue *)operationQueue + (NSOperationQueue *)operationQueue
{ {
static dispatch_once_t onceToken; static dispatch_once_t onceToken;

@ -0,0 +1,46 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import PromiseKit
enum NetworkManagerError: Error {
/// Wraps TSNetworkManager failure callback params in a single throwable error
case taskError(task: URLSessionDataTask, underlyingError: Error)
}
extension NetworkManagerError {
var isNetworkError: Bool {
switch self {
case .taskError(_, let underlyingError):
return IsNSErrorNetworkFailure(underlyingError)
}
}
var statusCode: Int {
switch self {
case .taskError(let task, _):
return task.statusCode()
}
}
}
extension TSNetworkManager {
func makePromise(request: TSRequest) -> Promise<(task: URLSessionDataTask, responseObject: Any?)> {
let (promise, fulfill, reject) = Promise<(task: URLSessionDataTask, responseObject: Any?)>.pending()
self.makeRequest(request,
success: { task, responseObject in
fulfill((task: task, responseObject: responseObject))
},
failure: { task, error in
let nmError = NetworkManagerError.taskError(task: task, underlyingError: error)
let nsError: NSError = nmError as NSError
nsError.isRetryable = (error as NSError).isRetryable
reject(nsError)
})
return promise
}
}

@ -24,67 +24,30 @@ class ServiceRestSocket: ServiceSocket {
func getAvailablePreKeys() -> Promise<Int> { func getAvailablePreKeys() -> Promise<Int> {
Logger.debug("") Logger.debug("")
let (promise, fulfill, reject) = Promise<Int>.pending()
let request = OWSRequestFactory.availablePreKeysCountRequest() let request = OWSRequestFactory.availablePreKeysCountRequest()
networkManager.makeRequest(request, return networkManager.makePromise(request: request).then { (_, responseObject) -> Int in
success: { (_, responseObject) in Logger.debug("got response")
Logger.debug("got response") guard let params = ParamParser(responseObject: responseObject) else {
guard let params = ParamParser(responseObject: responseObject) else { throw self.unexpectedServerResponseError()
reject(self.unexpectedServerResponseError()) }
return
}
let count: Int let count: Int = try! params.required(key: "count")
do {
count = try params.required(key: "count")
} catch {
reject(error)
return
}
fulfill(count) return count
}, }
failure: { (_, error) in
Logger.debug("error: \(error)")
reject(error)
})
return promise
} }
func registerPreKeys(identityKey: IdentityKey, signedPreKeyRecord: SignedPreKeyRecord, preKeyRecords: [PreKeyRecord]) -> Promise<Void> { func registerPreKeys(identityKey: IdentityKey, signedPreKeyRecord: SignedPreKeyRecord, preKeyRecords: [PreKeyRecord]) -> Promise<Void> {
Logger.debug("") Logger.debug("")
let (promise, fulfill, reject) = Promise<Void>.pending()
let request = OWSRequestFactory.registerPrekeysRequest(withPrekeyArray: preKeyRecords, identityKey: identityKey, signedPreKey: signedPreKeyRecord) let request = OWSRequestFactory.registerPrekeysRequest(withPrekeyArray: preKeyRecords, identityKey: identityKey, signedPreKey: signedPreKeyRecord)
return networkManager.makePromise(request: request).asVoid()
networkManager.makeRequest(request,
success: { (_, _) in
Logger.debug("success")
fulfill(())
},
failure: { (_, error) in
Logger.debug("error: \(error)")
reject(error)
})
return promise
} }
public func setCurrentSignedPreKey(_ signedPreKey: SignedPreKeyRecord) -> Promise<Void> { public func setCurrentSignedPreKey(_ signedPreKey: SignedPreKeyRecord) -> Promise<Void> {
let (promise, fulfill, reject) = Promise<Void>.pending() Logger.debug("")
let request = OWSRequestFactory.registerSignedPrekeyRequest(with: signedPreKey)
networkManager.makeRequest(request,
success: { (_, _) in
Logger.debug("success")
fulfill(())
}, let request = OWSRequestFactory.registerSignedPrekeyRequest(with: signedPreKey)
failure: { (_, error) in return networkManager.makePromise(request: request).asVoid()
Logger.debug("error: \(error)")
reject(error)
})
return promise
} }
} }

Loading…
Cancel
Save