C# OpenVPN stāvokļa novērotājs: vērojiet sesiju, nevis tīkla karti
NetworkAvailabilityChanged nav VPN notikums. Lasiet tuneļa īpašnieka klienta stāvokļa plūsmu, aizsargājieties no novecojušām pārbaudēm un publicējiet gatavību katram savienojumam.
Jūsu lietotne turpina darboties, kamēr tunelis mirst. Wi-Fi joprojām ir ieslēgts, internets joprojām atbild, un privātais API, no kura lietotne ir atkarīga, ir kļuvis nesasniedzams. .NET notikums, pie kura cilvēki šeit parasti vēršas, NetworkAvailabilityChanged, šo situāciju nemaz neapraksta. Tas ziņo par mašīnas kopējā stāvokļa izmaiņām, un šis stāvoklis var palikt patiess arī VPN atvienošanās un atkārtotas pievienošanās laikā. Novērotājam ir jāvēro klients, kuram pieder tunelis, nevis tīkla steka kopsavilkums par to.
Pieejamība ir kopsumma, nevis jūsu tunelis
NetworkAvailabilityChanged iedarbojas, kad mainās mašīnas kopējā pieejamības atbilde, un šī atbilde uzskaita jebkuru aktīvu saskarni, izņemot loopback vai tuneli.
VPN kritums, kamēr Wi-Fi ir ieslēgts, nemaina neko no tā, ko tas mēra, tāpēc notikums var palikt kluss tieši tā bojājuma laikā, kas jums ir svarīgs.
Stāvokļa plūsma pieder klientam, kuram pieder tunelis
Nosakiet, kura komponente pārvalda savienojumu: OpenVPN GUI vai pakalpojums, OpenVPN Connect, vai process, ko jūsu lietotne ir palaidusi un kontrolē. Tie ir dažādi īpašnieki ar dažādām atbalstītām saskarnēm, un novērotājam jāizmanto tā, kas atbilst izvietojumam. OpenVPN procesam, ar kuru jums ir atļauts integrēties, pārvaldības saskarne ziņo par pašreizējo stāvokli, vēsturi un reāllaika paziņojumiem. Analizējiet dokumentētos strukturētos ziņojumus, nevis meklējiet vārdu connected lokalizētā GUI parakstā.
Pārvaldības kanāls ir priviliģēta vadības virsma, tāpēc neatveriet jaunu klausītāju un necinieties ar GUI par kanālu, kas tam jau ir.
Paaudžu sargi aptur novecojušus rezultātus
Katrs novērojums pieder konkrētam savienojuma mēģinājumam. Palieliniet paaudzes skaitītāju, kad sākas jauns mēģinājums, kad tiek zaudēts kanāls un kad klients ziņo par iziešanu.
Apsveriet pārbaudi, kas sākta A savienojuma laikā. Tunelis krīt, sākas B savienojums, un pēc tam pienāk A aizkavētā HTTP veiksme. Bez sarga šis vecais rezultāts padara ekrānu zaļu, kamēr B vēl autentificējas. Atcelšana samazina izšķērdētu darbu, un paaudzes pārbaude ir tas, kas neļauj novecojušam pabeigumam kļūt par pašreizējo stāvokli:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
Piemērojiet to pašu noteikumu ap UI nosūtīšanu, jo maršalētais atjauninājums var pienākt pēc tam, kad paaudze ir pavirzījusies tālāk.
Inicializācija un atkārtota pievienošanās ir viens dzīves cikls
Uzskatiet pirmo savienojumu, atkārtotu pievienošanos un kanāla zudumu par vienu dzīves ciklu ar vienu noteikumu kopumu:
- Lasiet pašreizējo stāvokli un abonējiet paziņojumus vienā solī, kur saskarne to atļauj.
- Atzīmējiet katru novērojumu ar savienojuma identitāti un paaudzi.
- Padariet gatavību nederīgu atkārtotas pievienošanās, iziešanas vai zaudēta novērojuma kanāla gadījumā.
- Pārbaudiet privāto resursu tikai pēc tam, kad īpašnieks ziņo par inicializācijas pabeigšanu.
- Publicējiet tikai rezultātus, kas joprojām pieder pašreizējai paaudzei.
Zaudēts kanāls nozīmē nezināmu, nevis atvienotu. Ziņot par nezināmu ir godīgāk nekā ziņot par atvienošanos, ko nevarat pierādīt, un tas neļauj atkārtošanas loģikai rīkoties pēc minējuma.
Ziņojiet pierādījumus, nevis loģisko vērtību
Atgrieziet nosaukto sesijas stāvokli un resursa gatavību kā atsevišķas vērtības, katrai ir vecums. Patērētājs, kuram kaut kas jāizlemj, var redzēt, ka pēdējā veiksmīgā pārbaude ir četrdesmit sekundes veca, kas ir cita informācija nekā svaiga.
Publiskās IP meklēšana nav pierādījums, ka privātais API izmantoja nepieciešamo maršrutu, tāpēc neprezentējiet to tā, it kā tā būtu.
Turiet izpildi ārpus novērotāja
Atzvanīšana darbojas pēc fakta. Tā nevar garantēt, ka starp notikumu un apstrādātāju mašīnu nav atstājis neviens pakets. Ja dizains prasa bloķēšanu, to nodrošināt ir tīkla politikai, un novērotāja uzdevums ir izskaidrot pierādījumus savam izsaucējam. Abu sajaukšana rada kodu, kas uzskata sevi par ugunsmūri, jo tam ir loģiskā vērtība. Turiet izpildes slāni garlaicīgu un testējamu, un ļaujiet novērotājam palikt lasītājam.
Tad UI jautājums kļūst vienkāršs: parādiet, kas ir zināms, ar tā vecumu, un sakiet nezināmu, kad tā ir.