/*
* Copyright (c) 2025 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see .
*/
using System;
using System.Collections.Generic;
using ProtonVPN.Common.Core.Extensions;
using ProtonVPN.Common.Core.Networking;
namespace ProtonVPN.Vpn.Management;
///
/// Maps OpenVPN state received over management interface to VPN status.
///
public class ManagementState
{
private static readonly Dictionary _statusMapping = new(StringComparer.OrdinalIgnoreCase)
{
["TCP_CONNECT"] = VpnStatus.Connecting,
["WAIT"] = VpnStatus.Waiting,
["AUTH"] = VpnStatus.Authenticating,
["GET_CONFIG"] = VpnStatus.RetrievingConfiguration,
["ASSIGN_IP"] = VpnStatus.AssigningIp,
["ADD_ROUTES"] = VpnStatus.AssigningIp,
["CONNECTING"] = VpnStatus.Connecting,
["CONNECTED"] = VpnStatus.Connected,
["DISCONNECTED"] = VpnStatus.Disconnecting,
["EXITING"] = VpnStatus.Disconnecting,
["RECONNECTING"] = VpnStatus.Reconnecting,
};
private readonly string? _state;
private readonly string? _status;
public ManagementState(string? stateMessage, string? statusMessage, string? localIpAddress, string? remoteAddress)
{
_state = stateMessage;
_status = statusMessage;
LocalIpAddress = localIpAddress;
RemoteIpAddress = remoteAddress;
}
public VpnStatus Status => GetStatus();
public bool HasStatus => GetStatus() != default(VpnStatus);
public bool HasError => Status == VpnStatus.Connected && _status is not null && _status.EqualsIgnoringCase("ERROR")
|| HasTlsError();
public VpnError Error => HasTlsError() ? VpnError.TlsError : VpnError.None;
public static ManagementState Null => new(null, null, null, null);
public string? LocalIpAddress { get; }
public string? RemoteIpAddress { get; }
private VpnStatus GetStatus()
{
return _state is not null && _statusMapping.TryGetValue(_state, out VpnStatus status)
? status
: default(VpnStatus);
}
private bool HasTlsError()
{
return Status == VpnStatus.Reconnecting && _status is not null && _status.EqualsIgnoringCase("tls-error");
}
}