Pozorovatel stavu OpenVPN v C#: sledujte relaci, ne síťovou kartu
NetworkAvailabilityChanged není událost VPN. Čtěte tok stavu od klientského vlastníka, chraňte se před zastaralými sondami a publikujte připravenost pro každé spojení.
Vaše aplikace dál funguje, zatímco tunel umírá. Wi-Fi je stále zapnutá, internet stále odpovídá, a privátní API, na kterém aplikace závisí, se stalo nedostupným. Událost .NET, ke které se lidé v této situaci obvykle uchylují, NetworkAvailabilityChanged, tuto situaci vůbec nepopisuje. Hlásí změnu agregovaného stavu stroje a tento stav může zůstat pravdivý i přes odpojení a opětovné připojení VPN. Pozorovatel musí sledovat klienta, který tunel vlastní, ne shrnutí síťového zásobníku o něm.
Dostupnost je agregát, ne váš tunel
NetworkAvailabilityChanged se spustí, když se změní agregovaná odpověď stroje o dostupnosti, a tato odpověď počítá každé aktivní rozhraní kromě loopbacku nebo tunelu.
Výpadek VPN při zapnuté Wi-Fi nemění nic z toho, co měří, a proto může událost mlčet právě během závady, na které vám záleží.
Tok stavu patří klientovi, který tunel vlastní
Určete, která komponenta spojení vlastní: GUI nebo služba OpenVPN, OpenVPN Connect, nebo proces, který vaše aplikace spustila a ovládá. Jsou to různí vlastníci s různými podporovanými rozhraními a pozorovatel musí použít to, které odpovídá nasazení. U procesu OpenVPN, se kterým máte oprávnění se integrovat, hlásí rozhraní pro správu aktuální stav, historii a oznámení v reálném čase. Analyzujte dokumentované strukturované zprávy místo hledání slova connected v lokalizovaném popisu GUI.
Kanál pro správu je privilegovaná řídicí plocha, takže neotvírejte nový posluchač a nehádejte se s GUI o kanál, který už drží.
Generační pojistky zastavují zastaralé výsledky
Každé pozorování patří ke konkrétnímu pokusu o připojení. Zvyšte čítač generace, když začne nový pokus, když se ztratí kanál a když klient ohlásí ukončení.
Vezměte sondu spuštěnou během spojení A. Tunel spadne, začne spojení B a potom dorazí zpožděný úspěch HTTP od A. Bez pojistky ten starý výsledek zbarví displej zeleně, zatímco B se ještě autentizuje. Zrušení snižuje zbytečnou práci a generační kontrola je to, co brání tomu, aby se zastaralé dokončení stalo aktuálním stavem:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
Stejné pravidlo použijte i kolem odesílání do UI, protože zařazená aktualizace může dorazit poté, co generace už postoupila.
Inicializace a opětovné připojení jsou jeden životní cyklus
Považujte první připojení, opětovné připojení a ztrátu kanálu za jeden životní cyklus s jednou sadou pravidel:
- Přečtěte aktuální stav a přihlaste se k odběru oznámení v jednom kroku, kde to rozhraní umožňuje.
- Označte každé pozorování identitou spojení a generací.
- Zneplatněte připravenost při opětovném připojení, ukončení nebo ztraceném kanálu pozorování.
- Sondujte privátní zdroj až poté, co vlastník ohlásí dokončení inicializace.
- Publikujte jen výsledky, které stále patří aktuální generaci.
Ztracený kanál znamená neznámo, ne odpojeno. Hlásit neznámo je čestnější než hlásit odpojení, které nemůžete prokázat, a brání tomu, aby logika opakování jednala na základě dohadu.
Hlaste důkazy, ne boolean
Vracejte pojmenovaný stav relace a připravenost zdroje jako oddělené hodnoty, každou s věkem. Spotřebitel, který musí něco rozhodnout, pak vidí, že poslední úspěšná sonda je stará čtyřicet sekund, což je jiná informace než čerstvá.
Vyhledání veřejné IP není důkaz, že privátní API použilo požadovanou trasu, takže to nepředkládejte, jako by to důkaz byl.
Udržujte vynucování mimo pozorovatele
Zpětné volání běží až po události. Nemůže zaručit, že mezi událostí a obsluhou neopustil stroj žádný paket. Pokud návrh vyžaduje blokování, musí ho poskytnout síťová politika a úkolem pozorovatele je vysvětlit důkazy svému volajícímu. Míchání obojího vytváří kód, který si myslí, že je firewall, protože drží boolean. Udržujte vynucovací vrstvu nudnou a testovatelnou a nechte pozorovatele zůstat čtenářem.
Pak je otázka UI jednoduchá: ukažte, co je známo, s jeho stářím, a řekněte neznámo, když tomu tak je.