fix(ios-vpn): PacketTunnel Self-Heal — Blocklist-Retry bei leerem Start
startTunnel lädt blocklist.bin manchmal mit 0 Hashes (Datei wegen Data-Protection bei gesperrtem Gerät noch nicht lesbar). Bisher blieb Layer 1 dann tot bis zum nächsten App-Sync — in den Geräte-Logs als ~30-Min-Fenster mit 0 Hashes sichtbar (z.B. 16:22 startTunnel→0, erst 16:55 per Darwin-Reload geheilt). scheduleBlocklistRetryIfEmpty: lädt nach 3/10/30/60/120/300s erneut, bis Hashes da sind (max 20 Versuche). Sobald das Gerät entsperrt ist, wird die Datei lesbar → Self-Heal greift, ohne auf einen App-Sync zu warten. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
38a74dd1ad
commit
23b91a1a3e
@ -189,6 +189,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
ExtLog.write("✅ TUN-Settings gesetzt — Read-Loop startet")
|
||||
self.running = true
|
||||
self.readPackets()
|
||||
// Self-Heal: war die Blocklist beim Start leer (Data-Protection bei
|
||||
// gesperrtem Gerät), per Backoff erneut laden bis Hashes da sind.
|
||||
self.scheduleBlocklistRetryIfEmpty(attempt: 0)
|
||||
completionHandler(nil)
|
||||
}
|
||||
}
|
||||
@ -448,4 +451,37 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
hashList?.load()
|
||||
ExtLog.write("blocklist reloaded — \(hashList?.count() ?? 0) Hashes")
|
||||
}
|
||||
|
||||
/// Self-Heal: wenn `startTunnel` die Blocklist leer geladen hat (Datei wegen
|
||||
/// iOS-Data-Protection noch nicht lesbar — Tunnel-Start vor dem ersten
|
||||
/// Entsperren seit Boot, oder eine alte mit `.complete` geschriebene Datei),
|
||||
/// wird `load()` mit Backoff erneut versucht, bis Hashes da sind.
|
||||
///
|
||||
/// Ohne das bliebe Layer 1 still tot, bis die App das nächste Mal synct und
|
||||
/// die Darwin-Notification feuert — beobachtet in den Geräte-Logs als
|
||||
/// ~30-Minuten-Fenster mit 0 Hashes. Der Retry läuft auf `forwardQueue`.
|
||||
private func scheduleBlocklistRetryIfEmpty(attempt: Int) {
|
||||
guard running else { return }
|
||||
guard let list = hashList, list.count() == 0 else { return } // schon ok
|
||||
|
||||
let maxAttempts = 20
|
||||
guard attempt < maxAttempts else {
|
||||
ExtLog.write("⚠️ Blocklist nach \(maxAttempts) Retries leer — warte auf App-Sync")
|
||||
return
|
||||
}
|
||||
// Backoff in Sekunden; ab Index 5 konstant 300 s.
|
||||
let backoff: [Double] = [3, 10, 30, 60, 120]
|
||||
let delay = attempt < backoff.count ? backoff[attempt] : 300
|
||||
|
||||
forwardQueue.asyncAfter(deadline: .now() + delay) { [weak self] in
|
||||
guard let self = self, self.running else { return }
|
||||
self.hashList?.load()
|
||||
let n = self.hashList?.count() ?? 0
|
||||
if n > 0 {
|
||||
ExtLog.write("✅ blocklist self-heal — \(n) Hashes (Versuch \(attempt + 1))")
|
||||
} else {
|
||||
self.scheduleBlocklistRetryIfEmpty(attempt: attempt + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user