From 40169334ff4ec77a1616b07a533ec697855a51ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Thu, 1 Jan 2026 12:03:50 +0100 Subject: [PATCH] Fix connection drop for larger files --- NearbyShare/Connection/NearbyConnection.swift | 26 ++++++++++++------- QuickDrop.xcodeproj/project.pbxproj | 8 +++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/NearbyShare/Connection/NearbyConnection.swift b/NearbyShare/Connection/NearbyConnection.swift index d93fe25..ed4dde7 100644 --- a/NearbyShare/Connection/NearbyConnection.swift +++ b/NearbyShare/Connection/NearbyConnection.swift @@ -38,7 +38,10 @@ class NearbyConnection { private var connectionClosed: Bool = false private var inactivityTimer: DispatchSourceTimer? - private let timeoutInterval: TimeInterval = 30 + + private let ackInterval: TimeInterval = 5 + private let ackTimeoutInterval: TimeInterval = 30 + private var lastKeepAliveFrameSent = Date() // UKEY2-related state var privateKey: ECPrivateKey? @@ -429,11 +432,6 @@ class NearbyConnection { } } else if offlineFrame.hasV1, offlineFrame.v1.hasType, case .keepAlive = offlineFrame.v1.type { - - let bytesTransferred = self.bytesTransferred - let gigabytesTransferred = Double(bytesTransferred) / 1_000_000_000 - - log("[NearbyConnection \(self.id)] Sent keep-alive, \(self.bytesTransferred) bytes (\(gigabytesTransferred) GB) sent") sendKeepAlive(ack: true) } else { @@ -588,25 +586,33 @@ class NearbyConnection { } else { try sendFrameAsync(offlineFrame.serializedData()) } + + self.lastKeepAliveFrameSent = Date() } catch { log("[NearbyConnection \(self.id)] Error sending KEEP_ALIVE: \(error)") } + + log("[NearbyConnection \(self.id)] Sent keep-alive \(ack ? "ack" : "no ack"), \(self.bytesTransferred) bytes (\(Double(bytesTransferred) / 1_000_000_000) GB) sent") } func startAndResetHeartbeatTimer() { + if lastKeepAliveFrameSent.isOlderThan(seconds: ackInterval) { + sendKeepAlive(ack: false) + } + // Cancel previous timer if any inactivityTimer?.cancel() inactivityTimer = DispatchSource.makeTimerSource(queue: NearbyConnection.dispatchQueue) - inactivityTimer?.schedule(deadline: .now() + timeoutInterval) + inactivityTimer?.schedule(deadline: .now() + ackTimeoutInterval) inactivityTimer?.setEventHandler { [weak self] in guard let self = self else { return } if !self.connectionClosed { - log("[NearbyConnection \(self.id)] Connection timeout: No message received in \(self.timeoutInterval) seconds") + log("[NearbyConnection \(self.id)] Connection timeout: No message received in \(self.ackTimeoutInterval) seconds") self.lastError = NearbyError.canceled(reason: .timedOut) self.disconnect() } @@ -617,7 +623,7 @@ class NearbyConnection { func startDataTransferTimer(previousBytesTransferred: Int64) { - NearbyConnection.dispatchQueue.asyncAfter(deadline: .now() + timeoutInterval) { + NearbyConnection.dispatchQueue.asyncAfter(deadline: .now() + ackTimeoutInterval) { if previousBytesTransferred < self.bytesTransferred { // everything good, transferred more than last check, schedule next check @@ -626,7 +632,7 @@ class NearbyConnection { else { // connection stale, need to abort if !self.connectionClosed { - log("[NearbyConnection \(self.id)] Connection timeout: No more data received in \(self.timeoutInterval) seconds") + log("[NearbyConnection \(self.id)] Connection timeout: No more data received in \(self.ackTimeoutInterval) seconds") self.lastError = NearbyError.canceled(reason: .timedOut) self.disconnect() } diff --git a/QuickDrop.xcodeproj/project.pbxproj b/QuickDrop.xcodeproj/project.pbxproj index 244d51e..236e5a1 100644 --- a/QuickDrop.xcodeproj/project.pbxproj +++ b/QuickDrop.xcodeproj/project.pbxproj @@ -1733,8 +1733,8 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; - SHARED_BUILD = 106; - SHARED_VERSION = 2.10.1; + SHARED_BUILD = 107; + SHARED_VERSION = 2.10.3; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1796,8 +1796,8 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; - SHARED_BUILD = 106; - SHARED_VERSION = 2.10.1; + SHARED_BUILD = 107; + SHARED_VERSION = 2.10.3; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES;