Merge branch 'unexpected-ping-timeout'
This commit is contained in:
commit
2625cec278
|
@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Fixed
|
||||
|
||||
- Tunnel dying on idle or device locked. [#138](https://github.com/passepartoutvpn/tunnelkit/issues/138)
|
||||
- Keep-alive pings coalescing over time.
|
||||
- Ping timeout not checked for if keep-alive is disabled.
|
||||
|
||||
## 2.2.0 (2019-12-11)
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -57,6 +57,9 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
|
|||
/// The maximum number of lines in the log.
|
||||
public var maxLogLines = 1000
|
||||
|
||||
/// The log level when `OpenVPNTunnelProvider.Configuration.shouldDebug` is enabled.
|
||||
public var debugLogLevel: SwiftyBeaver.Level = .debug
|
||||
|
||||
/// The number of milliseconds after which a DNS resolution fails.
|
||||
public var dnsTimeout = 3000
|
||||
|
||||
|
@ -89,7 +92,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
|
|||
|
||||
private let observer = InterfaceObserver()
|
||||
|
||||
private let tunnelQueue = DispatchQueue(label: OpenVPNTunnelProvider.description())
|
||||
private let tunnelQueue = DispatchQueue(label: OpenVPNTunnelProvider.description(), qos: .utility)
|
||||
|
||||
private let prngSeedLength = 64
|
||||
|
||||
|
@ -294,6 +297,17 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
|
|||
}
|
||||
completionHandler?(response)
|
||||
}
|
||||
|
||||
// MARK: Wake/Sleep (debugging placeholders)
|
||||
|
||||
open override func wake() {
|
||||
log.verbose("Wake signal received")
|
||||
}
|
||||
|
||||
open override func sleep(completionHandler: @escaping () -> Void) {
|
||||
log.verbose("Sleep signal received")
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
// MARK: Connection (tunnel queue)
|
||||
|
||||
|
@ -772,7 +786,7 @@ extension OpenVPNTunnelProvider {
|
|||
// MARK: Logging
|
||||
|
||||
private func configureLogging(debug: Bool, customFormat: String? = nil) {
|
||||
let logLevel: SwiftyBeaver.Level = (debug ? .debug : .info)
|
||||
let logLevel: SwiftyBeaver.Level = (debug ? debugLogLevel : .info)
|
||||
let logFormat = customFormat ?? "$Dyyyy-MM-dd HH:mm:ss.SSS$d $L $N.$F:$l - $M"
|
||||
|
||||
if debug {
|
||||
|
|
|
@ -53,6 +53,8 @@ extension CoreConfiguration {
|
|||
|
||||
static let pushRequestInterval = 2.0
|
||||
|
||||
static let pingTimeoutCheckInterval = 10.0
|
||||
|
||||
static let pingTimeout = 120.0
|
||||
|
||||
static let retransmissionLimit = 0.1
|
||||
|
|
|
@ -160,7 +160,7 @@ public class OpenVPNSession: Session {
|
|||
|
||||
private var lastPing: BidirectionalState<Date>
|
||||
|
||||
private var isStopping: Bool
|
||||
private(set) var isStopping: Bool
|
||||
|
||||
/// The optional reason why the session stopped.
|
||||
public private(set) var stopError: Error?
|
||||
|
@ -407,6 +407,8 @@ public class OpenVPNSession: Session {
|
|||
}
|
||||
if let error = error {
|
||||
log.error("Failed LINK read: \(error)")
|
||||
|
||||
// XXX: why isn't the tunnel shutting down at this point?
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -428,7 +430,7 @@ public class OpenVPNSession: Session {
|
|||
}
|
||||
|
||||
if let packets = newPackets, !packets.isEmpty {
|
||||
// log.verbose("Received \(packets.count) packets from \(self.tunnelName)")
|
||||
// log.verbose("Received \(packets.count) packets from TUN")
|
||||
self?.receiveTunnel(packets: packets)
|
||||
}
|
||||
}
|
||||
|
@ -437,6 +439,7 @@ public class OpenVPNSession: Session {
|
|||
// Ruby: recv_link
|
||||
private func receiveLink(packets: [Data]) {
|
||||
guard shouldHandlePackets() else {
|
||||
log.warning("Discarding \(packets.count) LINK packets (should not handle)")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -536,46 +539,46 @@ public class OpenVPNSession: Session {
|
|||
// Ruby: recv_tun
|
||||
private func receiveTunnel(packets: [Data]) {
|
||||
guard shouldHandlePackets() else {
|
||||
log.warning("Discarding \(packets.count) TUN packets (should not handle)")
|
||||
return
|
||||
}
|
||||
sendDataPackets(packets)
|
||||
lastPing.outbound = Date()
|
||||
}
|
||||
|
||||
// Ruby: ping
|
||||
private func ping() {
|
||||
guard (currentKey?.controlState == .connected) else {
|
||||
guard currentKey?.controlState == .connected else {
|
||||
return
|
||||
}
|
||||
|
||||
let now = Date()
|
||||
guard (now.timeIntervalSince(lastPing.inbound) <= keepAliveTimeout) else {
|
||||
guard now.timeIntervalSince(lastPing.inbound) <= keepAliveTimeout else {
|
||||
deferStop(.shutdown, OpenVPNError.pingTimeout)
|
||||
return
|
||||
}
|
||||
|
||||
// postpone ping if elapsed less than keep-alive
|
||||
if let interval = keepAliveInterval {
|
||||
let elapsed = now.timeIntervalSince(lastPing.outbound)
|
||||
guard (elapsed >= interval) else {
|
||||
scheduleNextPing(elapsed: elapsed)
|
||||
return
|
||||
}
|
||||
// is keep-alive enabled?
|
||||
if let _ = keepAliveInterval {
|
||||
log.debug("Send ping")
|
||||
sendDataPackets([OpenVPN.DataPacket.pingString])
|
||||
lastPing.outbound = Date()
|
||||
}
|
||||
|
||||
log.debug("Send ping")
|
||||
sendDataPackets([OpenVPN.DataPacket.pingString])
|
||||
lastPing.outbound = Date()
|
||||
|
||||
// schedule even just to check for ping timeout
|
||||
scheduleNextPing()
|
||||
}
|
||||
|
||||
private func scheduleNextPing(elapsed: TimeInterval = 0.0) {
|
||||
guard let interval = keepAliveInterval else {
|
||||
return
|
||||
private func scheduleNextPing() {
|
||||
let interval: TimeInterval
|
||||
if let keepAliveInterval = keepAliveInterval {
|
||||
interval = keepAliveInterval
|
||||
log.verbose("Schedule ping after \(interval) seconds")
|
||||
} else {
|
||||
interval = CoreConfiguration.OpenVPN.pingTimeoutCheckInterval
|
||||
log.verbose("Schedule ping timeout check after \(interval) seconds")
|
||||
}
|
||||
let remaining = min(interval, interval - elapsed)
|
||||
queue.asyncAfter(deadline: .now() + remaining) { [weak self] in
|
||||
queue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
||||
log.verbose("Running ping block")
|
||||
self?.ping()
|
||||
}
|
||||
}
|
||||
|
@ -1221,7 +1224,7 @@ public class OpenVPNSession: Session {
|
|||
// MARK: Stop
|
||||
|
||||
private func shouldHandlePackets() -> Bool {
|
||||
return (!isStopping && !keys.isEmpty)
|
||||
return !isStopping && !keys.isEmpty
|
||||
}
|
||||
|
||||
private func deferStop(_ method: StopMethod, _ error: Error?) {
|
||||
|
|
Loading…
Reference in New Issue