Move "ud access for sends" logic into UD manager.

pull/1/head
Matthew Chen 7 years ago
parent 3f10ce7408
commit ad59b2f6d2

@ -54,7 +54,7 @@ public class OWSMessageSend: NSObject {
thread: TSThread?,
recipient: SignalRecipient,
senderCertificate: SMKSenderCertificate?,
udManager: OWSUDManager,
udAccessKey: SMKUDAccessKey?,
localNumber: String,
success: @escaping () -> Void,
failure: @escaping (Error) -> Void) {
@ -63,17 +63,9 @@ public class OWSMessageSend: NSObject {
self.recipient = recipient
self.localNumber = localNumber
self.senderCertificate = senderCertificate
self.udAccessKey = udAccessKey
if let recipientId = recipient.uniqueId {
if senderCertificate != nil {
let accessMode = udManager.unidentifiedAccessMode(forRecipientId: recipientId)
if accessMode == .unrestricted {
self.udAccessKey = udManager.randomUDAccessKey()
} else if accessMode == .unrestricted {
self.udAccessKey = udManager.udAccessKey(forRecipientId: recipientId)
}
}
self.isLocalNumber = localNumber == recipientId
} else {
owsFailDebug("SignalRecipient missing recipientId")

@ -578,6 +578,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
message:(TSOutgoingMessage *)message
thread:(nullable TSThread *)thread
senderCertificate:(nullable SMKSenderCertificate *)senderCertificate
selfUDAccessKey:(nullable SMKUDAccessKey *)selfUDAccessKey
sendErrors:(NSMutableArray<NSError *> *)sendErrors
{
OWSAssertDebug(recipients.count > 0);
@ -589,11 +590,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
for (SignalRecipient *recipient in recipients) {
// Use chained promises to make the code more readable.
AnyPromise *sendPromise = [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
SMKUDAccessKey *_Nullable theirUDAccessKey;
if (senderCertificate != nil && selfUDAccessKey != nil) {
theirUDAccessKey = [self.udManager udSendAccessKeyForRecipientId:recipient.recipientId];
}
OWSMessageSend *messageSend = [[OWSMessageSend alloc] initWithMessage:message
thread:thread
recipient:recipient
senderCertificate:senderCertificate
udManager:self.udManager
udAccessKey:theirUDAccessKey
localNumber:self.tsAccountManager.localNumber
success:^{
// The value doesn't matter, we just need any non-NSError value.
@ -624,10 +630,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
{
AssertIsOnSendingQueue();
SMKUDAccessKey *_Nullable selfUDAccessKey;
if (senderCertificate) {
selfUDAccessKey = [self.udManager udSendAccessKeyForRecipientId:self.tsAccountManager.localNumber];
}
void (^successHandler)(void) = ^() {
dispatch_async([OWSDispatch sendingQueue], ^{
[self handleMessageSentLocally:message
senderCertificate:senderCertificate
selfUDAccessKey:selfUDAccessKey
success:^{
successHandlerParam();
}
@ -645,6 +657,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
dispatch_async([OWSDispatch sendingQueue], ^{
[self handleMessageSentLocally:message
senderCertificate:senderCertificate
selfUDAccessKey:selfUDAccessKey
success:^{
failureHandlerParam(error);
}
@ -726,6 +739,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
message:message
thread:thread
senderCertificate:senderCertificate
selfUDAccessKey:selfUDAccessKey
sendErrors:sendErrors]
.then(^(id value) {
successHandler();
@ -1328,6 +1342,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
- (void)handleMessageSentLocally:(TSOutgoingMessage *)message
senderCertificate:(nullable SMKSenderCertificate *)senderCertificate
selfUDAccessKey:(nullable SMKUDAccessKey *)selfUDAccessKey
success:(void (^)(void))success
failure:(RetryableFailureHandler)failure
{
@ -1344,6 +1359,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[self
sendSyncTranscriptForMessage:message
senderCertificate:senderCertificate
selfUDAccessKey:selfUDAccessKey
success:^{
// TODO: We might send to a recipient, then to another recipient on retry.
// To ensure desktop receives all "delivery status" info, we might
@ -1360,6 +1376,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
- (void)sendSyncTranscriptForMessage:(TSOutgoingMessage *)message
senderCertificate:(nullable SMKSenderCertificate *)senderCertificate
selfUDAccessKey:(nullable SMKUDAccessKey *)selfUDAccessKey
success:(void (^)(void))success
failure:(RetryableFailureHandler)failure
{
@ -1376,7 +1393,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
thread:message.thread
recipient:recipient
senderCertificate:senderCertificate
udManager:self.udManager
udAccessKey:selfUDAccessKey
localNumber:self.tsAccountManager.localNumber
success:^{
OWSLogInfo(@"Successfully sent sync transcript.");

@ -20,6 +20,19 @@ public enum UnidentifiedAccessMode: Int {
case unrestricted
}
private func string(forUnidentifiedAccessMode mode: UnidentifiedAccessMode) -> String {
switch mode {
case .unknown:
return "unknown"
case .enabled:
return "enabled"
case .disabled:
return "disabled"
case .unrestricted:
return "unrestricted"
}
}
@objc public protocol OWSUDManager: class {
@objc func setup()
@ -28,6 +41,8 @@ public enum UnidentifiedAccessMode: Int {
@objc func isUDEnabled() -> Bool
@objc func isUDVerboseLoggingEnabled() -> Bool
// MARK: - Recipient State
@objc
@ -42,6 +57,9 @@ public enum UnidentifiedAccessMode: Int {
@objc
func udAccessKey(forRecipientId recipientId: RecipientIdentifier) -> SMKUDAccessKey?
@objc
func udSendAccessKey(forRecipientId recipientId: RecipientIdentifier) -> SMKUDAccessKey?
// MARK: Sender Certificate
// We use completion handlers instead of a promise so that message sending
@ -52,8 +70,10 @@ public enum UnidentifiedAccessMode: Int {
// MARK: Unrestricted Access
@objc func shouldAllowUnrestrictedAccessLocal() -> Bool
@objc func setShouldAllowUnrestrictedAccessLocal(_ value: Bool)
@objc
func shouldAllowUnrestrictedAccessLocal() -> Bool
@objc
func setShouldAllowUnrestrictedAccessLocal(_ value: Bool)
}
// MARK: -
@ -104,6 +124,24 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
ensureSenderCertificate().retainUntilComplete()
}
// MARK: -
@objc
public func isUDEnabled() -> Bool {
// Only enable UD if UD is supported by all linked devices,
// so that sync messages can also be sent via UD.
guard let localNumber = tsAccountManager.localNumber() else {
return false
}
let ourAccessMode = unidentifiedAccessMode(forRecipientId: localNumber)
return ourAccessMode == .enabled || ourAccessMode == .unrestricted
}
@objc
public func isUDVerboseLoggingEnabled() -> Bool {
return true
}
// MARK: - Dependencies
private var profileManager: ProfileManagerProtocol {
@ -121,9 +159,9 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
return SMKUDAccessKey(randomKeyData: ())
}
@objc
public func unidentifiedAccessMode(forRecipientId recipientId: RecipientIdentifier) -> UnidentifiedAccessMode {
guard let existingRawValue = dbConnection.object(forKey: recipientId, inCollection: kUnidentifiedAccessCollection) as? Int else {
private func unidentifiedAccessMode(forRecipientId recipientId: RecipientIdentifier,
transaction: YapDatabaseReadTransaction) -> UnidentifiedAccessMode {
guard let existingRawValue = transaction.object(forKey: recipientId, inCollection: kUnidentifiedAccessCollection) as? Int else {
return .unknown
}
guard let existingValue = UnidentifiedAccessMode(rawValue: existingRawValue) else {
@ -132,15 +170,32 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
return existingValue
}
@objc
public func unidentifiedAccessMode(forRecipientId recipientId: RecipientIdentifier) -> UnidentifiedAccessMode {
var mode: UnidentifiedAccessMode = .unknown
dbConnection.read { (transaction) in
mode = self.unidentifiedAccessMode(forRecipientId: recipientId, transaction: transaction)
}
return mode
}
@objc
public func setUnidentifiedAccessMode(_ mode: UnidentifiedAccessMode, recipientId: String) {
if let localNumber = tsAccountManager.localNumber() {
if recipientId == localNumber {
Logger.info("Setting local UD access mode: \(mode.rawValue)")
Logger.info("Setting local UD access mode: \(string(forUnidentifiedAccessMode: mode))")
}
}
dbConnection.setObject(mode.rawValue as Int, forKey: recipientId, inCollection: kUnidentifiedAccessCollection)
dbConnection.readWrite { (transaction) in
let oldMode = self.unidentifiedAccessMode(forRecipientId: recipientId, transaction: transaction)
transaction.setObject(mode.rawValue as Int, forKey: recipientId, inCollection: self.kUnidentifiedAccessCollection)
if mode != oldMode {
Logger.info("Setting UD access mode for \(recipientId): \(string(forUnidentifiedAccessMode: oldMode)) -> \(string(forUnidentifiedAccessMode: mode))")
}
}
}
// Returns the UD access key for a given recipient
@ -160,6 +215,50 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
}
}
// Returns the UD access key for sending to a given recipient.
@objc
public func udSendAccessKey(forRecipientId recipientId: RecipientIdentifier) -> SMKUDAccessKey? {
// This check is currently redundant with the "send access key for local number"
// check below, but behavior of isUDEnabled() may change.
guard isUDEnabled() else {
if isUDVerboseLoggingEnabled() {
Logger.info("UD Send disabled for \(recipientId), UD disabled.")
}
return nil
}
guard let localNumber = tsAccountManager.localNumber() else {
if isUDVerboseLoggingEnabled() {
Logger.info("UD Send disabled for \(recipientId), no local number.")
}
return nil
}
if localNumber != recipientId {
guard udSendAccessKey(forRecipientId: localNumber) != nil else {
if isUDVerboseLoggingEnabled() {
Logger.info("UD Send disabled for \(recipientId), UD disabled for sync messages.")
}
return nil
}
}
let accessMode = unidentifiedAccessMode(forRecipientId: localNumber)
if accessMode == .unrestricted {
if isUDVerboseLoggingEnabled() {
Logger.info("UD Send enabled for \(recipientId) with random key.")
}
return randomUDAccessKey()
}
guard accessMode == .enabled else {
if isUDVerboseLoggingEnabled() {
Logger.info("UD Send disabled for \(recipientId), UD not enabled for this recipient.")
}
return nil
}
if isUDVerboseLoggingEnabled() {
Logger.info("UD Send enabled for \(recipientId).")
}
return udAccessKey(forRecipientId: recipientId)
}
// MARK: - Sender Certificate
#if DEBUG
@ -257,17 +356,6 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
}
}
@objc
public func isUDEnabled() -> Bool {
// Only enable UD if UD is supported by all linked devices,
// so that sync messages can also be sent via UD.
guard let localNumber = tsAccountManager.localNumber() else {
return false
}
let ourAccessMode = unidentifiedAccessMode(forRecipientId: localNumber)
return ourAccessMode == .enabled || ourAccessMode == .unrestricted
}
@objc
public func trustRoot() -> ECPublicKey {
return OWSUDManagerImpl.trustRoot()

Loading…
Cancel
Save