diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs index 3509e2e2..d0b03774 100644 --- a/v2rayN/ServiceLib/Global.cs +++ b/v2rayN/ServiceLib/Global.cs @@ -187,6 +187,7 @@ public static readonly List DomainMatchers = new() { "linear", "mph", "" }; public static readonly List Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" }; public static readonly List UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" }; + public static readonly List XhttpMode = new() { "auto", "packet-up", "stream-up" }; public static readonly List AllowInsecure = new() { "true", "false", "" }; public static readonly List DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" }; @@ -206,9 +207,9 @@ public static readonly List SingboxMuxs = new() { "h2mux", "smux", "yamux", "" }; public static readonly List TuicCongestionControls = new() { "cubic", "new_reno", "bbr" }; - public static readonly List allowSelectType = new List { "selector", "urltest", "loadbalance", "fallback" }; - public static readonly List notAllowTestType = new List { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" }; - public static readonly List proxyVehicleType = new List { "file", "http" }; + public static readonly List allowSelectType = new() { "selector", "urltest", "loadbalance", "fallback" }; + public static readonly List notAllowTestType = new() { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" }; + public static readonly List proxyVehicleType = new() { "file", "http" }; #endregion const } diff --git a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs index 00663e6f..374fd9cb 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs @@ -83,6 +83,16 @@ namespace ServiceLib.Handler.Fmt case nameof(ETransport.ws): case nameof(ETransport.httpupgrade): + if (Utils.IsNotEmpty(item.RequestHost)) + { + dicQuery.Add("host", Utils.UrlEncode(item.RequestHost)); + } + if (Utils.IsNotEmpty(item.Path)) + { + dicQuery.Add("path", Utils.UrlEncode(item.Path)); + } + break; + case nameof(ETransport.splithttp): case nameof(ETransport.xhttp): if (Utils.IsNotEmpty(item.RequestHost)) @@ -93,6 +103,10 @@ namespace ServiceLib.Handler.Fmt { dicQuery.Add("path", Utils.UrlEncode(item.Path)); } + if (Utils.IsNotEmpty(item.HeaderType) && Global.XhttpMode.Contains(item.HeaderType)) + { + dicQuery.Add("mode", Utils.UrlEncode(item.HeaderType)); + } break; case nameof(ETransport.http): @@ -157,10 +171,15 @@ namespace ServiceLib.Handler.Fmt case nameof(ETransport.ws): case nameof(ETransport.httpupgrade): + item.RequestHost = Utils.UrlDecode(query["host"] ?? ""); + item.Path = Utils.UrlDecode(query["path"] ?? "/"); + break; + case nameof(ETransport.splithttp): case nameof(ETransport.xhttp): item.RequestHost = Utils.UrlDecode(query["host"] ?? ""); item.Path = Utils.UrlDecode(query["path"] ?? "/"); + item.HeaderType = Utils.UrlDecode(query["mode"] ?? ""); break; case nameof(ETransport.http): diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index 1edb383d..710d627f 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -348,6 +348,7 @@ namespace ServiceLib.Models { public string? path { get; set; } public string? host { get; set; } + public string? mode { get; set; } public string? scMaxEachPostBytes { get; set; } public string? scMaxConcurrentPosts { get; set; } public string? scMinPostsIntervalMs { get; set; } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 2eaaaa8a..76229529 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -3733,6 +3733,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 *xhttp mode 的本地化字符串。 + /// + public static string TransportHeaderTypeTip5 { + get { + return ResourceManager.GetString("TransportHeaderTypeTip5", resourceCulture); + } + } + /// /// 查找类似 *ws/httpupgrade/xhttp path 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 099887ef..917a82fc 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1381,4 +1381,7 @@ Please do not run this app with sudo + + *xhttp mode + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index d952cbbb..22f7d4c2 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1381,4 +1381,7 @@ Please do not run this app with sudo + + *xhttp mode + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 255b578e..a7e16f18 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1381,4 +1381,7 @@ Please do not run this app with sudo + + *xhttp mode + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 9b86c88a..fc83b374 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1378,4 +1378,7 @@ 请不要用sudo运行本app + + *xhttp 模式 + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index c93f92fa..898ab7f6 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1366,7 +1366,7 @@ 混淆密碼(obfs password) - + Linux系統的sudo密碼 @@ -1378,4 +1378,7 @@ 請不要用sudo來運行本app + + *xhttp 模式 + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs index 1babb504..511498b9 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs @@ -945,6 +945,11 @@ namespace ServiceLib.Services.CoreConfig { xhttpSettings.host = host; } + if (Utils.IsNotEmpty(node.HeaderType) && Global.XhttpMode.Contains(node.HeaderType)) + { + xhttpSettings.mode = node.HeaderType; + } + streamSettings.xhttpSettings = xhttpSettings; break; diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs index 9f8dc83b..7e2fba9a 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs @@ -299,6 +299,13 @@ namespace v2rayN.Desktop.Views cmbHeaderType.Items.Add(it); }); } + else if (network is nameof(ETransport.splithttp) or nameof(ETransport.xhttp)) + { + Global.XhttpMode.ForEach(it => + { + cmbHeaderType.Items.Add(it); + }); + } else if (network == nameof(ETransport.grpc)) { cmbHeaderType.Items.Add(Global.GrpcGunMode); @@ -337,10 +344,16 @@ namespace v2rayN.Desktop.Views case nameof(ETransport.ws): case nameof(ETransport.httpupgrade): + tipRequestHost.Text = ResUI.TransportRequestHostTip2; + tipPath.Text = ResUI.TransportPathTip1; + break; + case nameof(ETransport.splithttp): case nameof(ETransport.xhttp): tipRequestHost.Text = ResUI.TransportRequestHostTip2; tipPath.Text = ResUI.TransportPathTip1; + tipHeaderType.Text = ResUI.TransportHeaderTypeTip5; + labHeaderType.IsVisible = false; break; case nameof(ETransport.h2): diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs index 7b3c531b..24c8d637 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs @@ -294,6 +294,13 @@ namespace v2rayN.Views cmbHeaderType.Items.Add(it); }); } + else if (network is nameof(ETransport.splithttp) or nameof(ETransport.xhttp)) + { + Global.XhttpMode.ForEach(it => + { + cmbHeaderType.Items.Add(it); + }); + } else if (network == nameof(ETransport.grpc)) { cmbHeaderType.Items.Add(Global.GrpcGunMode); @@ -332,10 +339,16 @@ namespace v2rayN.Views case nameof(ETransport.ws): case nameof(ETransport.httpupgrade): + tipRequestHost.Text = ResUI.TransportRequestHostTip2; + tipPath.Text = ResUI.TransportPathTip1; + break; + case nameof(ETransport.splithttp): case nameof(ETransport.xhttp): tipRequestHost.Text = ResUI.TransportRequestHostTip2; tipPath.Text = ResUI.TransportPathTip1; + tipHeaderType.Text = ResUI.TransportHeaderTypeTip5; + labHeaderType.Visibility = Visibility.Hidden; break; case nameof(ETransport.h2):