C# OpenVPN-toestandswaarnemer: hou die sessie dop, nie die netwerkkaart nie
NetworkAvailabilityChanged is nie 'n VPN-gebeurtenis nie. Lees die toestandstroom van die eienaar, beskerm teen verouderde ondersoeke en publiseer gereedheid per verbinding.
U toepassing hou aan werk terwyl die tonnel sterf. Wi-Fi is nog aan, die internet antwoord nog, en die private API waarvan die app afhanklik is, het onbereikbaar geword. Die .NET-gebeurtenis waarna mense hier gewoonlik gryp, NetworkAvailabilityChanged, beskryf daardie situasie glad nie. Dit rapporteer 'n verandering in die saamgestelde toestand van die masjien, en daardie toestand kan waar bly dwarsdeur 'n VPN-ontkoppeling en -herverbinding. 'n Waarnemer moet die kliënt dophou wat die tonnel besit, nie die netwerkstapel se opsomming daarvan nie.
Beskikbaarheid is 'n samevatting, nie jou tonnel nie
NetworkAvailabilityChanged word geaktiveer wanneer die masjien se saamgestelde beskikbaarheidsantwoord verander, en daardie antwoord tel enige op-koppelvlak buiten loopback of 'n tonnel.
'n VPN-onderbreking terwyl Wi-Fi aan is, verander niks wat dit meet nie; daarom kan die gebeurtenis stil bly tydens die presiese fout waaroor jy bekommerd is.
Die toestandstroom behoort aan die kliënt wat die tonnel besit
Identifiseer watter komponent die verbinding besit: die OpenVPN GUI of -diens, OpenVPN Connect, of 'n proses wat jou toepassing begin en beheer het. Dit is verskillende eienaars met verskillende ondersteunde koppelvlakke, en die waarnemer moet die een gebruik wat by die ontplooiing pas. Vir 'n OpenVPN-proses waarmee jy gemagtig is om te integreer, rapporteer die bestuurskoppelvlak die huidige toestand, 'n geskiedenis en intydse kennisgewings. Ontleed die gedokumenteerde gestruktureerde boodskappe eerder as om 'n gelokaliseerde GUI-byskrif te deursoek vir die woord connected.
Die bestuurskanaal is 'n bevoorregte beheeroppervlak, so moenie 'n nuwe luisteraar oopmaak of met die GUI veg oor 'n kanaal wat dit reeds hou nie.
Generasiewagte stop verouderde resultate
Elke waarneming hoort by 'n spesifieke verbindingspoging. Verhoog 'n generasieteller wanneer 'n nuwe poging begin, wanneer die kanaal verloor word en wanneer die kliënt afsluiting rapporteer.
Oorweeg 'n ondersoek wat tydens verbinding A begin is. Die tonnel val weg, verbinding B begin, en A se vertraagde HTTP-sukses kom daarna aan. Sonder 'n wag sou daardie ou resultaat die vertoning groen maak terwyl B nog besig is om te verifieer. Kansellasie verminder vermorste werk, en die generasiecontrole is wat keer dat 'n verouderde voltooiing die huidige toestand word:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
Pas dieselfde reël toe rondom die UI-versending, want die opgehoopte opdatering kan aankom nadat die generasie al verder gegaan het.
Inisialisering en herverbinding is een lewensiklus
Behandel eerste verbinding, herverbinding en kanaalverlies as een lewensiklus met een stel reëls:
- Lees die huidige toestand en teken in op kennisgewings in een stap waar die koppelvlak dit toelaat.
- Merk elke waarneming met die verbindingsidentiteit en die generasie.
- Maak gereedheid ongeldig by herverbinding, afsluiting of 'n verlore waarnemingskanaal.
- Ondersoek die private hulpbron eers nadat die eienaar inisialisering voltooid rapporteer.
- Publiseer slegs resultate wat nog aan die huidige generasie behoort.
'n Verlore kanaal beteken onbekend, nie ontkoppel nie. Om onbekend te rapporteer is eerliker as om 'n ontkoppeling te rapporteer wat jy nie kan bewys nie, en dit keer dat die herprobeerlogika op 'n raaiskoot reageer.
Rapporteer bewyse, nie 'n boole nie
Gee die genoemde sessietoestand en die hulpbron-gereedheid as afsonderlike waardes terug, elk met 'n ouderdom. 'n Verbruiker wat iets moet besluit, kan dan sien dat die laaste suksesvolle ondersoek veertig sekondes oud is, wat ander inligting is as 'n vars een.
'n Opsoek van die publieke IP is nie bewyse dat 'n private API die vereiste roete gebruik het nie, so moenie dit voorstel asof dit wel so is nie.
Hou afdwinging buite die waarnemer
'n Terugroep loop na die feit. Dit kan nie waarborg dat geen pakket die masjien verlaat het tussen die gebeurtenis en die hanteerder nie. As die ontwerp blokkering vereis, moet die netwerkbeleid dit verskaf, en die waarnemer se taak is om die bewyse aan sy oproeper te verduidelik. Om die twee te vermeng, lewer kode wat dink dit is 'n firewall omdat dit 'n boole hou. Hou die afdwingingslaag vervelig en toetsbaar, en laat die waarnemer 'n leser bly.
Dan word die UI-vraag eenvoudig: wys wat bekend is, met sy ouderdom, en sê onbekend wanneer dit so is.