Observador de estado de OpenVPN en C#: vixía a sesión, non a tarxeta de rede
NetworkAvailabilityChanged non é un evento de VPN. Le o fluxo de estado do cliente propietario, protéxete das sondas obsoletas e publica a dispoñibilidade por conexión.
A túa aplicación segue funcionando mentres o túnel morre. O Wi-Fi segue activo, internet segue respondendo e a API privada da que depende a aplicación volveuse inalcanzable. O evento de .NET ao que a xente adoita recorrer aquí, NetworkAvailabilityChanged, non describe esa situación en absoluto. Informa dun cambio na condición agregada da máquina, e esa condición pode seguir sendo certa durante unha desconexión e reconexión de VPN. Un observador ten que vixiar o cliente que posúe o túnel, non o resumo da pila de rede.
A dispoñibilidade é un agregado, non o teu túnel
NetworkAvailabilityChanged disparase cando cambia a resposta agregada de dispoñibilidade da máquina, e esa resposta conta calquera interface activa que non sexa loopback nin un túnel.
Unha caída da VPN co Wi-Fi activo non cambia nada do que mide, por iso o evento pode quedar silencioso xusto durante o fallo que che importa.
O fluxo de estado pertence ao cliente que posúe o túnel
Identifica que compoñente posúe a conexión: a GUI ou o servizo de OpenVPN, OpenVPN Connect, ou un proceso que a túa aplicación iniciou e controla. Son propietarios distintos con interfaces compatibles distintas, e o observador debe usar a que corresponda ao despregamento. Para un proceso de OpenVPN co que tes autorización para integrarte, a interface de xestión informa do estado actual, un historial e notificacións en tempo real. Analiza as mensaxes estruturadas documentadas en lugar de buscar a palabra connected nun rótulo de GUI localizado.
A canle de xestión é unha superficie de control privilexiada, así que non abras un novo escoitador nin discutas coa GUI por unha canle que xa ten.
As proteccións de xeración deteñen os resultados obsoletos
Cada observación pertence a un intento de conexión concreto. Incrementa un contador de xeración cando comeza un intento novo, cando se perde a canle e cando o cliente informa da saída.
Considera unha sonda iniciada durante a conexión A. O túnel cae, comeza a conexión B e despois chega o éxito HTTP atrasado de A. Sen unha protección, ese resultado antigo pon a pantalla en verde mentres B aínda se autentica. A cancelación reduce o traballo desperdiciado, e a comprobación de xeración é o que impide que unha finalización obsoleta se converta en estado actual:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
Aplica a mesma regra arredor do envío á UI, porque a actualización empaquetada pode chegar despois de que a xeración avanzase.
A inicialización e a reconexión son un só ciclo de vida
Trata a primeira conexión, a reconexión e a perda de canle como un só ciclo de vida cun único conxunto de regras:
- Le o estado actual e subscríbete ás notificacións nun só paso onde a interface o permita.
- Etiqueta cada observación coa identidade da conexión e a xeración.
- Invalida a dispoñibilidade na reconexión, a saída ou unha canle de observación perdida.
- Sondea o recurso privado só despois de que o propietario informe de que a inicialización está completa.
- Publica só os resultados que aínda pertencen á xeración actual.
Unha canle perdida significa descoñecido, non desconectado. Informar de descoñecido é máis honesto que informar dunha desconexión que non podes demostrar, e evita que a lóxica de reintentos actúe sobre unha suposición.
Informa de evidencia, non dun booleano
Devolve o estado de sesión nomeado e a dispoñibilidade do recurso como valores separados, cada un cunha idade. Un consumidor que ten que decidir algo pode entón ver que a última sonda exitosa ten corenta segundos, o que é información distinta dunha recente.
Unha consulta de IP pública non é evidencia de que unha API privada usase a ruta requirida, así que non a presentes como se o fose.
Mantén a aplicación fóra do observador
Unha devolución de chamada execútase despois do feito. Non pode garantir que ningún paquete saíse da máquina entre o evento e o manexador. Se o deseño require bloqueo, a política de rede ten que proporcionalo, e a tarefa do observador é explicar a evidencia ao seu chamador. Mesturar as dúas cousas produce código que cre ser un cortalumes porque ten un booleano. Mantén a capa de aplicación aburrida e comprobable, e deixa que o observador siga sendo un lector.
Entón a cuestión da UI vólvese simple: mostra o que se sabe, coa súa idade, e di descoñecido cando o sexa.