Changed the networking logic to suspend/resume rather than just cancel connections

pull/976/head
Morgan Pretty 1 month ago
parent b0eec5a4c2
commit 6cb9294143

@ -197,7 +197,7 @@ public final class SessionCallManager: NSObject, CallManagerProtocol {
// Stop all jobs except for message sending and when completed suspend the database // Stop all jobs except for message sending and when completed suspend the database
JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend, using: dependencies) { JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend, using: dependencies) {
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()
} }

@ -147,6 +147,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
UNUserNotificationCenter.current().delegate = self UNUserNotificationCenter.current().delegate = self
Storage.resumeDatabaseAccess() Storage.resumeDatabaseAccess()
LibSession.resumeNetworkAccess()
// Reset the 'startTime' (since it would be invalid from the last launch) // Reset the 'startTime' (since it would be invalid from the last launch)
startTime = CACurrentMediaTime() startTime = CACurrentMediaTime()
@ -211,7 +212,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// Stop all jobs except for message sending and when completed suspend the database // Stop all jobs except for message sending and when completed suspend the database
JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend, using: dependencies) { JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend, using: dependencies) {
if !self.hasCallOngoing() { if !self.hasCallOngoing() {
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.info("[AppDelegate] completed network and database shutdowns.") Log.info("[AppDelegate] completed network and database shutdowns.")
Log.flush() Log.flush()
@ -281,6 +282,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
Storage.resumeDatabaseAccess() Storage.resumeDatabaseAccess()
LibSession.resumeNetworkAccess()
// Background tasks only last for a certain amount of time (which can result in a crash and a // Background tasks only last for a certain amount of time (which can result in a crash and a
// prompt appearing for the user), we want to avoid this and need to make sure to suspend the // prompt appearing for the user), we want to avoid this and need to make sure to suspend the
@ -298,7 +300,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
BackgroundPoller.isValid = false BackgroundPoller.isValid = false
if Singleton.hasAppContext && Singleton.appContext.isInBackground { if Singleton.hasAppContext && Singleton.appContext.isInBackground {
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()
} }
@ -325,7 +327,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
BackgroundPoller.isValid = false BackgroundPoller.isValid = false
if Singleton.hasAppContext && Singleton.appContext.isInBackground { if Singleton.hasAppContext && Singleton.appContext.isInBackground {
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()
} }

@ -114,7 +114,7 @@ public struct SessionApp {
public static func resetAppData(onReset: (() -> ())? = nil) { public static func resetAppData(onReset: (() -> ())? = nil) {
LibSession.clearMemoryState() LibSession.clearMemoryState()
LibSession.clearSnodeCache() LibSession.clearSnodeCache()
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.resetAllStorage() Storage.resetAllStorage()
ProfileManager.resetProfileStorage() ProfileManager.resetProfileStorage()
Attachment.resetAttachmentStorage() Attachment.resetAttachmentStorage()

@ -287,6 +287,7 @@ public enum PushRegistrationError: Error {
} }
Storage.resumeDatabaseAccess() Storage.resumeDatabaseAccess()
LibSession.resumeNetworkAccess()
let maybeCall: SessionCall? = Storage.shared.write { db in let maybeCall: SessionCall? = Storage.shared.write { db in
let messageInfo: CallMessage.MessageInfo = CallMessage.MessageInfo( let messageInfo: CallMessage.MessageInfo = CallMessage.MessageInfo(

@ -51,6 +51,7 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
// Perform main setup // Perform main setup
Storage.resumeDatabaseAccess() Storage.resumeDatabaseAccess()
LibSession.resumeNetworkAccess()
DispatchQueue.main.sync { self.setUpIfNecessary() { } } DispatchQueue.main.sync { self.setUpIfNecessary() { } }
// Handle the push notification // Handle the push notification
@ -349,7 +350,7 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
.map { NSNumber(value: $0) } .map { NSNumber(value: $0) }
.defaulting(to: NSNumber(value: 0)) .defaulting(to: NSNumber(value: 0))
Log.info("Complete silently.") Log.info("Complete silently.")
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()
@ -416,7 +417,7 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
private func handleFailure(for content: UNMutableNotificationContent, error: NotificationError) { private func handleFailure(for content: UNMutableNotificationContent, error: NotificationError) {
Log.error("Show generic failure message due to error: \(error).") Log.error("Show generic failure message due to error: \(error).")
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()

@ -100,7 +100,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
// When the thread picker disappears it means the user has left the screen (this will be called // When the thread picker disappears it means the user has left the screen (this will be called
// whether the user has sent the message or cancelled sending) // whether the user has sent the message or cancelled sending)
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()
} }
@ -229,6 +229,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
ModalActivityIndicatorViewController.present(fromViewController: shareNavController!, canCancel: false, message: "vc_share_sending_message".localized()) { activityIndicator in ModalActivityIndicatorViewController.present(fromViewController: shareNavController!, canCancel: false, message: "vc_share_sending_message".localized()) { activityIndicator in
Storage.resumeDatabaseAccess() Storage.resumeDatabaseAccess()
LibSession.resumeNetworkAccess()
let swarmPublicKey: String = { let swarmPublicKey: String = {
switch threadVariant { switch threadVariant {
@ -314,7 +315,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sinkUntilComplete( .sinkUntilComplete(
receiveCompletion: { [weak self] result in receiveCompletion: { [weak self] result in
LibSession.closeNetworkConnections() LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess() Storage.suspendDatabaseAccess()
Log.flush() Log.flush()
activityIndicator.dismiss { } activityIndicator.dismiss { }

@ -12,6 +12,7 @@ import SessionUtilitiesKit
public extension LibSession { public extension LibSession {
private static var networkCache: Atomic<UnsafeMutablePointer<network_object>?> = Atomic(nil) private static var networkCache: Atomic<UnsafeMutablePointer<network_object>?> = Atomic(nil)
private static var snodeCachePath: String { "\(OWSFileSystem.appSharedDataDirectoryPath())/snodeCache" } private static var snodeCachePath: String { "\(OWSFileSystem.appSharedDataDirectoryPath())/snodeCache" }
private static var isSuspended: Atomic<Bool> = Atomic(false)
private static var lastPaths: Atomic<[[Snode]]> = Atomic([]) private static var lastPaths: Atomic<[[Snode]]> = Atomic([])
private static var lastNetworkStatus: Atomic<NetworkStatus> = Atomic(.unknown) private static var lastNetworkStatus: Atomic<NetworkStatus> = Atomic(.unknown)
private static var pathsChangedCallbacks: Atomic<[UUID: ([[Snode]], UUID) -> ()]> = Atomic([:]) private static var pathsChangedCallbacks: Atomic<[UUID: ([[Snode]], UUID) -> ()]> = Atomic([:])
@ -114,12 +115,18 @@ public extension LibSession {
pathsChangedCallbacks.mutate { $0.removeValue(forKey: callbackId) } pathsChangedCallbacks.mutate { $0.removeValue(forKey: callbackId) }
} }
static func closeNetworkConnections() { static func suspendNetworkAccess() {
isSuspended.mutate { $0 = true }
guard let network: UnsafeMutablePointer<network_object> = networkCache.wrappedValue else { return } guard let network: UnsafeMutablePointer<network_object> = networkCache.wrappedValue else { return }
network_close_connections(network) network_close_connections(network)
} }
static func resumeNetworkAccess() {
isSuspended.mutate { $0 = false }
}
static func clearSnodeCache() { static func clearSnodeCache() {
guard let network: UnsafeMutablePointer<network_object> = networkCache.wrappedValue else { return } guard let network: UnsafeMutablePointer<network_object> = networkCache.wrappedValue else { return }
@ -329,6 +336,11 @@ public extension LibSession {
// MARK: - Internal Functions // MARK: - Internal Functions
private static func getOrCreateNetwork() -> AnyPublisher<UnsafeMutablePointer<network_object>?, Error> { private static func getOrCreateNetwork() -> AnyPublisher<UnsafeMutablePointer<network_object>?, Error> {
guard !isSuspended.wrappedValue else {
Log.warn("[LibSession] Attempted to access suspended network.")
return Fail(error: NetworkError.suspended).eraseToAnyPublisher()
}
guard networkCache.wrappedValue == nil else { guard networkCache.wrappedValue == nil else {
return Just(networkCache.wrappedValue) return Just(networkCache.wrappedValue)
.setFailureType(to: Error.self) .setFailureType(to: Error.self)

@ -15,6 +15,7 @@ public enum NetworkError: LocalizedError, Equatable {
case badRequest(error: String, rawData: Data?) case badRequest(error: String, rawData: Data?)
case requestFailed(error: String, rawData: Data?) case requestFailed(error: String, rawData: Data?)
case timeout case timeout
case suspended
case unknown case unknown
public var errorDescription: String? { public var errorDescription: String? {
@ -27,6 +28,7 @@ public enum NetworkError: LocalizedError, Equatable {
case .unauthorised: return "Unauthorised (Failed to verify the signature)." case .unauthorised: return "Unauthorised (Failed to verify the signature)."
case .badRequest(let error, _), .requestFailed(let error, _): return error case .badRequest(let error, _), .requestFailed(let error, _): return error
case .timeout: return "The request timed out." case .timeout: return "The request timed out."
case .suspended: return "Network requests are suspended."
case .unknown: return "An unknown error occurred." case .unknown: return "An unknown error occurred."
} }
} }

Loading…
Cancel
Save