Merge branch 'unexpected-ping-timeout'

This commit is contained in:
Davide De Rosa 2019-12-14 10:14:10 +01:00
commit 2625cec278
4 changed files with 51 additions and 24 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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?) {