private void ManagementSession_StateReported(object sender, StateReportedEventArgs e) { var state = SessionStatusType.Error; string msg = null; switch (e.State) { case OpenVPNStateType.Connecting: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeConnecting; break; case OpenVPNStateType.Resolving: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeResolving; break; case OpenVPNStateType.TcpConnecting: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeTcpConnecting; break; case OpenVPNStateType.Waiting: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeWaiting; break; case OpenVPNStateType.Authenticating: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeAuthenticating; break; case OpenVPNStateType.GettingConfiguration: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeGettingConfiguration; break; case OpenVPNStateType.AssigningIP: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeAssigningIP; break; case OpenVPNStateType.AddingRoutes: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeAddingRoutes; break; case OpenVPNStateType.Connected: state = SessionStatusType.Connected; msg = Resources.Strings.OpenVPNStateTypeConnected; break; case OpenVPNStateType.Reconnecting: state = SessionStatusType.Connecting; msg = Resources.Strings.OpenVPNStateTypeReconnecting; break; case OpenVPNStateType.Exiting: state = SessionStatusType.Disconnecting; msg = Resources.Strings.OpenVPNStateTypeExiting; break; } if (!string.IsNullOrEmpty(e.Message)) { if (msg != null) { msg += "\r\n" + e.Message; } else { msg = e.Message; } } else if (msg == null) { msg = ""; } Wizard.TryInvoke((Action)(() => { StateDescription = msg; TunnelAddress = e.Tunnel; IPv6TunnelAddress = e.IPv6Tunnel; ConnectedAt = e.State == OpenVPNStateType.Connected ? (DateTimeOffset?)e.TimeStamp : null; // Set State property last, as the whole world is listening on this property to monitor connectivity changes. // It is important that we have IP addresses and other info already set before rising PropertyChanged event for State. State = state; })); if (e.State == OpenVPNStateType.Reconnecting) { switch (e.Message) { case "connection-reset": // Connection was reset. if (ValidTo <= DateTimeOffset.Now) { // Client certificate expired. Try with a new client certificate then. goto case "tls-error"; } goto default; case "auth-failure": // Client certificate was deleted/revoked on the server side, or the user is disabled. case "tls-error": // Client certificate is not compliant with this eduVPN server. Was eduVPN server reinstalled? // Refresh configuration. var config = ConnectingProfile.Connect( Wizard.GetAuthenticatingServer(ConnectingProfile.Server), true, ProfileConfig.ContentType, Window.Abort.Token); Wizard.TryInvoke((Action)(() => ProfileConfig = config)); IgnoreHoldHint = true; break; default: IgnoreHoldHint = false; break; } ManagementSession.QueueReleaseHold(Window.Abort.Token); } }
/// <inheritdoc/> protected override void Run() { Wizard.TryInvoke((Action)(() => Wizard.TaskCount++)); try { var propertyUpdater = new DispatcherTimer( new TimeSpan(0, 0, 0, 1), DispatcherPriority.Normal, (object sender, EventArgs e) => _ShowLog?.RaiseCanExecuteChanged(), Wizard.Dispatcher); propertyUpdater.Start(); try { retry: // Connect to WireGuard Tunnel Manager Service to activate the tunnel. using (var managerSession = new eduWireGuard.ManagerService.Session()) { Wizard.TryInvoke((Action)(() => State = SessionStatusType.Connecting)); try { managerSession.Activate( "eduWGManager" + Properties.Settings.Default.WireGuardTunnelManagerServiceInstance, TunnelName, ProfileConfig.Value, 3000, Window.Abort.Token); } catch (OperationCanceledException) { throw; } catch (Exception ex) { throw new AggregateException(Resources.Strings.ErrorWireGuardTunnelManagerService, ex); } IPAddress tunnelAddress = null, ipv6TunnelAddress = null; using (var reader = new StringReader(ProfileConfig.Value)) { var iface = new eduWireGuard.Interface(reader); foreach (var a in iface.Addresses) { switch (a.Address.AddressFamily) { case AddressFamily.InterNetwork: tunnelAddress = a.Address; break; case AddressFamily.InterNetworkV6: ipv6TunnelAddress = a.Address; break; } } } RenewInProgress = new CancellationTokenSource(); Wizard.TryInvoke((Action)(() => { _Renew?.RaiseCanExecuteChanged(); _Disconnect?.RaiseCanExecuteChanged(); Wizard.TaskCount--; TunnelAddress = tunnelAddress; IPv6TunnelAddress = ipv6TunnelAddress; State = SessionStatusType.Connected; })); // Wait for a change and update stats. var ct = CancellationTokenSource.CreateLinkedTokenSource(new CancellationToken[] { DeactivateInProgress.Token, RenewInProgress.Token, Window.Abort.Token }); do { try { var cfg = managerSession.GetTunnelConfig(ct.Token); ulong rxBytes = 0, txBytes = 0; DateTimeOffset lastHandshake = DateTimeOffset.MinValue; foreach (var peer in cfg.Peers) { rxBytes += peer.RxBytes; txBytes += peer.TxBytes; if (lastHandshake < peer.LastHandshake) { lastHandshake = peer.LastHandshake; } } Wizard.TryInvoke((Action)(() => { if (ConnectedAt == null && lastHandshake != DateTimeOffset.MinValue) { ConnectedAt = lastHandshake; } BytesIn = rxBytes; BytesOut = txBytes; })); } catch { Wizard.TryInvoke((Action)(() => ConnectedAt = null)); } } while (!ct.Token.WaitHandle.WaitOne(5 * 1000)); Wizard.TryInvoke((Action)(() => { Wizard.TaskCount++; State = SessionStatusType.Disconnecting; })); managerSession.Deactivate(); if (DeactivateInProgress.IsCancellationRequested || Window.Abort.IsCancellationRequested) { return; } } // Reapply for a profile config. ConnectingProfile.Server.ResetKeypair(); var config = ConnectingProfile.Connect( Wizard.GetAuthenticatingServer(ConnectingProfile.Server), true, ProfileConfig.ContentType, Window.Abort.Token); Wizard.TryInvoke((Action)(() => ProfileConfig = config)); goto retry; } finally { Wizard.TryInvoke((Action)(() => { // Cleanup status properties. TunnelAddress = null; IPv6TunnelAddress = null; ConnectedAt = null; BytesIn = null; BytesOut = null; })); propertyUpdater.Stop(); } } finally { Wizard.TryInvoke((Action)(() => Wizard.TaskCount--)); } }