using System.Text.Json.Serialization;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using AppTunnel.Services;
namespace AppTunnel.Models;
public enum TunnelType
{
L2tpIpsec,
V2Ray,
OpenVpn,
SocksProxy
}
public enum ProxyProtocol
{
Socks5,
Http
}
///
/// A named connection profile containing server settings and selected applications.
/// Multiple profiles can be saved and quickly switched between.
///
public class ConnectionProfile : INotifyPropertyChanged
{
private string _id = Guid.NewGuid().ToString("N")[..8];
private string _name = "پروفایل جدید";
private DateTime _createdAt = DateTime.Now;
private DateTime _lastUsedAt = DateTime.Now;
private string _serverAddress = string.Empty;
private string _username = string.Empty;
private string _password = string.Empty;
private string _preSharedKey = string.Empty;
private List _tunnelApps = new();
private List _excludedDestinations = new();
private TunnelType _tunnelType = TunnelType.L2tpIpsec;
private string _v2RayConfig = "";
private string _openVpnConfig = "";
private string _openVpnConfigPath = "";
private string _openVpnUsername = "";
private string _openVpnPassword = "";
private ProxyProtocol _proxyProtocol = ProxyProtocol.Socks5;
private string _proxyServerAddress = "";
private int _proxyPort = 1080;
private string _proxyUsername = "";
private string _proxyPassword = "";
private int _mixedProxyPort = 1080;
private bool _autoTuneMtu = true;
private bool _enableDnsOptimization = true;
private bool _enableGameMode = false;
public ConnectionProfile()
{
LocalizationService.Instance.LanguageChanged += (_, _) =>
{
OnPropertyChanged(nameof(TunnelTypeDisplay));
OnPropertyChanged(nameof(EndpointDisplay));
OnPropertyChanged(nameof(ReadinessText));
};
}
public string Id
{
get => _id;
set => SetField(ref _id, value);
}
public string Name
{
get => _name;
set => SetField(ref _name, value);
}
public DateTime CreatedAt
{
get => _createdAt;
set => SetField(ref _createdAt, value);
}
public DateTime LastUsedAt
{
get => _lastUsedAt;
set => SetField(ref _lastUsedAt, value);
}
// Server configuration
public string ServerAddress
{
get => _serverAddress;
set => SetField(ref _serverAddress, value);
}
public string Username
{
get => _username;
set => SetField(ref _username, value);
}
public string Password
{
get => _password;
set => SetField(ref _password, value);
}
public string PreSharedKey
{
get => _preSharedKey;
set => SetField(ref _preSharedKey, value);
}
// Selected apps for this profile
public List TunnelApps
{
get => _tunnelApps;
set => SetField(ref _tunnelApps, value);
}
///
/// Domains or IPs that should bypass the tunnel even for target apps.
///
public List ExcludedDestinations
{
get => _excludedDestinations;
set => SetField(ref _excludedDestinations, value);
}
public TunnelType TunnelType
{
get => _tunnelType;
set => SetField(ref _tunnelType, value);
}
public string V2RayConfig
{
get => _v2RayConfig;
set => SetField(ref _v2RayConfig, value);
}
public string OpenVpnConfig
{
get => _openVpnConfig;
set => SetField(ref _openVpnConfig, value);
}
public string OpenVpnConfigPath
{
get => _openVpnConfigPath;
set => SetField(ref _openVpnConfigPath, value);
}
public string OpenVpnUsername
{
get => _openVpnUsername;
set => SetField(ref _openVpnUsername, value);
}
public string OpenVpnPassword
{
get => _openVpnPassword;
set => SetField(ref _openVpnPassword, value);
}
public ProxyProtocol ProxyProtocol
{
get => _proxyProtocol;
set => SetField(ref _proxyProtocol, value);
}
public string ProxyServerAddress
{
get => _proxyServerAddress;
set => SetField(ref _proxyServerAddress, value);
}
public int ProxyPort
{
get => _proxyPort;
set => SetField(ref _proxyPort, value);
}
public string ProxyUsername
{
get => _proxyUsername;
set => SetField(ref _proxyUsername, value);
}
public string ProxyPassword
{
get => _proxyPassword;
set => SetField(ref _proxyPassword, value);
}
[JsonPropertyName("socks5Port")]
public int MixedProxyPort
{
get => _mixedProxyPort;
set => SetField(ref _mixedProxyPort, value);
}
public bool AutoTuneMtu
{
get => _autoTuneMtu;
set => SetField(ref _autoTuneMtu, value);
}
public bool EnableDnsOptimization
{
get => _enableDnsOptimization;
set => SetField(ref _enableDnsOptimization, value);
}
public bool EnableGameMode
{
get => _enableGameMode;
set => SetField(ref _enableGameMode, value);
}
[JsonIgnore]
public string ConnectionName => $"TunnelX-{Id}";
[JsonIgnore]
public string TunnelTypeDisplay => TunnelType switch
{
TunnelType.L2tpIpsec => "L2TP/IPsec",
TunnelType.V2Ray => "V2Ray / Xray",
TunnelType.OpenVpn => "OpenVPN",
TunnelType.SocksProxy => ProxyProtocol == ProxyProtocol.Http ? "HTTP Proxy" : "SOCKS5 Proxy",
_ => LocalizationService.Instance.T("نامشخص")
};
[JsonIgnore]
public string EndpointDisplay => TunnelType switch
{
TunnelType.L2tpIpsec => string.IsNullOrWhiteSpace(ServerAddress) ? LocalizationService.Instance.T("آدرس سرور وارد نشده") : ServerAddress,
TunnelType.V2Ray => string.IsNullOrWhiteSpace(V2RayConfig) ? LocalizationService.Instance.T("کانفیگ وارد نشده") : LocalizationService.Instance.T("کانفیگ آماده"),
TunnelType.OpenVpn => string.IsNullOrWhiteSpace(OpenVpnConfigPath) ? LocalizationService.Instance.T("فایل .ovpn انتخاب نشده") : Path.GetFileName(OpenVpnConfigPath),
TunnelType.SocksProxy => string.IsNullOrWhiteSpace(ProxyServerAddress) ? LocalizationService.Instance.T("آدرس پراکسی وارد نشده") : $"{ProxyServerAddress}:{ProxyPort}",
_ => ""
};
[JsonIgnore]
public bool IsReady => TunnelType switch
{
TunnelType.L2tpIpsec => !string.IsNullOrWhiteSpace(ServerAddress),
TunnelType.V2Ray => !string.IsNullOrWhiteSpace(V2RayConfig),
TunnelType.OpenVpn => !string.IsNullOrWhiteSpace(OpenVpnConfig),
TunnelType.SocksProxy => !string.IsNullOrWhiteSpace(ProxyServerAddress) && ProxyPort is > 0 and <= 65535,
_ => false
};
[JsonIgnore]
public string ReadinessText => IsReady ? LocalizationService.Instance.T("آماده اتصال") : LocalizationService.Instance.T("نیاز به تکمیل");
[JsonIgnore]
public string ReadinessColor => IsReady ? "#6CCB5F" : "#E0A020";
public ServerConfig ToServerConfig() => new()
{
ServerAddress = ServerAddress,
Username = Username,
Password = Password,
PreSharedKey = PreSharedKey,
ConnectionName = ConnectionName,
TunnelType = TunnelType,
V2RayConfig = V2RayConfig,
OpenVpnConfig = OpenVpnConfig,
OpenVpnUsername = OpenVpnUsername,
OpenVpnPassword = OpenVpnPassword,
ProxyProtocol = ProxyProtocol,
ProxyServerAddress = ProxyServerAddress,
ProxyPort = ProxyPort,
ProxyUsername = ProxyUsername,
ProxyPassword = ProxyPassword,
AutoTuneMtu = AutoTuneMtu,
EnableDnsOptimization = EnableDnsOptimization,
EnableGameMode = EnableGameMode
};
public override string ToString() => Name;
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
OnPropertyChanged(nameof(TunnelTypeDisplay));
OnPropertyChanged(nameof(EndpointDisplay));
OnPropertyChanged(nameof(IsReady));
OnPropertyChanged(nameof(ReadinessText));
OnPropertyChanged(nameof(ReadinessColor));
return true;
}
}
public class ProfileApp
{
public string DisplayName { get; set; } = string.Empty;
public string ExecutablePath { get; set; } = string.Empty;
public string ExecutableName { get; set; } = string.Empty;
public bool IsEnabled { get; set; } = true;
}