Merge branch 'dev' of https://github.com/loki-project/session-ios into PN-without-preview

pull/144/head
ryanzhao 5 years ago
commit a926813b91

@ -1 +1 @@
Subproject commit f636079cbdf8e7a0b959f25917b1bcc0b64b0f0c Subproject commit 7d2822b86d1ff3bf09eb6cab2f01a03e7e214081

@ -8,8 +8,8 @@ extern NSString *const AppDelegateStoryboardMain;
@interface AppDelegate : UIResponder <UIApplicationDelegate> @interface AppDelegate : UIResponder <UIApplicationDelegate>
- (void)startLongPollerIfNeeded; - (void)startPollerIfNeeded;
- (void)stopLongPollerIfNeeded; - (void)stopPollerIfNeeded;
- (void)setUpDefaultPublicChatsIfNeeded; - (void)setUpDefaultPublicChatsIfNeeded;
- (void)startOpenGroupPollersIfNeeded; - (void)startOpenGroupPollersIfNeeded;
- (void)stopOpenGroupPollersIfNeeded; - (void)stopOpenGroupPollersIfNeeded;

@ -69,7 +69,7 @@ static BOOL isInternalTestVersion = NO;
// Loki // Loki
@property (nonatomic) LKP2PServer *lokiP2PServer; @property (nonatomic) LKP2PServer *lokiP2PServer;
@property (nonatomic) LKLongPoller *lokiLongPoller; @property (nonatomic) LKPoller *lokiPoller;
@property (nonatomic) LKRSSFeedPoller *lokiNewsFeedPoller; @property (nonatomic) LKRSSFeedPoller *lokiNewsFeedPoller;
@property (nonatomic) LKRSSFeedPoller *lokiMessengerUpdatesFeedPoller; @property (nonatomic) LKRSSFeedPoller *lokiMessengerUpdatesFeedPoller;
@ -181,7 +181,7 @@ static BOOL isInternalTestVersion = NO;
[DDLog flushLog]; [DDLog flushLog];
// Loki: Stop pollers // Loki: Stop pollers
[self stopLongPollerIfNeeded]; [self stopPollerIfNeeded];
[self stopOpenGroupPollersIfNeeded]; [self stopOpenGroupPollersIfNeeded];
} }
@ -202,7 +202,7 @@ static BOOL isInternalTestVersion = NO;
[DDLog flushLog]; [DDLog flushLog];
// Loki: Stop pollers // Loki: Stop pollers
[self stopLongPollerIfNeeded]; [self stopPollerIfNeeded];
[self stopOpenGroupPollersIfNeeded]; [self stopOpenGroupPollersIfNeeded];
if (self.lokiP2PServer) { [self.lokiP2PServer stop]; } if (self.lokiP2PServer) { [self.lokiP2PServer stop]; }
@ -786,7 +786,7 @@ static BOOL isInternalTestVersion = NO;
[LKP2PAPI broadcastOnlineStatus]; [LKP2PAPI broadcastOnlineStatus];
// Loki: Start pollers // Loki: Start pollers
[self startLongPollerIfNeeded]; [self startPollerIfNeeded];
[self startOpenGroupPollersIfNeeded]; [self startOpenGroupPollersIfNeeded];
// Loki: Get device links // Loki: Get device links
@ -1479,7 +1479,7 @@ static BOOL isInternalTestVersion = NO;
[self.lokiFriendRequestExpirationJob startIfNecessary]; [self.lokiFriendRequestExpirationJob startIfNecessary];
// Loki: Start pollers // Loki: Start pollers
[self startLongPollerIfNeeded]; [self startPollerIfNeeded];
[self startOpenGroupPollersIfNeeded]; [self startOpenGroupPollersIfNeeded];
// Loki: Get device links // Loki: Get device links
@ -1597,12 +1597,12 @@ static BOOL isInternalTestVersion = NO;
#pragma mark - Loki #pragma mark - Loki
- (void)setUpLongPollerIfNeeded - (void)setUpPollerIfNeeded
{ {
if (self.lokiLongPoller != nil) { return; } if (self.lokiPoller != nil) { return; }
NSString *userHexEncodedPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey; NSString *userHexEncodedPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
if (userHexEncodedPublicKey == nil) { return; } if (userHexEncodedPublicKey == nil) { return; }
self.lokiLongPoller = [[LKLongPoller alloc] initOnMessagesReceived:^(NSArray<SSKProtoEnvelope *> *messages) { self.lokiPoller = [[LKPoller alloc] initOnMessagesReceived:^(NSArray<SSKProtoEnvelope *> *messages) {
for (SSKProtoEnvelope *message in messages) { for (SSKProtoEnvelope *message in messages) {
NSData *data = [message serializedDataAndReturnError:nil]; NSData *data = [message serializedDataAndReturnError:nil];
if (data != nil) { if (data != nil) {
@ -1614,15 +1614,15 @@ static BOOL isInternalTestVersion = NO;
}]; }];
} }
- (void)startLongPollerIfNeeded - (void)startPollerIfNeeded
{ {
[self setUpLongPollerIfNeeded]; [self setUpPollerIfNeeded];
[self.lokiLongPoller startIfNeeded]; [self.lokiPoller startIfNeeded];
} }
- (void)stopLongPollerIfNeeded - (void)stopPollerIfNeeded
{ {
[self.lokiLongPoller stopIfNeeded]; [self.lokiPoller stopIfNeeded];
} }
- (void)setUpDefaultPublicChatsIfNeeded - (void)setUpDefaultPublicChatsIfNeeded
@ -1719,7 +1719,7 @@ static BOOL isInternalTestVersion = NO;
[SSKEnvironment.shared.messageSenderJobQueue clearAllJobs]; [SSKEnvironment.shared.messageSenderJobQueue clearAllJobs];
[SSKEnvironment.shared.identityManager clearIdentityKey]; [SSKEnvironment.shared.identityManager clearIdentityKey];
[LKAPI clearRandomSnodePool]; [LKAPI clearRandomSnodePool];
[self stopLongPollerIfNeeded]; [self stopPollerIfNeeded];
[self stopOpenGroupPollersIfNeeded]; [self stopOpenGroupPollersIfNeeded];
[self.lokiNewsFeedPoller stop]; [self.lokiNewsFeedPoller stop];
[self.lokiMessengerUpdatesFeedPoller stop]; [self.lokiMessengerUpdatesFeedPoller stop];

@ -5,5 +5,19 @@ class BaseVC : UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
setNeedsStatusBarAppearanceUpdate() setNeedsStatusBarAppearanceUpdate()
NotificationCenter.default.addObserver(self, selector: #selector(handleUnexpectedDeviceLinkRequestReceivedNotification), name: .unexpectedDeviceLinkRequestReceived, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc private func handleUnexpectedDeviceLinkRequestReceivedNotification() {
guard DeviceLinkingUtilities.shouldShowUnexpectedDeviceLinkRequestReceivedAlert else { return }
DispatchQueue.main.async {
let alert = UIAlertController(title: "Device Link Request Received", message: "Open the device link screen by going to \"Settings\"> \"Devices\" > \"Link a Device\" to link your devices.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
} }
} }

@ -42,7 +42,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
private lazy var subtitleLabel: UILabel = { private lazy var subtitleLabel: UILabel = {
let result = UILabel() let result = UILabel()
result.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity) result.textColor = Colors.text
result.font = .systemFont(ofSize: Values.smallFontSize) result.font = .systemFont(ofSize: Values.smallFontSize)
result.numberOfLines = 0 result.numberOfLines = 0
result.lineBreakMode = .byWordWrapping result.lineBreakMode = .byWordWrapping
@ -131,7 +131,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
}() }()
subtitleLabel.text = { subtitleLabel.text = {
switch mode { switch mode {
case .master: return NSLocalizedString("Open Session on your secondary device and tap \"Link to an existing account\"", comment: "") case .master: return NSLocalizedString("Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first.", comment: "")
case .slave: return NSLocalizedString("Please check that the words below match those shown on your other device", comment: "") case .slave: return NSLocalizedString("Please check that the words below match those shown on your other device", comment: "")
} }
}() }()

@ -155,7 +155,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
TSAccountManager.sharedInstance().phoneNumberAwaitingVerification = keyPair.hexEncodedPublicKey TSAccountManager.sharedInstance().phoneNumberAwaitingVerification = keyPair.hexEncodedPublicKey
TSAccountManager.sharedInstance().didRegister() TSAccountManager.sharedInstance().didRegister()
let appDelegate = UIApplication.shared.delegate as! AppDelegate let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.startLongPollerIfNeeded() appDelegate.startPollerIfNeeded()
let deviceLinkingModal = DeviceLinkingModal(mode: .slave, delegate: self) let deviceLinkingModal = DeviceLinkingModal(mode: .slave, delegate: self)
deviceLinkingModal.modalPresentationStyle = .overFullScreen deviceLinkingModal.modalPresentationStyle = .overFullScreen
deviceLinkingModal.modalTransitionStyle = .crossDissolve deviceLinkingModal.modalTransitionStyle = .crossDissolve
@ -176,7 +176,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
func handleDeviceLinkingModalDismissed() { func handleDeviceLinkingModalDismissed() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.stopLongPollerIfNeeded() appDelegate.stopPollerIfNeeded()
TSAccountManager.sharedInstance().resetForReregistration() TSAccountManager.sharedInstance().resetForReregistration()
} }

@ -33,7 +33,7 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon
}() }()
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = { private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
let message = NSLocalizedString("Link to your existing account by going into your in-app settings and clicking \"Devices\".", comment: "") let message = NSLocalizedString("Navigate to \"Settings\" > \"Devices\" > \"Link a Device\" on your other device and then scan the QR code that comes up to start the linking process.", comment: "")
let result = ScanQRCodeWrapperVC(message: message) let result = ScanQRCodeWrapperVC(message: message)
result.delegate = self result.delegate = self
return result return result
@ -167,7 +167,7 @@ private final class EnterPublicKeyVC : UIViewController {
let explanationLabel = UILabel() let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize) explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "Enter your Session ID to start the linking process." explanationLabel.text = "Navigate to \"Settings\" > \"Devices\" > \"Link a Device\" on your other device and then enter your Session ID here to start the linking process."
explanationLabel.numberOfLines = 0 explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping explanationLabel.lineBreakMode = .byWordWrapping
// Link button // Link button

@ -444,6 +444,11 @@ typedef enum : NSUInteger {
selector:@selector(handleMessageFailedNotification:) selector:@selector(handleMessageFailedNotification:)
name:NSNotification.messageFailed name:NSNotification.messageFailed
object:nil]; object:nil];
// Device linking
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleUnexpectedDeviceLinkRequestReceivedNotification)
name:NSNotification.unexpectedDeviceLinkRequestReceived
object:nil];
} }
- (BOOL)isGroupConversation - (BOOL)isGroupConversation
@ -5479,6 +5484,16 @@ typedef enum : NSUInteger {
}); });
} }
- (void)handleUnexpectedDeviceLinkRequestReceivedNotification
{
if (!LKDeviceLinkingUtilities.shouldShowUnexpectedDeviceLinkRequestReceivedAlert) { return; }
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Device Link Request Received" message:@"Open the device link screen by going to \"Settings\"> \"Devices\" > \"Link a Device\" to link your devices." preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
});
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -681,7 +681,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
[SSKEnvironment.shared.identityManager clearIdentityKey]; [SSKEnvironment.shared.identityManager clearIdentityKey];
[LKAPI clearRandomSnodePool]; [LKAPI clearRandomSnodePool];
AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate; AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
[appDelegate stopLongPollerIfNeeded]; [appDelegate stopPollerIfNeeded];
[appDelegate stopOpenGroupPollersIfNeeded]; [appDelegate stopOpenGroupPollersIfNeeded];
[SSKEnvironment.shared.tsAccountManager resetForReregistration]; [SSKEnvironment.shared.tsAccountManager resetForReregistration];
UIViewController *rootViewController = [[OnboardingController new] initialViewController]; UIViewController *rootViewController = [[OnboardingController new] initialViewController];

@ -2768,7 +2768,7 @@
"Link to an existing account" = "Link to an existing account"; "Link to an existing account" = "Link to an existing account";
"Enter your public key" = "Enter your public key"; "Enter your public key" = "Enter your public key";
"Link to your existing account by going into your in-app settings and clicking \"Devices\"." = "Link to your existing account by going into your in-app settings and clicking \"Devices\"."; "Link to your existing account by going into your in-app settings and clicking \"Devices\"." = "Link to your existing account by going into your in-app settings and clicking \"Devices\".";
"Open Session on your secondary device and tap \"Link to an existing account\"" = "Open Session on your secondary device and tap \"Link to an existing account\""; "Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first." = "Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first.";
"Group Settings" = "Group Settings"; "Group Settings" = "Group Settings";
"Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design." = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design."; "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design." = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
"Enter the recovery phrase that was given to you when you signed up to restore your account." = "Enter the recovery phrase that was given to you when you signed up to restore your account."; "Enter the recovery phrase that was given to you when you signed up to restore your account." = "Enter the recovery phrase that was given to you when you signed up to restore your account.";

@ -1,20 +1,16 @@
import PromiseKit import PromiseKit
@objc(LKLongPoller) @objc(LKPoller)
public final class LokiLongPoller : NSObject { public final class LokiPoller : NSObject {
private let onMessagesReceived: ([SSKProtoEnvelope]) -> Void private let onMessagesReceived: ([SSKProtoEnvelope]) -> Void
private let storage = OWSPrimaryStorage.shared() private let storage = OWSPrimaryStorage.shared()
private var hasStarted = false private var hasStarted = false
private var hasStopped = false private var hasStopped = false
private var connections = Set<Promise<Void>>()
private var usedSnodes = Set<LokiAPITarget>() private var usedSnodes = Set<LokiAPITarget>()
// MARK: Settings // MARK: Settings
private let connectionCount = 3 private static let pollInterval: TimeInterval = 1
private let retryInterval: TimeInterval = 4 private static let retryInterval: TimeInterval = 4
// MARK: Convenience
private var userHexEncodedPublicKey: String { return getUserHexEncodedPublicKey() }
// MARK: Initialization // MARK: Initialization
@objc public init(onMessagesReceived: @escaping ([SSKProtoEnvelope]) -> Void) { @objc public init(onMessagesReceived: @escaping ([SSKProtoEnvelope]) -> Void) {
@ -25,7 +21,7 @@ public final class LokiLongPoller : NSObject {
// MARK: Public API // MARK: Public API
@objc public func startIfNeeded() { @objc public func startIfNeeded() {
guard !hasStarted else { return } guard !hasStarted else { return }
print("[Loki] Started long polling.") print("[Loki] Started polling.")
hasStarted = true hasStarted = true
hasStopped = false hasStopped = false
openConnections() openConnections()
@ -33,7 +29,7 @@ public final class LokiLongPoller : NSObject {
@objc public func stopIfNeeded() { @objc public func stopIfNeeded() {
guard !hasStopped else { return } guard !hasStopped else { return }
print("[Loki] Stopped long polling.") print("[Loki] Stopped polling.")
hasStarted = false hasStarted = false
hasStopped = true hasStopped = true
usedSnodes.removeAll() usedSnodes.removeAll()
@ -42,49 +38,46 @@ public final class LokiLongPoller : NSObject {
// MARK: Private API // MARK: Private API
private func openConnections() { private func openConnections() {
guard !hasStopped else { return } guard !hasStopped else { return }
LokiAPI.getSwarm(for: userHexEncodedPublicKey).then { [weak self] _ -> Guarantee<[Result<Void>]> in LokiAPI.getSwarm(for: getUserHexEncodedPublicKey()).then { [weak self] _ -> Promise<Void> in
guard let strongSelf = self else { return Guarantee.value([Result<Void>]()) } guard let strongSelf = self else { return Promise { $0.fulfill(()) } }
strongSelf.usedSnodes.removeAll() strongSelf.usedSnodes.removeAll()
let connections: [Promise<Void>] = (0..<strongSelf.connectionCount).map { _ in let (promise, seal) = Promise<Void>.pending()
let (promise, seal) = Promise<Void>.pending() strongSelf.pollNextSnode(seal: seal)
strongSelf.openConnectionToNextSnode(seal: seal) return promise
return promise
}
strongSelf.connections = Set(connections)
return when(resolved: connections)
}.ensure { [weak self] in }.ensure { [weak self] in
guard let strongSelf = self else { return } guard let strongSelf = self else { return }
Timer.scheduledTimer(withTimeInterval: strongSelf.retryInterval, repeats: false) { _ in Timer.scheduledTimer(withTimeInterval: LokiPoller.retryInterval, repeats: false) { _ in
guard let strongSelf = self else { return } guard let strongSelf = self else { return }
strongSelf.openConnections() strongSelf.openConnections()
} }
} }
} }
private func openConnectionToNextSnode(seal: Resolver<Void>) { private func pollNextSnode(seal: Resolver<Void>) {
let userHexEncodedPublicKey = getUserHexEncodedPublicKey()
let swarm = LokiAPI.swarmCache[userHexEncodedPublicKey] ?? [] let swarm = LokiAPI.swarmCache[userHexEncodedPublicKey] ?? []
let userHexEncodedPublicKey = self.userHexEncodedPublicKey
let unusedSnodes = Set(swarm).subtracting(usedSnodes) let unusedSnodes = Set(swarm).subtracting(usedSnodes)
if !unusedSnodes.isEmpty { if !unusedSnodes.isEmpty {
// randomElement() uses the system's default random generator, which is cryptographically secure
let nextSnode = unusedSnodes.randomElement()! let nextSnode = unusedSnodes.randomElement()!
usedSnodes.insert(nextSnode) usedSnodes.insert(nextSnode)
print("[Loki] Opening long polling connection to \(nextSnode).") print("[Loki] Polling \(nextSnode).")
longPoll(nextSnode, seal: seal).catch(on: LokiAPI.errorHandlingQueue) { [weak self] error in poll(nextSnode, seal: seal).catch(on: LokiAPI.errorHandlingQueue) { [weak self] error in
print("[Loki] Long polling connection to \(nextSnode) failed; dropping it and switching to next snode.") print("[Loki] Polling \(nextSnode) failed; dropping it and switching to next snode.")
LokiAPI.dropIfNeeded(nextSnode, hexEncodedPublicKey: userHexEncodedPublicKey) LokiAPI.dropIfNeeded(nextSnode, hexEncodedPublicKey: userHexEncodedPublicKey)
self?.openConnectionToNextSnode(seal: seal) self?.pollNextSnode(seal: seal)
} }
} else { } else {
seal.fulfill(()) seal.fulfill(())
} }
} }
private func longPoll(_ target: LokiAPITarget, seal: Resolver<Void>) -> Promise<Void> { private func poll(_ target: LokiAPITarget, seal: Resolver<Void>) -> Promise<Void> {
return LokiAPI.getRawMessages(from: target, usingLongPolling: true).then(on: DispatchQueue.global()) { [weak self] rawResponse -> Promise<Void> in return LokiAPI.getRawMessages(from: target, usingLongPolling: false).then(on: DispatchQueue.global()) { [weak self] rawResponse -> Promise<Void> in
guard let strongSelf = self, !strongSelf.hasStopped else { return Promise.value(()) } guard let strongSelf = self, !strongSelf.hasStopped else { return Promise.value(()) }
let messages = LokiAPI.parseRawMessagesResponse(rawResponse, from: target) let messages = LokiAPI.parseRawMessagesResponse(rawResponse, from: target)
strongSelf.onMessagesReceived(messages) strongSelf.onMessagesReceived(messages)
return strongSelf.longPoll(target, seal: seal) return strongSelf.poll(target, seal: seal)
} }
} }
} }

@ -1,6 +1,19 @@
public enum DeviceLinkingUtilities { @objc(LKDeviceLinkingUtilities)
public final class DeviceLinkingUtilities : NSObject {
private static var lastUnexpectedDeviceLinkRequestDate: Date? = nil
private override init() { }
@objc public static var shouldShowUnexpectedDeviceLinkRequestReceivedAlert: Bool {
let now = Date()
if let lastUnexpectedDeviceLinkRequestDate = lastUnexpectedDeviceLinkRequestDate {
if now.timeIntervalSince(lastUnexpectedDeviceLinkRequestDate) < 30 { return false }
}
lastUnexpectedDeviceLinkRequestDate = now
return true
}
// When requesting a device link, the slave device signs the master device's public key. When authorizing // When requesting a device link, the slave device signs the master device's public key. When authorizing
// a device link, the master device signs the slave device's public key. // a device link, the master device signs the slave device's public key.

@ -17,6 +17,8 @@ public extension Notification.Name {
public static let seedViewed = Notification.Name("seedViewed") public static let seedViewed = Notification.Name("seedViewed")
// Interaction // Interaction
public static let dataNukeRequested = Notification.Name("dataNukeRequested") public static let dataNukeRequested = Notification.Name("dataNukeRequested")
// Device linking
public static let unexpectedDeviceLinkRequestReceived = Notification.Name("unexpectedDeviceLinkRequestReceived")
} }
@objc public extension NSNotification { @objc public extension NSNotification {
@ -37,4 +39,6 @@ public extension Notification.Name {
@objc public static let seedViewed = Notification.Name.seedViewed.rawValue as NSString @objc public static let seedViewed = Notification.Name.seedViewed.rawValue as NSString
// Interaction // Interaction
@objc public static let dataNukeRequested = Notification.Name.dataNukeRequested.rawValue as NSString @objc public static let dataNukeRequested = Notification.Name.dataNukeRequested.rawValue as NSString
// Device linking
@objc public static let unexpectedDeviceLinkRequestReceived = Notification.Name.unexpectedDeviceLinkRequestReceived.rawValue as NSString
} }

@ -494,6 +494,9 @@ NS_ASSUME_NONNULL_BEGIN
} }
} else if (slaveSignature != nil) { // Request } else if (slaveSignature != nil) { // Request
OWSLogInfo(@"[Loki] Received a device linking request from: %@", envelope.source); // Not slaveHexEncodedPublicKey OWSLogInfo(@"[Loki] Received a device linking request from: %@", envelope.source); // Not slaveHexEncodedPublicKey
if (LKDeviceLinkingSession.current == nil) {
[NSNotificationCenter.defaultCenter postNotificationName:NSNotification.unexpectedDeviceLinkRequestReceived object:nil];
}
[LKDeviceLinkingSession.current processLinkingRequestFrom:slaveHexEncodedPublicKey to:masterHexEncodedPublicKey with:slaveSignature]; [LKDeviceLinkingSession.current processLinkingRequestFrom:slaveHexEncodedPublicKey to:masterHexEncodedPublicKey with:slaveSignature];
} }
} else if (contentProto.syncMessage) { } else if (contentProto.syncMessage) {

Loading…
Cancel
Save