C# OpenVPN būsenos stebėtojas: stebėkite sesiją, o ne tinklo plokštę
NetworkAvailabilityChanged nėra VPN įvykis. Skaitykite tunelį valdančio kliento būsenos srautą, apsisaugokite nuo pasenusių patikrų ir skelbkite pasirengimą kiekvienam ryšiui.
Jūsų programa toliau veikia, kol tunelis miršta. Wi-Fi vis dar įjungtas, internetas vis dar atsako, o privati API, nuo kurios priklauso programa, tapo nepasiekiama. .NET įvykis, į kurį žmonės čia paprastai kreipiasi, NetworkAvailabilityChanged, visiškai neaprašo šios situacijos. Jis praneša apie mašinos bendros būsenos pasikeitimą, ir ši būsena gali likti teisinga per VPN atsijungimą ir prisijungimą iš naujo. Stebėtojas turi stebėti klientą, kuriam priklauso tunelis, o ne tinklo kamino santrauką apie jį.
Prieinamumas yra agregatas, o ne jūsų tunelis
NetworkAvailabilityChanged suveikia, kai pasikeičia mašinos agreguotas prieinamumo atsakymas, ir tas atsakymas skaičiuoja bet kurią aktyvią sąsają, išskyrus loopback ar tunelį.
VPN kritimas, kai Wi-Fi įjungtas, nekeičia nieko, ką jis matuoja, todėl įvykis gali likti tylus būtent to gedimo metu, kuris jums rūpi.
Būsenos srautas priklauso klientui, kuriam priklauso tunelis
Nustatykite, kuris komponentas valdo ryšį: OpenVPN GUI ar paslauga, OpenVPN Connect, ar procesas, kurį paleido ir kontroliuoja jūsų programa. Tai skirtingi savininkai su skirtingomis palaikomomis sąsajomis, ir stebėtojas turi naudoti tą, kuri atitinka diegimą. OpenVPN procesui, su kuriuo turite teisę integruotis, valdymo sąsaja praneša dabartinę būseną, istoriją ir realaus laiko pranešimus. Analizuokite dokumentuotus struktūrizuotus pranešimus, o ne ieškokite žodžio connected lokalizuotame GUI užraše.
Valdymo kanalas yra privilegijuotas valdymo paviršius, todėl neatidarykite naujo klausytojo ir nesiginčykite su GUI dėl kanalo, kurį jis jau turi.
Kartų apsaugos sustabdo pasenusius rezultatus
Kiekvienas stebėjimas priklauso konkrečiam prisijungimo bandymui. Padidinkite kartos skaitiklį, kai prasideda naujas bandymas, kai prarandamas kanalas ir kai klientas praneša apie išėjimą.
Apsvarstykite patikrą, pradėtą per A ryšį. Tunelis krenta, prasideda B ryšys, o tada ateina pavėluota A HTTP sėkmė. Be apsaugos tas senas rezultatas paverčia ekraną žaliu, kol B dar autentifikuojasi. Atšaukimas sumažina švaistomą darbą, o kartos patikra yra tai, kas neleidžia pasenusiam užbaigimui tapti dabartine būsena:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
Taikykite tą pačią taisyklę aplink UI siuntimą, nes maršalizuotas atnaujinimas gali atvykti po to, kai karta pajudėjo toliau.
Inicializacija ir prisijungimas iš naujo yra vienas gyvavimo ciklas
Traktuokite pirmąjį prisijungimą, prisijungimą iš naujo ir kanalo praradimą kaip vieną gyvavimo ciklą su vienu taisyklių rinkiniu:
- Skaitykite dabartinę būseną ir prenumeruokite pranešimus vienu žingsniu, kur sąsaja tai leidžia.
- Pažymėkite kiekvieną stebėjimą ryšio tapatybe ir karta.
- Padarykite pasirengimą negaliojančiu prisijungus iš naujo, išėjus ar praradus stebėjimo kanalą.
- Tikrinkite privatų išteklių tik po to, kai savininkas praneša apie inicializacijos pabaigą.
- Skelbkite tik rezultatus, kurie vis dar priklauso dabartinei kartai.
Prarastas kanalas reiškia nežinoma, o ne atjungta. Pranešti nežinoma yra sąžiningiau nei pranešti apie atjungimą, kurio negalite įrodyti, ir tai neleidžia pakartotinio bandymo logikai veikti pagal spėjimą.
Praneškite įrodymus, o ne loginę reikšmę
Grąžinkite įvardytą sesijos būseną ir ištekliaus pasirengimą kaip atskiras reikšmes, kiekvieną su amžiumi. Vartotojas, kuris turi ką nors nuspręsti, gali pamatyti, kad paskutinė sėkminga patikra yra keturiasdešimt sekundžių, o tai kitokia informacija nei šviežia.
Viešo IP paieška nėra įrodymas, kad privati API naudojo reikiamą maršrutą, todėl nepateikite jos taip, tarsi taip būtų.
Laikykite vykdymą už stebėtojo ribų
Atgalinis iškvietimas veikia po fakto. Jis negali garantuoti, kad tarp įvykio ir apdorotojo mašinos nepaliko nė vienas paketas. Jei dizainas reikalauja blokavimo, jį turi užtikrinti tinklo politika, o stebėtojo užduotis yra paaiškinti įrodymus savo kvietėjui. Sumaišius abu, gaunamas kodas, kuris mano esąs ugniasienė, nes laiko loginę reikšmę. Laikykite vykdymo sluoksnį nuobodų ir testuojamą, o stebėtojas tebūnie skaitytojas.
Tada UI klausimas tampa paprastas: parodykite, kas žinoma, su jo amžiumi, ir pasakykite nežinoma, kai taip yra.