Пример #1
0
 public void Disconnect(VpnError error = VpnError.None)
 {
     _reconnectPending = false;
     _reconnecting     = false;
     _disconnecting    = true;
     _origin.Disconnect(error);
 }
Пример #2
0
        public async Task DisconnectError_ShouldBe_None_WhenUnexpectedlyDisconnected_WithoutAnError()
        {
            // Arrange
            VpnError disconnectError = VpnError.None;

            SetupDisconnect();
            SetupConnect();
            SetupUnexpectedDisconnect(VpnError.None);

            HandlingRequestsWrapper subject = new(_logger, _taskQueue, _origin);

            subject.StateChanged += (s, e) =>
            {
                if (e.Data.Status == VpnStatus.Disconnected)
                {
                    disconnectError = e.Data.Error;
                }
            };

            // Act
            subject.Connect(_endpoint, _credentials, _config);
            await _taskQueue.WaitForLastTask();

            // Assert
            disconnectError.Should().Be(VpnError.None);
        }
Пример #3
0
 private void InvokeStateChange(VpnStatus status, VpnError error = VpnError.None)
 {
     StateChanged?.Invoke(this,
                          new EventArgs <VpnState>(
                              new VpnState(status, error, _config.WireGuard.DefaultClientAddress, _endpoint?.Server.Ip ?? string.Empty,
                                           VpnProtocol.WireGuard, null, _endpoint?.Server.Label ?? string.Empty)));
 }
Пример #4
0
        private async Task ShowModalAsync(VpnStateChangedEventArgs e)
        {
            VpnError error = e.Error;

            if (error == VpnError.AuthorizationError)
            {
                error = await _connectionErrorResolver.ResolveError();
            }

            switch (error)
            {
            case VpnError.UserTierTooLowError:
                await ForceReconnectAsync();

                break;

            case VpnError.Unpaid:
                await ShowDelinquencyPopupViewModelAsync();

                break;

            case VpnError.SessionLimitReached:
                ShowMaximumDeviceLimitModalViewModel();
                break;

            default:
                ShowDisconnectErrorModalViewModel(error, e.NetworkBlocked);
                break;
            }
        }
Пример #5
0
        private async Task ConnectAction(CancellationToken cancellationToken)
        {
            _logger.Info("OpenVpnConnection: Connect action started");

            OnStateChanged(VpnStatus.Connecting);

            var port          = _managementPorts.Port();
            var password      = ManagementPassword();
            var processParams = new OpenVpnProcessParams(_endpoint, port, password, _config.CustomDns, _config.SplitTunnelMode, _config.SplitTunnelIPs);

            cancellationToken.ThrowIfCancellationRequested();

            if (!await _process.Start(processParams))
            {
                _disconnectError = VpnError.Unknown;
            }
            else
            {
                await _managementClient.Connect(port, password);

                if (cancellationToken.IsCancellationRequested)
                {
                    await _managementClient.CloseVpnConnection();

                    cancellationToken.ThrowIfCancellationRequested();
                }

                await _managementClient.StartVpnConnection(_credentials, cancellationToken);
            }

            cancellationToken.ThrowIfCancellationRequested();
        }
Пример #6
0
        private void ManagementClient_StateChanged(object sender, EventArgs <VpnState> e)
        {
            _logger.Info($"ManagementClient: State changed to {e.Data.Status}");

            VpnState state = new(
                e.Data.Status,
                e.Data.Error,
                e.Data.LocalIp,
                e.Data.RemoteIp,
                _endpoint.VpnProtocol,
                _config.OpenVpnAdapter,
                e.Data.Label);

            if ((state.Status == VpnStatus.Pinging || state.Status == VpnStatus.Connecting || state.Status == VpnStatus.Reconnecting) &&
                string.IsNullOrEmpty(state.RemoteIp))
            {
                state = new VpnState(
                    state.Status,
                    VpnError.None,
                    string.Empty,
                    _endpoint.Server.Ip,
                    _endpoint.VpnProtocol,
                    state.OpenVpnAdapter,
                    _endpoint.Server.Label);
            }

            if (state.Status == VpnStatus.Disconnecting && !_disconnectAction.IsRunning)
            {
                _disconnectError = state.Error;
            }

            OnStateChanged(state);
        }
Пример #7
0
        public void Disconnect(VpnError error)
        {
            _connectRequested     = false;
            _disconnectedReceived = false;

            _origin.Disconnect(error);
        }
Пример #8
0
        private void OnStateChanged(VpnState state)
        {
            _disconnected = state.Status == VpnStatus.Disconnected;

            if (_connectRequested)
            {
                InvokeConnecting();

                if (_disconnected)
                {
                    _logger.Info("HandlingRequestsWrapper: Already disconnected, queuing Connect");
                    Queued(Connect);
                }

                return;
            }

            if (_disconnectRequested || _disconnecting)
            {
                if (state.Status == VpnStatus.Disconnecting || state.Status == VpnStatus.Disconnected)
                {
                    InvokeStateChanged(state.WithError(_disconnectError));
                    return;
                }

                InvokeDisconnecting();

                return;
            }

            if (_connecting && state.Status == VpnStatus.Disconnecting)
            {
                // Force disconnect if disconnected while connecting
                _disconnectRequested = true;
                _disconnectError     = state.Error == VpnError.None ? VpnError.Unknown : state.Error;
                _logger.Info("HandlingRequestsWrapper: Disconnecting unexpectedly, queuing Disconnect");
                Queued(Disconnect);
            }

            if (state.Status == VpnStatus.Disconnecting || state.Status == VpnStatus.Disconnected)
            {
                var error = state.Error == VpnError.None ? VpnError.Unknown : state.Error;

                if (_connecting)
                {
                    // Force disconnect if disconnected while connecting
                    _disconnectRequested = true;
                    _disconnectError     = error;
                    _logger.Info("HandlingRequestsWrapper: Disconnecting unexpectedly, queuing Disconnect");
                    Queued(Disconnect);
                    return;
                }

                InvokeStateChanged(state.WithError(error));
                return;
            }

            InvokeStateChanged(WithFallbackRemoteIp(state, _endpoint.Server.Ip));
        }
Пример #9
0
        private static VpnStateChangedEventArgs Map(VpnStateContract contract)
        {
            VpnStatus   status   = Map(contract.Status);
            VpnError    error    = Map(contract.Error);
            VpnProtocol protocol = Map(contract.VpnProtocol);

            return(new(status, error, contract.EndpointIp, contract.NetworkBlocked, protocol, contract.OpenVpnAdapterType, contract.Label));
        }
Пример #10
0
        private static VpnStateChangedEventArgs Map(VpnStateContract contract)
        {
            VpnStatus   status   = Map(contract.Status);
            VpnError    error    = Map(contract.Error);
            VpnProtocol protocol = Map(contract.Protocol);

            return(new VpnStateChangedEventArgs(status, error, contract.EndpointIp, contract.NetworkBlocked, protocol));
        }
Пример #11
0
        public VpnStateChangedEventArgs(VpnState state, VpnError error, bool networkBlocked)
        {
            Ensure.NotNull(state, nameof(state));

            State          = state;
            Error          = error;
            NetworkBlocked = networkBlocked;
        }
Пример #12
0
 public VpnState(VpnStatus status, VpnError error, string localIp, string remoteIp, VpnProtocol protocol = VpnProtocol.Auto)
 {
     Status   = status;
     Error    = error;
     LocalIp  = localIp;
     RemoteIp = remoteIp;
     Protocol = protocol;
 }
Пример #13
0
        public void Disconnect(VpnError error)
        {
            _connectRequested    = false;
            _disconnectRequested = true;
            _disconnectError     = error;

            _logger.Info("HandlingRequestsWrapper: Disconnect requested, queuing Disconnect");
            Queued(Disconnect);
        }
Пример #14
0
        private void ShowDisconnectErrorModalViewModel(VpnError error, bool networkBlocked)
        {
            dynamic options = new ExpandoObject();

            options.Error          = error;
            options.NetworkBlocked = networkBlocked;

            _modals.Show <DisconnectErrorModalViewModel>(options);
        }
Пример #15
0
        public VpnStateChangedEventArgs(VpnState state, VpnError error, bool networkBlocked, VpnProtocol protocol = VpnProtocol.Auto)
        {
            Ensure.NotNull(state, nameof(state));

            State          = state;
            Error          = error;
            NetworkBlocked = networkBlocked;
            Protocol       = protocol;
        }
Пример #16
0
 public static VpnState WithError(this VpnState state, VpnError error)
 {
     return(new VpnState(
                state.Status,
                error,
                state.LocalIp,
                state.RemoteIp,
                state.Protocol));
 }
Пример #17
0
 public VpnState(VpnStatus status, VpnError error, string localIp, string remoteIp, VpnProtocol vpnProtocol, OpenVpnAdapter?openVpnAdapter = null, string label = "")
 {
     Status         = status;
     Error          = error;
     LocalIp        = localIp;
     RemoteIp       = remoteIp;
     OpenVpnAdapter = openVpnAdapter;
     VpnProtocol    = vpnProtocol;
     Label          = label;
 }
Пример #18
0
 public static VpnState WithError(this VpnState state, VpnError error)
 {
     return(new(
                state.Status,
                error,
                state.LocalIp,
                state.RemoteIp,
                state.VpnProtocol,
                state.OpenVpnAdapter,
                state.Label));
 }
Пример #19
0
 public void Disconnect(VpnError error)
 {
     if (VpnConnection == null)
     {
         OnStateChanged(this, new EventArgs <VpnState>(new VpnState(VpnStatus.Disconnected, VpnProtocol.Smart)));
     }
     else
     {
         VpnConnection.Disconnect(error);
     }
 }
Пример #20
0
        public void VpnError_ShouldBe(VpnError expected, string message)
        {
            // Arrange
            var error = new ManagementError(message);

            // Act
            var result = error.VpnError();

            // Assert
            result.Should().Be(expected);
        }
Пример #21
0
        public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config)
        {
            _endpoint    = endpoint;
            _credentials = credentials;
            _config      = config;

            _connectRequested    = true;
            _disconnectRequested = false;
            _disconnectError     = VpnError.Unknown;

            _logger.Info("HandlingRequestsWrapper: Connect requested, queuing Connect");
            Queued(Connect);
        }
Пример #22
0
 private void SetupUnexpectedDisconnect(VpnError error)
 {
     _origin.StateChanged += (s, e) =>
     {
         if (e.Data.Status == VpnStatus.Connected)
         {
             _taskQueue.Enqueue(() => RaiseStateChangedEvents(
                                    new []
             {
                 new VpnState(VpnStatus.Disconnecting, error),
                 new VpnState(VpnStatus.Disconnected, error)
             }));
         }
     };
 }
Пример #23
0
        private async Task UpdateServersOrDisconnect(VpnError disconnectReason)
        {
            if (_state.Status == VpnStatus.Disconnecting ||
                _state.Status == VpnStatus.Disconnected ||
                _lastProfile == null)
            {
                return;
            }

            _lastServerCandidates = _profileConnector.ServerCandidates(_lastProfile);

            if (!await _profileConnector.UpdateServers(_lastServerCandidates, _lastProfile))
            {
                await _vpnServiceManager.Disconnect(disconnectReason);
            }
        }
Пример #24
0
        private async Task HandleStateMessage(ReceivedManagementMessage message)
        {
            ManagementState managementState = message.State();

            if (managementState.HasError)
            {
                await TrySend(_managementChannel.Messages.Disconnect());

                if (_lastError == VpnError.None)
                {
                    _lastError = managementState.Error;
                }
            }
            else
            {
                if (managementState.HasStatus)
                {
                    OnVpnStateChanged(new VpnState(managementState.Status, _lastError,
                                                   managementState.LocalIpAddress, managementState.RemoteIpAddress, default, label: _endpoint.Server.Label));
Пример #25
0
        private void ManagementClient_StateChanged(object sender, EventArgs <VpnState> e)
        {
            _logger.Info($"ManagementClient: State changed to {e.Data.Status}");

            var state = e.Data;

            if ((state.Status == VpnStatus.Connecting || state.Status == VpnStatus.Reconnecting) &&
                string.IsNullOrEmpty(state.RemoteIp))
            {
                state = new VpnState(state.Status, VpnError.None, string.Empty, _endpoint.Server.Ip, _endpoint.Protocol);
            }

            if (state.Status == VpnStatus.Disconnecting && !_disconnectAction.IsRunning)
            {
                _disconnectError = state.Error;
            }

            OnStateChanged(state);
        }
Пример #26
0
    public VpnException(VpnError error, Pack?pack = null) : base($"{ErrorToStr(error)}")
    {
        this.Error = error;
        this.Pack  = pack?.Clone() ?? null;

        if (this.Pack != null)
        {
            if (error == VpnError.ERR_RECV_MSG)
            {
                // メッセージ付きエラー
                this.RecvMsg = this.Pack["Msg"].UniStrValueNonNull;
            }

            if (error == VpnError.ERR_RECV_URL)
            {
                // URL 付きエラー
                this.RecvUrl = this.Pack["Url"].StrValueNonNull;
            }
        }
    }
Пример #27
0
        private void OnStateChanged(VpnState state)
        {
            _disconnected = state.Status == VpnStatus.Disconnected;

            if (_connectRequested)
            {
                InvokeConnecting();

                if (_disconnected)
                {
                    _logger.Info("HandlingRequestsWrapper: Already disconnected, queuing Connect");
                    Queued(Connect);
                }

                return;
            }

            if (_disconnectRequested || _disconnecting)
            {
                if (state.Status == VpnStatus.Disconnecting || state.Status == VpnStatus.Disconnected)
                {
                    InvokeStateChanged(new VpnState(state.Status, _disconnectError));
                    return;
                }

                InvokeDisconnecting();

                return;
            }

            if (_connecting && state.Status == VpnStatus.Disconnecting)
            {
                // Force disconnect if disconnected while connecting
                _disconnectRequested = true;
                _disconnectError     = state.Error;
                _logger.Info("HandlingRequestsWrapper: Disconnecting unexpectedly, queuing Disconnect");
                Queued(Disconnect);
            }

            InvokeStateChanged(state);
        }
Пример #28
0
        /// <summary>
        /// Primary VPN connect method, doesn't finish until disconnect.
        /// This method will raise <see cref="TransportStatsChanged"/>, <see cref="VpnStateChanged"/>
        /// </summary>
        /// <param name="credentials"><see cref="VpnCredentials"/> (username and password) for authenticating to VPN server</param>
        /// <param name="endpoint"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task StartVpnConnection(VpnCredentials credentials, VpnEndpoint endpoint, CancellationToken cancellationToken)
        {
            _lastError           = VpnError.None;
            _credentials         = credentials;
            _endpoint            = endpoint;
            _sendingFailed       = false;
            _disconnectRequested = false;
            _disconnectAccepted  = false;

            while (!cancellationToken.IsCancellationRequested && !_sendingFailed)
            {
                ReceivedManagementMessage message = await Receive();

                if (message.IsChannelDisconnected)
                {
                    if (!_disconnectRequested && _lastError == VpnError.None)
                    {
                        _lastError = VpnError.Unknown;
                    }

                    OnVpnStateChanged(VpnStatus.Disconnecting);
                    return;
                }

                if (!cancellationToken.IsCancellationRequested)
                {
                    HandleMessage(message);
                }
            }

            if (!_sendingFailed)
            {
                await SendExit();
            }

            if (!cancellationToken.IsCancellationRequested && _sendingFailed)
            {
                OnVpnStateChanged(VpnStatus.Disconnecting);
            }
        }
Пример #29
0
        private async Task ReceiveLogsAction(CancellationToken cancellationToken)
        {
            uint cursor = RingLogger.CursorAll;

            while (true)
            {
                List <string> lines = _ringLogger.FollowFromCursor(ref cursor);
                foreach (string line in lines)
                {
                    _logger.Info(GetFormattedMessage(line));

                    if (line.Contains("Interface up"))
                    {
                        InvokeStateChange(VpnStatus.Connected);
                    }
                    else if (line.Contains("Shutting down"))
                    {
                        InvokeStateChange(VpnStatus.Disconnected, _lastError);
                        _lastError = VpnError.None;
                    }
                    else if (line.Contains("Could not install driver"))
                    {
                        _lastError = VpnError.NoTapAdaptersError;
                    }
                }

                try
                {
                    Thread.Sleep(300);
                }
                catch
                {
                    break;
                }

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
Пример #30
0
    public WpcResult(VpnError errorCode, Pack?pack = null, string?additionalErrorStr = null, [CallerFilePath] string filename = "", [CallerLineNumber] int line = 0, [CallerMemberName] string?caller = null)
    {
        if (pack == null)
        {
            pack = new Pack();
        }

        this.Pack = pack;

        this.ErrorCode = errorCode;
        this.Pack.AddInt("Error", (uint)this.ErrorCode);

        if (this.IsError)
        {
            this.AdditionalErrorStr = additionalErrorStr._NonNullTrim();
            if (this.AdditionalErrorStr._IsEmpty())
            {
                this.AdditionalErrorStr = null;
            }

            this.ErrorLocation = $"{filename}:{line} by {caller}";
        }
    }