Network Type Transition Optimization
Nucleic-Session: 40F8C53A-F001-423A-8607-EAE181DBE14B Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -28,7 +28,15 @@ final class NWFrameChannel: FrameChannel, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(endpoint: NWEndpoint) {
|
init(endpoint: NWEndpoint) {
|
||||||
let params = NWParameters.tcp
|
// Short TCP keepalive so a silently-dead LAN link (Wi-Fi dropped, Mac left the subnet) is
|
||||||
|
// detected in ~15s instead of the OS default of minutes — the belt to the path-monitor's
|
||||||
|
// braces for the case where a path still exists but the route to the Mac is gone.
|
||||||
|
let tcp = NWProtocolTCP.Options()
|
||||||
|
tcp.enableKeepalive = true
|
||||||
|
tcp.keepaliveIdle = 5
|
||||||
|
tcp.keepaliveInterval = 5
|
||||||
|
tcp.keepaliveCount = 2
|
||||||
|
let params = NWParameters(tls: nil, tcp: tcp)
|
||||||
params.includePeerToPeer = true
|
params.includePeerToPeer = true
|
||||||
connection = NWConnection(to: endpoint, using: params)
|
connection = NWConnection(to: endpoint, using: params)
|
||||||
peerDescription = "\(endpoint)"
|
peerDescription = "\(endpoint)"
|
||||||
@@ -39,6 +47,13 @@ final class NWFrameChannel: FrameChannel, @unchecked Sendable {
|
|||||||
connection.stateUpdateHandler = { [weak self] state in
|
connection.stateUpdateHandler = { [weak self] state in
|
||||||
switch state {
|
switch state {
|
||||||
case .ready: self?.markReady(); self?.onReady?()
|
case .ready: self?.markReady(); self?.onReady?()
|
||||||
|
case .waiting(let error):
|
||||||
|
// No usable path right now (Wi-Fi dropped, host unreachable). NWConnection would sit
|
||||||
|
// in `.waiting` indefinitely, holding the transport hostage — the core of the "still
|
||||||
|
// on LAN after leaving Wi-Fi" stall. Fail fast so the store falls straight through to
|
||||||
|
// tailnet/relay. (Healthy connections go setup→preparing→ready and never hit this;
|
||||||
|
// the connect-timeout guard covers a wrong-network socket that stays `.preparing`.)
|
||||||
|
self?.onFailed?("waiting: \(error)"); self?.continuation.finish()
|
||||||
case .failed(let error): self?.onFailed?("\(error)"); self?.continuation.finish()
|
case .failed(let error): self?.onFailed?("\(error)"); self?.continuation.finish()
|
||||||
case .cancelled: self?.continuation.finish()
|
case .cancelled: self?.continuation.finish()
|
||||||
default: break
|
default: break
|
||||||
|
|||||||
Reference in New Issue
Block a user