From 90fec23835169c96392f26a3a624efb639781ead Mon Sep 17 00:00:00 2001 From: antallusion Date: Sun, 5 Apr 2026 03:02:37 +0300 Subject: [PATCH] Add LiteConnectionBridge class in Lite directory --- Lite/LiteConnectionBridge.cs | 244 +++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 Lite/LiteConnectionBridge.cs diff --git a/Lite/LiteConnectionBridge.cs b/Lite/LiteConnectionBridge.cs new file mode 100644 index 00000000..d9307ac7 --- /dev/null +++ b/Lite/LiteConnectionBridge.cs @@ -0,0 +1,244 @@ +namespace v2rayN.Lite; + +/// +/// Bridge to v2rayN backend infrastructure for Lite UI +/// Handles VLESS profile import, config generation, and connection management +/// while reusing existing AppManager, ConfigHandler, CoreManager infrastructure +/// +public class LiteConnectionBridge +{ + private const string LiteProfileName = "VPN RUS Client Lite"; + private string? _currentProfileId; + + public async Task ConnectAsync(string vlessLink, CancellationToken cancellationToken = default) + { + try + { + // Validate VLESS link + if (!vlessLink.StartsWith("vless://", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + cancellationToken.ThrowIfCancellationRequested(); + + // Import/update VLESS profile using existing v2rayN infrastructure + _currentProfileId = await ImportVlessProfileAsync(vlessLink, cancellationToken); + + if (string.IsNullOrEmpty(_currentProfileId)) + { + return false; + } + + cancellationToken.ThrowIfCancellationRequested(); + + // Set profile as active + var profile = AppManager.Instance?.GetProfileById(_currentProfileId); + if (profile == null) + { + return false; + } + + AppManager.Instance?.SetActiveProfile(_currentProfileId); + + // Enable TUN in the profile configuration + profile.EnableTun = true; + ConfigHandler.SaveProfile(profile); + + cancellationToken.ThrowIfCancellationRequested(); + + // Start the core using existing v2rayN pipeline + // This reuses CoreConfigContextBuilder → CoreConfigHandler → CoreManager + await Task.Delay(500, cancellationToken); + var result = await CoreManager.Instance.StartAsync(); + + return result; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + Logging.SaveLog(nameof(LiteConnectionBridge), ex); + return false; + } + } + + public async Task DisconnectAsync(CancellationToken cancellationToken = default) + { + try + { + cancellationToken.ThrowIfCancellationRequested(); + + // Stop core using existing CoreManager + var result = await CoreManager.Instance.StopAsync(); + + await Task.Delay(300, cancellationToken); + + return result; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + Logging.SaveLog(nameof(LiteConnectionBridge), ex); + return false; + } + } + + public bool IsConnected() + { + try + { + return CoreManager.Instance.IsRunning(); + } + catch + { + return false; + } + } + + private async Task ImportVlessProfileAsync(string vlessLink, CancellationToken cancellationToken = default) + { + try + { + cancellationToken.ThrowIfCancellationRequested(); + + // Check if Lite profile already exists + var existingProfile = AppManager.Instance?.GetProfiles() + .FirstOrDefault(p => p.Name == LiteProfileName); + + ProfileItem profile; + + if (existingProfile != null) + { + // Update existing profile + profile = existingProfile; + } + else + { + // Create new profile + var groupId = await GetOrCreateLiteGroupAsync(cancellationToken); + profile = new ProfileItem + { + Name = LiteProfileName, + GroupId = groupId + }; + } + + cancellationToken.ThrowIfCancellationRequested(); + + // Parse VLESS link and update profile + if (!ParseVlessLink(vlessLink, profile)) + { + return null; + } + + // Save profile + ConfigHandler.SaveProfile(profile); + + return profile.Id; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + Logging.SaveLog(nameof(LiteConnectionBridge), ex); + return null; + } + } + + private bool ParseVlessLink(string vlessLink, ProfileItem profile) + { + try + { + // Basic VLESS link parsing + // Format: vless://uuid@host:port?encryption=none&security=reality&sni=domain&fp=... + + if (!Uri.TryCreate(vlessLink, UriKind.Absolute, out var uri)) + { + return false; + } + + // Extract UUID (user info) + var userInfo = uri.UserInfo; + if (string.IsNullOrEmpty(userInfo)) + { + return false; + } + + // Extract host and port + var host = uri.Host; + var port = uri.Port > 0 ? uri.Port : 443; + + if (string.IsNullOrEmpty(host)) + { + return false; + } + + // Parse query parameters + var query = System.Web.HttpUtility.ParseQueryString(uri.Query); + var security = query["security"] ?? "reality"; + var sni = query["sni"] ?? host; + var fp = query["fp"] ?? "chrome"; + + // Update profile with parsed VLESS data + profile.Address = host; + profile.Port = port; + profile.Security = security; + profile.Sni = sni; + profile.Fingerprint = fp; + profile.Protocol = EProtocol.VLESS; + + // Enable TUN + profile.EnableTun = true; + + return true; + } + catch (Exception ex) + { + Logging.SaveLog(nameof(LiteConnectionBridge), ex); + return false; + } + } + + private async Task GetOrCreateLiteGroupAsync(CancellationToken cancellationToken = default) + { + try + { + cancellationToken.ThrowIfCancellationRequested(); + + var liteGroup = AppManager.Instance?.GetProfileGroups() + .FirstOrDefault(g => g.GroupName == LiteProfileName); + + if (liteGroup != null) + { + return liteGroup.Id; + } + + // Create new group + var newGroup = new ProfileGroup + { + GroupName = LiteProfileName + }; + + ConfigHandler.SaveProfileGroup(newGroup); + + return newGroup.Id; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + Logging.SaveLog(nameof(LiteConnectionBridge), ex); + return string.Empty; + } + } +} \ No newline at end of file