From db9fe9c5eaed3fc0e1ff131012e969580cb2b6dd Mon Sep 17 00:00:00 2001 From: DHR60 Date: Sat, 21 Mar 2026 11:47:04 +0000 Subject: [PATCH] Fix (#8972) --- .../Handler/Builder/NodeValidator.cs | 6 ---- v2rayN/ServiceLib/Handler/ConfigHandler.cs | 3 +- v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs | 18 ++++++---- v2rayN/ServiceLib/Models/ProtocolExtraItem.cs | 1 + .../Singbox/SingboxOutboundService.cs | 2 +- .../ViewModels/AddServerViewModel.cs | 11 ++++-- .../Views/AddServerWindow.axaml | 31 +++++++++++------ .../Views/AddServerWindow.axaml.cs | 14 +++++--- v2rayN/v2rayN/Views/AddServerWindow.xaml | 34 ++++++++++++------- v2rayN/v2rayN/Views/AddServerWindow.xaml.cs | 13 ++++--- 10 files changed, 85 insertions(+), 48 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs b/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs index 053c51f2..65110b2a 100644 --- a/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs +++ b/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs @@ -152,12 +152,6 @@ public class NodeValidator private static string? ValidateSingboxTransport(EConfigType configType, string net) { - // Naive support tcp and quic transports - if (configType == EConfigType.Naive && net == "quic") - { - return null; - } - // sing-box does not support xhttp / kcp transports if (SingboxUnsupportedTransports.Contains(net)) { diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index bbc23f1c..524d9d6a 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -848,7 +848,8 @@ public static class ConfigHandler profileItem.Address = profileItem.Address.TrimEx(); profileItem.Username = profileItem.Username.TrimEx(); profileItem.Password = profileItem.Password.TrimEx(); - profileItem.Network = profileItem.Network == "quic" ? "quic" : string.Empty; + profileItem.Alpn = string.Empty; + profileItem.Network = string.Empty; if (profileItem.StreamSecurity.IsNullOrEmpty()) { profileItem.StreamSecurity = Global.StreamSecurity; diff --git a/v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs index aec27d57..5792472b 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/NaiveFmt.cs @@ -19,9 +19,13 @@ public class NaiveFmt : BaseFmt Address = parsedUrl.IdnHost, Port = parsedUrl.Port, }; + var protocolExtra = item.GetProtocolExtra(); if (parsedUrl.Scheme.Contains("quic")) { - item.Network = "quic"; + protocolExtra = protocolExtra with + { + NaiveQuic = true, + }; } var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo); if (rawUserInfo.Contains(':')) @@ -40,12 +44,13 @@ public class NaiveFmt : BaseFmt var insecureConcurrency = int.TryParse(GetQueryValue(query, "insecure-concurrency"), out var ic) ? ic : 0; if (insecureConcurrency > 0) { - item.SetProtocolExtra(item.GetProtocolExtra() with + protocolExtra = protocolExtra with { InsecureConcurrency = insecureConcurrency, - }); + }; } + item.SetProtocolExtra(protocolExtra); return item; } @@ -63,9 +68,10 @@ public class NaiveFmt : BaseFmt var userInfo = item.Username.IsNotEmpty() ? $"{Utils.UrlEncode(item.Username)}:{Utils.UrlEncode(item.Password)}" : Utils.UrlEncode(item.Password); var dicQuery = new Dictionary(); ToUriQuery(item, Global.None, ref dicQuery); - if (item.GetProtocolExtra().InsecureConcurrency > 0) + var protocolExtra = item.GetProtocolExtra(); + if (protocolExtra.InsecureConcurrency > 0) { - dicQuery.Add("insecure-concurrency", item.GetProtocolExtra()?.InsecureConcurrency.ToString()); + dicQuery.Add("insecure-concurrency", protocolExtra?.InsecureConcurrency.ToString()); } var query = dicQuery.Count > 0 @@ -73,7 +79,7 @@ public class NaiveFmt : BaseFmt : string.Empty; var url = $"{userInfo}@{GetIpv6(item.Address)}:{item.Port}"; - if (item.Network == "quic") + if (protocolExtra.NaiveQuic == true) { return $"{Global.NaiveQuicProtocolShare}{url}{query}{remark}"; } diff --git a/v2rayN/ServiceLib/Models/ProtocolExtraItem.cs b/v2rayN/ServiceLib/Models/ProtocolExtraItem.cs index 89f171ea..03403f5b 100644 --- a/v2rayN/ServiceLib/Models/ProtocolExtraItem.cs +++ b/v2rayN/ServiceLib/Models/ProtocolExtraItem.cs @@ -34,6 +34,7 @@ public record ProtocolExtraItem // naiveproxy public int? InsecureConcurrency { get; init; } + public bool? NaiveQuic { get; init; } // group profile public string? GroupType { get; init; } diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs index 1d3f407e..4d4bc04e 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs @@ -282,7 +282,7 @@ public partial class CoreConfigSingboxService { outbound.username = _node.Username; outbound.password = _node.Password; - if (outbound.network == "quic") + if (protocolExtra.NaiveQuic == true) { outbound.quic = true; outbound.quic_congestion_control = protocolExtra.CongestionControl.NullIfEmpty(); diff --git a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs index e792e8b7..e5c307c8 100644 --- a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs @@ -68,7 +68,10 @@ public class AddServerViewModel : MyReactiveObject public string CongestionControl { get; set; } [Reactive] - public int InsecureConcurrency { get; set; } + public int? InsecureConcurrency { get; set; } + + [Reactive] + public bool NaiveQuic { get; set; } public ReactiveCommand FetchCertCmd { get; } public ReactiveCommand FetchCertChainCmd { get; } @@ -134,7 +137,8 @@ public class AddServerViewModel : MyReactiveObject WgMtu = protocolExtra?.WgMtu ?? 1280; Uot = protocolExtra?.Uot ?? false; CongestionControl = protocolExtra?.CongestionControl ?? string.Empty; - InsecureConcurrency = protocolExtra?.InsecureConcurrency ?? 0; + InsecureConcurrency = protocolExtra?.InsecureConcurrency > 0 ? protocolExtra.InsecureConcurrency : null; + NaiveQuic = protocolExtra?.NaiveQuic ?? false; } private async Task SaveServerAsync() @@ -199,7 +203,8 @@ public class AddServerViewModel : MyReactiveObject WgMtu = WgMtu >= 576 ? WgMtu : null, Uot = Uot ? true : null, CongestionControl = CongestionControl.NullIfEmpty(), - InsecureConcurrency = InsecureConcurrency > 0 ? InsecureConcurrency : null + InsecureConcurrency = InsecureConcurrency > 0 ? InsecureConcurrency : null, + NaiveQuic = NaiveQuic ? true : null, }); if (await ConfigHandler.AddServer(_config, SelectedSource) == 0) diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml index 4da1ae82..4dc378b4 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml @@ -497,7 +497,7 @@ VerticalAlignment="Center" Text="{x:Static resx:ResUI.TbHeaderType8}" /> - + + VerticalAlignment="Center" + Orientation="Horizontal"> + + + - + + Margin="{StaticResource Margin4}" + HorizontalAlignment="Left" /> cmbFingerprint.SelectedValue = string.Empty; gridFinalmask.IsVisible = false; - cmbHeaderType8.ItemsSource = Global.TuicCongestionControls; + cmbCongestionControl8.ItemsSource = Global.TuicCongestionControls; break; case EConfigType.WireGuard: @@ -103,14 +103,18 @@ public partial class AddServerWindow : WindowBase case EConfigType.Naive: gridNaive.IsVisible = true; + sepa2.IsVisible = false; + gridTransport.IsVisible = false; cmbCoreType.IsEnabled = false; gridFinalmask.IsVisible = false; cmbFingerprint.IsEnabled = false; cmbFingerprint.SelectedValue = string.Empty; + cmbAlpn.IsEnabled = false; + cmbAlpn.SelectedValue = string.Empty; cmbAllowInsecure.IsEnabled = false; cmbAllowInsecure.SelectedValue = string.Empty; - cmbHeaderType12.ItemsSource = Global.NaiveCongestionControls; + cmbCongestionControl12.ItemsSource = Global.NaiveCongestionControls; break; } cmbStreamSecurity.ItemsSource = lstStreamSecurity; @@ -171,7 +175,7 @@ public partial class AddServerWindow : WindowBase case EConfigType.TUIC: this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId8.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity8.Text).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbHeaderType8.SelectedValue).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbCongestionControl8.SelectedValue).DisposeWith(disposables); break; case EConfigType.WireGuard: @@ -189,8 +193,10 @@ public partial class AddServerWindow : WindowBase case EConfigType.Naive: this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId12.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity12.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.NaiveQuic, v => v.togNaiveQuic12.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.NaiveQuic, v => v.cmbCongestionControl12.IsEnabled).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbCongestionControl12.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.InsecureConcurrency, v => v.txtInsecureConcurrency12.Text).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbHeaderType12.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.Uot, v => v.togUotEnabled12.IsChecked).DisposeWith(disposables); break; } diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml b/v2rayN/v2rayN/Views/AddServerWindow.xaml index b87493e7..1eb28d9d 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml @@ -660,7 +660,7 @@ Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.TbHeaderType8}" /> - + + VerticalAlignment="Center" + Orientation="Horizontal"> + + + - + + HorizontalAlignment="Left" + Style="{StaticResource DefTextBox}" /> vm.SelectedSource.Username, v => v.txtId8.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity8.Text).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbHeaderType8.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbCongestionControl8.Text).DisposeWith(disposables); break; case EConfigType.WireGuard: @@ -184,8 +188,9 @@ public partial class AddServerWindow case EConfigType.Naive: this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId12.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity12.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.NaiveQuic, v => v.togNaiveQuic12.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbCongestionControl12.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.InsecureConcurrency, v => v.txtInsecureConcurrency12.Text).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.CongestionControl, v => v.cmbHeaderType12.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.Uot, v => v.togUotEnabled12.IsChecked).DisposeWith(disposables); break; }