Compare commits

..

7 commits

Author SHA1 Message Date
DHR60
366daef7c5 Fix
Fix raw http ui

Fill xhttp default mode

Fix share uri

Remove RawHost

Fix singbox tcp http path

Fix vmess share uri
2026-03-29 17:22:58 +08:00
DHR60
8de4ba082d Fix 2026-03-29 17:22:58 +08:00
DHR60
0458df7b69 Rename tcp to raw 2026-03-29 17:22:58 +08:00
DHR60
40770dd250 Refactor transport 2026-03-29 17:22:58 +08:00
2dust
1090afd774 up 7.20.0
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release Linux / deb (push) Blocked by required conditions
release Linux / rpm (push) Blocked by required conditions
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run
2026-03-29 15:05:55 +08:00
2dust
c758c5abf9 Update Directory.Packages.props 2026-03-29 15:05:30 +08:00
DHR60
c61b023ab3
Allow enable legacy process name tun protect (#9005) 2026-03-29 14:44:04 +08:00
33 changed files with 331 additions and 177 deletions

View file

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>7.19.5</Version>
<Version>7.20.0</Version>
</PropertyGroup>
<PropertyGroup>

View file

@ -6,11 +6,11 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.12" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.12" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.12" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.13" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.13" />
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.12" />
<PackageVersion Include="CliWrap" Version="3.10.0" />
<PackageVersion Include="CliWrap" Version="3.10.1" />
<PackageVersion Include="Downloader" Version="5.1.0" />
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.4.1" />
<PackageVersion Include="MaterialDesignThemes" Version="5.3.1" />

View file

@ -45,6 +45,8 @@ public class Global
public const string DefaultNetwork = "raw";
public const string RawHeaderHttp = "http";
public const string None = "none";
public const string RawNetworkAlias = "tcp";
public const string DefaultXhttpMode = "auto";
public const string ProxyTag = "proxy";
public const string DirectTag = "direct";
public const string BlockTag = "block";

View file

@ -92,6 +92,7 @@ public static class ConfigHandler
EnableTun = false,
Mtu = 9000,
IcmpRouting = Global.TunIcmpRoutingPolicies.First(),
EnableLegacyProtect = false,
};
config.GuiItem ??= new();
config.MsgUIItem ??= new();
@ -1138,7 +1139,6 @@ public static class ConfigHandler
&& AreEqual(oProtocolExtra.VmessSecurity, nProtocolExtra.VmessSecurity)
&& AreEqual(o.Network, n.Network)
&& AreEqual(oTransport.RawHeaderType, nTransport.RawHeaderType)
&& AreEqual(oTransport.RawHost, nTransport.RawHost)
&& AreEqual(oTransport.Host, nTransport.Host)
&& AreEqual(oTransport.Path, nTransport.Path)
&& AreEqual(oTransport.XhttpMode, nTransport.XhttpMode)
@ -1416,19 +1416,32 @@ public static class ConfigHandler
/// <returns>A SOCKS profile item or null if not needed</returns>
public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
{
if (node.ConfigType != EConfigType.Custom || !(node.PreSocksPort > 0))
{
return null;
}
ProfileItem? itemSocks = null;
var preCoreType = AppManager.Instance.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
itemSocks = new ProfileItem()
if (node.ConfigType != EConfigType.Custom
&& coreType != ECoreType.sing_box
&& config.TunModeItem.EnableTun
&& config.TunModeItem.EnableLegacyProtect)
{
CoreType = preCoreType,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Port = node.PreSocksPort.Value,
};
itemSocks = new ProfileItem()
{
CoreType = ECoreType.sing_box,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks)
};
}
else if (node.ConfigType == EConfigType.Custom
&& node.PreSocksPort is > 0 and <= 65535)
{
var preCoreType = AppManager.Instance.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
itemSocks = new ProfileItem()
{
CoreType = preCoreType,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Port = node.PreSocksPort.Value,
};
}
return itemSocks;
}

View file

@ -5,6 +5,7 @@ namespace ServiceLib.Handler.Fmt;
public class BaseFmt
{
private static readonly string[] _allowInsecureArray = new[] { "insecure", "allowInsecure", "allow_insecure" };
private static string UrlEncodeSafe(string? value) => Utils.UrlEncode(value ?? string.Empty);
protected static string GetIpv6(string address)
{
@ -95,15 +96,20 @@ public class BaseFmt
network = nameof(ETransport.raw);
}
dicQuery.Add("type", network);
//dicQuery.Add("type", network);
dicQuery.Add("type", network == nameof(ETransport.raw) ? Global.RawNetworkAlias : network);
switch (network)
{
case nameof(ETransport.raw):
dicQuery.Add("headerType", transport.RawHeaderType.IsNotEmpty() ? transport.RawHeaderType : Global.None);
if (transport.RawHost.IsNotEmpty())
if (transport.Host.IsNotEmpty())
{
dicQuery.Add("host", Utils.UrlEncode(transport.RawHost));
dicQuery.Add("host", UrlEncodeSafe(transport.Host));
}
if (transport.Path.IsNotEmpty())
{
dicQuery.Add("path", UrlEncodeSafe(transport.Path));
}
break;
@ -111,44 +117,34 @@ public class BaseFmt
dicQuery.Add("headerType", transport.KcpHeaderType.IsNotEmpty() ? transport.KcpHeaderType : Global.None);
if (transport.KcpSeed.IsNotEmpty())
{
dicQuery.Add("seed", Utils.UrlEncode(transport.KcpSeed));
dicQuery.Add("seed", UrlEncodeSafe(transport.KcpSeed));
}
break;
case nameof(ETransport.ws):
if (transport.Host.IsNotEmpty())
{
dicQuery.Add("host", Utils.UrlEncode(transport.Host));
}
if (transport.Path.IsNotEmpty())
{
dicQuery.Add("path", Utils.UrlEncode(transport.Path));
}
break;
case nameof(ETransport.httpupgrade):
if (transport.Host.IsNotEmpty())
{
dicQuery.Add("host", Utils.UrlEncode(transport.Host));
dicQuery.Add("host", UrlEncodeSafe(transport.Host));
}
if (transport.Path.IsNotEmpty())
{
dicQuery.Add("path", Utils.UrlEncode(transport.Path));
dicQuery.Add("path", UrlEncodeSafe(transport.Path));
}
break;
case nameof(ETransport.xhttp):
if (transport.Host.IsNotEmpty())
{
dicQuery.Add("host", Utils.UrlEncode(transport.Host));
dicQuery.Add("host", UrlEncodeSafe(transport.Host));
}
if (transport.Path.IsNotEmpty())
{
dicQuery.Add("path", Utils.UrlEncode(transport.Path));
dicQuery.Add("path", UrlEncodeSafe(transport.Path));
}
if (transport.XhttpMode.IsNotEmpty() && Global.XhttpMode.Contains(transport.XhttpMode))
{
dicQuery.Add("mode", Utils.UrlEncode(transport.XhttpMode));
dicQuery.Add("mode", UrlEncodeSafe(transport.XhttpMode));
}
if (transport.XhttpExtra.IsNotEmpty())
{
@ -161,18 +157,18 @@ public class BaseFmt
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})
: transport.XhttpExtra;
dicQuery.Add("extra", Utils.UrlEncode(extra));
dicQuery.Add("extra", UrlEncodeSafe(extra));
}
break;
case nameof(ETransport.grpc):
if (transport.GrpcServiceName.IsNotEmpty())
{
dicQuery.Add("authority", Utils.UrlEncode(transport.GrpcAuthority));
dicQuery.Add("serviceName", Utils.UrlEncode(transport.GrpcServiceName));
dicQuery.Add("authority", UrlEncodeSafe(transport.GrpcAuthority));
dicQuery.Add("serviceName", UrlEncodeSafe(transport.GrpcServiceName));
if (transport.GrpcMode is Global.GrpcGunMode or Global.GrpcMultiMode)
{
dicQuery.Add("mode", Utils.UrlEncode(transport.GrpcMode));
dicQuery.Add("mode", UrlEncodeSafe(transport.GrpcMode));
}
}
break;
@ -260,6 +256,10 @@ public class BaseFmt
}
var net = GetQueryValue(query, "type", nameof(ETransport.raw));
if (net == Global.RawNetworkAlias)
{
net = nameof(ETransport.raw);
}
if (!Global.Networks.Contains(net))
{
net = nameof(ETransport.raw);
@ -272,7 +272,8 @@ public class BaseFmt
transport = transport with
{
RawHeaderType = GetQueryValue(query, "headerType", Global.None),
RawHost = GetQueryDecoded(query, "host"),
Host = GetQueryDecoded(query, "host"),
Path = GetQueryDecoded(query, "path"),
};
break;
@ -286,13 +287,6 @@ public class BaseFmt
break;
case nameof(ETransport.ws):
transport = transport with
{
Host = GetQueryDecoded(query, "host"),
Path = GetQueryDecoded(query, "path", "/"),
};
break;
case nameof(ETransport.httpupgrade):
transport = transport with
{

View file

@ -51,7 +51,7 @@ public class ShadowsocksFmt : BaseFmt
if (item.Network == nameof(ETransport.raw) && transport.RawHeaderType == Global.RawHeaderHttp)
{
plugin = "obfs-local";
pluginArgs = $"obfs=http;obfs-host={transport.RawHost};";
pluginArgs = $"obfs=http;obfs-host={transport.Host};";
}
else
{
@ -213,7 +213,7 @@ public class ShadowsocksFmt : BaseFmt
item.SetTransportExtra(item.GetTransportExtra() with
{
RawHeaderType = Global.RawHeaderHttp,
RawHost = obfsHost,
Host = obfsHost,
});
}
}

View file

@ -34,7 +34,7 @@ public class VmessFmt : BaseFmt
id = item.Password,
aid = int.TryParse(item.GetProtocolExtra()?.AlterId, out var result) ? result : 0,
scy = item.GetProtocolExtra().VmessSecurity ?? "",
net = item.Network,
net = item.GetNetwork() == nameof(ETransport.raw) ? Global.RawNetworkAlias : item.Network,
type = item.GetNetwork() switch
{
nameof(ETransport.raw) => item.GetTransportExtra().RawHeaderType,
@ -45,7 +45,7 @@ public class VmessFmt : BaseFmt
},
host = item.GetNetwork() switch
{
nameof(ETransport.raw) => item.GetTransportExtra().RawHost,
nameof(ETransport.raw) => item.GetTransportExtra().Host,
nameof(ETransport.ws) => item.GetTransportExtra().Host,
nameof(ETransport.httpupgrade) => item.GetTransportExtra().Host,
nameof(ETransport.xhttp) => item.GetTransportExtra().Host,
@ -54,6 +54,7 @@ public class VmessFmt : BaseFmt
},
path = item.GetNetwork() switch
{
nameof(ETransport.raw) => item.GetTransportExtra().Path,
nameof(ETransport.kcp) => item.GetTransportExtra().KcpSeed,
nameof(ETransport.ws) => item.GetTransportExtra().Path,
nameof(ETransport.httpupgrade) => item.GetTransportExtra().Path,
@ -111,7 +112,7 @@ public class VmessFmt : BaseFmt
});
if (vmessQRCode.net.IsNotEmpty())
{
item.Network = vmessQRCode.net;
item.Network = vmessQRCode.net == Global.RawNetworkAlias ? nameof(ETransport.raw) : vmessQRCode.net;
}
if (vmessQRCode.type.IsNotEmpty())
{
@ -126,7 +127,7 @@ public class VmessFmt : BaseFmt
}
transport = item.GetNetwork() switch
{
nameof(ETransport.raw) => transport with { RawHost = Utils.ToString(vmessQRCode.host) },
nameof(ETransport.raw) => transport with { Host = Utils.ToString(vmessQRCode.host), Path = Utils.ToString(vmessQRCode.path) },
nameof(ETransport.kcp) => transport with { KcpSeed = Utils.ToString(vmessQRCode.path) },
nameof(ETransport.ws) => transport with { Host = Utils.ToString(vmessQRCode.host), Path = Utils.ToString(vmessQRCode.path) },
nameof(ETransport.httpupgrade) => transport with { Host = Utils.ToString(vmessQRCode.host), Path = Utils.ToString(vmessQRCode.path) },
@ -164,7 +165,7 @@ public class VmessFmt : BaseFmt
item.SetProtocolExtra(new ProtocolExtraItem
{
VmessSecurity = "auto",
VmessSecurity = Global.DefaultSecurity,
});
var query = Utils.ParseQueryString(url.Query);

View file

@ -361,7 +361,7 @@ public sealed class AppManager
{
try
{
if (item.Network == "tcp")
if (item.Network == Global.RawNetworkAlias)
{
item.Network = nameof(ETransport.raw);
}
@ -375,7 +375,8 @@ public sealed class AppManager
transport = transport with
{
RawHeaderType = item.HeaderType.NullIfEmpty(),
RawHost = item.RequestHost.NullIfEmpty(),
Host = item.RequestHost.NullIfEmpty(),
Path = item.Path.NullIfEmpty(),
};
break;
@ -420,7 +421,7 @@ public sealed class AppManager
transport = transport with
{
RawHeaderType = item.HeaderType.NullIfEmpty(),
RawHost = item.RequestHost.NullIfEmpty(),
Host = item.RequestHost.NullIfEmpty(),
};
break;
}

View file

@ -145,6 +145,7 @@ public class TunModeItem
public int Mtu { get; set; }
public bool EnableIPv6Address { get; set; }
public string IcmpRouting { get; set; }
public bool EnableLegacyProtect { get; set; }
}
[Serializable]

View file

@ -169,7 +169,7 @@ public class ProfileItem
public string Network { get; set; }
[Obsolete("Use TransportExtra.RawHeaderType/XhttpMode/GrpcMode/KcpHeaderType instead.")]
public string HeaderType { get; set; }
[Obsolete("Use TransportExtra.RawHost/Host/GrpcAuthority instead.")]
[Obsolete("Use TransportExtra.Host/GrpcAuthority instead.")]
public string RequestHost { get; set; }
[Obsolete("Use TransportExtra.Path/GrpcServiceName/KcpSeed instead.")]
public string Path { get; set; }

View file

@ -3,7 +3,6 @@ namespace ServiceLib.Models;
public record TransportExtra
{
public string? RawHeaderType { get; init; }
public string? RawHost { get; init; }
public string? Host { get; init; }
public string? Path { get; init; }

View file

@ -3150,6 +3150,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Legacy TUN Protect 的本地化字符串。
/// </summary>
public static string TbLegacyProtect {
get {
return ResourceManager.GetString("TbLegacyProtect", resourceCulture);
}
}
/// <summary>
/// 查找类似 Address (IPv4, IPv6) 的本地化字符串。
/// </summary>

View file

@ -1695,4 +1695,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP routing policy</value>
</data>
<data name="TbLegacyProtect" xml:space="preserve">
<value>Legacy TUN Protect</value>
</data>
</root>

View file

@ -1692,4 +1692,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP routing policy</value>
</data>
<data name="TbLegacyProtect" xml:space="preserve">
<value>Legacy TUN Protect</value>
</data>
</root>

View file

@ -1695,4 +1695,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP routing policy</value>
</data>
<data name="TbLegacyProtect" xml:space="preserve">
<value>Legacy TUN Protect</value>
</data>
</root>

View file

@ -1695,4 +1695,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP routing policy</value>
</data>
<data name="TbLegacyProtect" xml:space="preserve">
<value>Legacy TUN Protect</value>
</data>
</root>

View file

@ -1695,4 +1695,7 @@
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP routing policy</value>
</data>
</root>
<data name="TbLegacyProtect" xml:space="preserve">
<value>Legacy TUN Protect</value>
</data>
</root>

View file

@ -1692,4 +1692,7 @@
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP 路由策略</value>
</data>
<data name="TbLegacyProtect" xml:space="preserve">
<value>旧版 TUN 保护</value>
</data>
</root>

View file

@ -1692,4 +1692,7 @@
<data name="TbIcmpRoutingPolicy" xml:space="preserve">
<value>ICMP 路由策略</value>
</data>
</root>
<data name="TbLegacyProtect" xml:space="preserve">
<value>Legacy TUN Protect</value>
</data>
</root>

View file

@ -61,7 +61,8 @@ public partial class CoreConfigSingboxService(CoreConfigContext context)
ret.Success = true;
ret.Data = ApplyFullConfigTemplate();
if (context.TunProtectSsPort is > 0 and <= 65535)
if (!context.AppConfig.TunModeItem.EnableLegacyProtect
&& context.TunProtectSsPort is > 0 and <= 65535)
{
var ssInbound = new
{

View file

@ -119,7 +119,7 @@ public partial class CoreConfigSingboxService
if (network == nameof(ETransport.raw) && transportExtra.RawHeaderType == Global.RawHeaderHttp)
{
outbound.plugin = "obfs-local";
outbound.plugin_opts = $"obfs=http;obfs-host={transportExtra.RawHost};";
outbound.plugin_opts = $"obfs=http;obfs-host={transportExtra.Host};";
}
else
{
@ -383,7 +383,7 @@ public partial class CoreConfigSingboxService
{
var host = _node.GetNetwork() switch
{
nameof(ETransport.raw) => _node.GetTransportExtra().RawHost,
nameof(ETransport.raw) => _node.GetTransportExtra().Host,
nameof(ETransport.ws) => _node.GetTransportExtra().Host,
nameof(ETransport.httpupgrade) => _node.GetTransportExtra().Host,
nameof(ETransport.xhttp) => _node.GetTransportExtra().Host,
@ -453,7 +453,8 @@ public partial class CoreConfigSingboxService
if (transportExtra.RawHeaderType == Global.RawHeaderHttp)
{
transport.type = nameof(ETransport.http);
transport.host = transportExtra.RawHost.IsNullOrEmpty() ? null : Utils.String2List(transportExtra.RawHost);
transport.host = transportExtra.Host.IsNullOrEmpty() ? null : Utils.String2List(transportExtra.Host);
transport.path = transportExtra.Path.NullIfEmpty();
}
break;

View file

@ -15,7 +15,10 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
var ret = new RetResult();
try
{
if (context.IsTunEnabled && context.TunProtectSsPort > 0 && context.ProxyRelaySsPort > 0)
if (!context.AppConfig.TunModeItem.EnableLegacyProtect
&& context.IsTunEnabled
&& context.TunProtectSsPort is > 0 and <= 65535
&& context.ProxyRelaySsPort is > 0 and <= 65535)
{
return GenerateClientProxyRelayConfig();
}

View file

@ -357,7 +357,8 @@ public partial class CoreConfigV2rayService
switch (network)
{
case nameof(ETransport.raw):
host = transport.RawHost?.TrimEx() ?? string.Empty;
host = transport.Host?.TrimEx() ?? string.Empty;
path = transport.Path?.TrimEx() ?? string.Empty;
headerType = transport.RawHeaderType?.TrimEx() ?? string.Empty;
break;

View file

@ -76,9 +76,6 @@ public class AddServerViewModel : MyReactiveObject
[Reactive]
public string RawHeaderType { get; set; }
[Reactive]
public string RawHost { get; set; }
[Reactive]
public string Host { get; set; }
@ -141,7 +138,7 @@ public class AddServerViewModel : MyReactiveObject
{
get => SelectedSource.GetNetwork() switch
{
nameof(ETransport.raw) => RawHost,
nameof(ETransport.raw) => Host,
nameof(ETransport.ws) => Host,
nameof(ETransport.httpupgrade) => Host,
nameof(ETransport.xhttp) => Host,
@ -153,7 +150,7 @@ public class AddServerViewModel : MyReactiveObject
switch (SelectedSource.GetNetwork())
{
case nameof(ETransport.raw):
RawHost = value;
Host = value;
break;
case nameof(ETransport.ws):
Host = value;
@ -298,10 +295,9 @@ public class AddServerViewModel : MyReactiveObject
NaiveQuic = protocolExtra?.NaiveQuic ?? false;
RawHeaderType = transport.RawHeaderType ?? Global.None;
RawHost = transport.RawHost ?? string.Empty;
Host = transport.Host ?? string.Empty;
Path = transport.Path ?? string.Empty;
XhttpMode = transport.XhttpMode ?? string.Empty;
XhttpMode = transport.XhttpMode ?? Global.DefaultXhttpMode;
XhttpExtra = transport.XhttpExtra ?? string.Empty;
GrpcAuthority = transport.GrpcAuthority ?? string.Empty;
GrpcServiceName = transport.GrpcServiceName ?? string.Empty;
@ -363,7 +359,6 @@ public class AddServerViewModel : MyReactiveObject
var transport = new TransportExtra
{
RawHeaderType = RawHeaderType.NullIfEmpty(),
RawHost = RawHost.NullIfEmpty(),
Host = Host.NullIfEmpty(),
Path = Path.NullIfEmpty(),
XhttpMode = XhttpMode.NullIfEmpty(),
@ -497,7 +492,7 @@ public class AddServerViewModel : MyReactiveObject
{
return SelectedSource.GetNetwork() switch
{
nameof(ETransport.raw) => RawHost,
nameof(ETransport.raw) => Host,
nameof(ETransport.ws) => Host,
nameof(ETransport.httpupgrade) => Host,
nameof(ETransport.xhttp) => Host,

View file

@ -96,6 +96,7 @@ public class OptionSettingViewModel : MyReactiveObject
[Reactive] public int TunMtu { get; set; }
[Reactive] public bool TunEnableIPv6Address { get; set; }
[Reactive] public string TunIcmpRouting { get; set; }
[Reactive] public bool TunEnableLegacyProtect { get; set; }
#endregion Tun mode
@ -220,6 +221,7 @@ public class OptionSettingViewModel : MyReactiveObject
TunMtu = _config.TunModeItem.Mtu;
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
TunIcmpRouting = _config.TunModeItem.IcmpRouting;
TunEnableLegacyProtect = _config.TunModeItem.EnableLegacyProtect;
#endregion Tun mode
@ -379,6 +381,7 @@ public class OptionSettingViewModel : MyReactiveObject
_config.TunModeItem.Mtu = TunMtu;
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
_config.TunModeItem.IcmpRouting = TunIcmpRouting;
_config.TunModeItem.EnableLegacyProtect = TunEnableLegacyProtect;
//coreType
await SaveCoreType();

View file

@ -718,33 +718,54 @@
<Grid Grid.Row="2">
<Grid
x:Name="gridTransportRaw"
ColumnDefinitions="300,Auto"
IsVisible="False"
RowDefinitions="Auto,Auto">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbHeaderType}" />
<ComboBox
x:Name="cmbHeaderTypeRaw"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
<TextBlock
<Grid Grid.Row="0" ColumnDefinitions="300,Auto">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbHeaderType}" />
<ComboBox
x:Name="cmbHeaderTypeRaw"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
</Grid>
<Grid
x:Name="gridTransportRawHttp"
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbRequestHost}" />
<TextBox
x:Name="txtRequestHostRaw"
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}" />
ColumnDefinitions="300,Auto"
IsVisible="False"
RowDefinitions="Auto,Auto">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbRequestHost}" />
<TextBox
x:Name="txtRequestHostRaw"
Grid.Row="0"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbPath}" />
<TextBox
x:Name="txtPathRaw"
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}" />
</Grid>
</Grid>
<Grid

View file

@ -16,6 +16,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
Loaded += Window_Loaded;
btnCancel.Click += (s, e) => Close();
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
cmbHeaderTypeRaw.SelectionChanged += CmbHeaderTypeRaw_SelectionChanged;
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;
btnGUID.Click += btnGUID_Click;
btnGUID5.Click += btnGUID_Click;
@ -24,6 +25,16 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
cmbCoreType.ItemsSource = Global.CoreTypes.AppendEmpty();
cmbNetwork.ItemsSource = Global.Networks;
cmbHeaderTypeRaw.ItemsSource = new List<string> { Global.None, Global.RawHeaderHttp };
var kcpHeaderTypes = new List<string> { Global.None };
kcpHeaderTypes.AddRange(Global.KcpHeaderTypes);
cmbHeaderTypeKcp.ItemsSource = kcpHeaderTypes;
cmbHeaderTypeXhttp.ItemsSource = Global.XhttpMode;
cmbHeaderTypeGrpc.ItemsSource = new List<string> { Global.GrpcGunMode, Global.GrpcMultiMode };
cmbFingerprint.ItemsSource = Global.Fingerprints;
cmbFingerprint2.ItemsSource = Global.Fingerprints;
cmbAllowInsecure.ItemsSource = Global.AllowInsecure;
@ -202,7 +213,8 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
}
this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RawHeaderType, v => v.cmbHeaderTypeRaw.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RawHost, v => v.txtRequestHostRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Host, v => v.txtRequestHostRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Path, v => v.txtPathRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KcpHeaderType, v => v.cmbHeaderTypeKcp.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KcpSeed, v => v.txtKcpSeed.Text).DisposeWith(disposables);
@ -269,8 +281,12 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
private void CmbNetwork_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
SetHeaderType();
SetTips();
SetTransportGridVisibility();
}
private void CmbHeaderTypeRaw_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
SetRawHttpFieldsVisibility();
}
private void CmbStreamSecurity_SelectionChanged(object? sender, SelectionChangedEventArgs e)
@ -299,25 +315,6 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
txtId5.Text = Utils.GetGuid();
}
private void SetHeaderType()
{
cmbHeaderTypeRaw.ItemsSource = new List<string> { Global.None, Global.RawHeaderHttp };
var kcpHeaderTypes = new List<string> { Global.None };
kcpHeaderTypes.AddRange(Global.KcpHeaderTypes);
cmbHeaderTypeKcp.ItemsSource = kcpHeaderTypes;
cmbHeaderTypeXhttp.ItemsSource = Global.XhttpMode;
cmbHeaderTypeGrpc.ItemsSource = new List<string> { Global.GrpcGunMode, Global.GrpcMultiMode };
SetTransportGridVisibility();
}
private void SetTips()
{
SetTransportGridVisibility();
}
private void SetTransportGridVisibility()
{
var network = cmbNetwork.SelectedItem?.ToString();
@ -357,5 +354,21 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
gridTransportRaw.IsVisible = true;
break;
}
SetRawHttpFieldsVisibility();
}
private void SetRawHttpFieldsVisibility()
{
var network = cmbNetwork.SelectedItem?.ToString();
if (network.IsNullOrEmpty())
{
network = Global.DefaultNetwork;
}
var rawHeaderType = cmbHeaderTypeRaw.SelectedItem?.ToString();
var showRawHttpFields = network == nameof(ETransport.raw)
&& rawHeaderType == Global.RawHeaderHttp;
gridTransportRawHttp.IsVisible = showRawHttpFields;
}
}

View file

@ -768,7 +768,7 @@
Margin="{StaticResource Margin4}"
ColumnDefinitions="Auto,Auto,Auto"
DockPanel.Dock="Top"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock
Grid.Row="2"
@ -851,6 +851,18 @@
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="8"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbLegacyProtect}" />
<ToggleSwitch
x:Name="togEnableLegacyProtect"
Grid.Row="8"
Grid.Column="1"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
</Grid>
</TabItem>

View file

@ -116,6 +116,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunIcmpRouting, v => v.cmbIcmpRoutingPolicy.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunEnableLegacyProtect, v => v.togEnableLegacyProtect.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);

View file

@ -944,42 +944,73 @@
<Grid Grid.Row="2">
<Grid x:Name="gridTransportRaw" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbHeaderType}" />
<ComboBox
x:Name="cmbHeaderTypeRaw"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
<TextBlock
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbHeaderType}" />
<ComboBox
x:Name="cmbHeaderTypeRaw"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
x:Name="gridTransportRawHttp"
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRequestHost}" />
<TextBox
x:Name="txtRequestHostRaw"
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRequestHost}" />
<TextBox
x:Name="txtRequestHostRaw"
Grid.Row="0"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPath}" />
<TextBox
x:Name="txtPathRaw"
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
</Grid>
</Grid>
<Grid x:Name="gridTransportXhttp" Visibility="Collapsed">

View file

@ -11,6 +11,7 @@ public partial class AddServerWindow
Owner = Application.Current.MainWindow;
Loaded += Window_Loaded;
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
cmbHeaderTypeRaw.SelectionChanged += CmbHeaderTypeRaw_SelectionChanged;
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;
btnGUID.Click += btnGUID_Click;
btnGUID5.Click += btnGUID_Click;
@ -23,6 +24,16 @@ public partial class AddServerWindow
{
ViewModel.SelectedSource.Network = Global.DefaultNetwork;
}
cmbHeaderTypeRaw.ItemsSource = new List<string> { Global.None, Global.RawHeaderHttp };
var kcpHeaderTypes = new List<string> { Global.None };
kcpHeaderTypes.AddRange(Global.KcpHeaderTypes);
cmbHeaderTypeKcp.ItemsSource = kcpHeaderTypes;
cmbHeaderTypeXhttp.ItemsSource = Global.XhttpMode;
cmbHeaderTypeGrpc.ItemsSource = new List<string> { Global.GrpcGunMode, Global.GrpcMultiMode };
cmbFingerprint.ItemsSource = Global.Fingerprints;
cmbFingerprint2.ItemsSource = Global.Fingerprints;
cmbAllowInsecure.ItemsSource = Global.AllowInsecure;
@ -200,7 +211,8 @@ public partial class AddServerWindow
}
this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RawHeaderType, v => v.cmbHeaderTypeRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RawHost, v => v.txtRequestHostRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Host, v => v.txtRequestHostRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Path, v => v.txtPathRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KcpHeaderType, v => v.cmbHeaderTypeKcp.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KcpSeed, v => v.txtKcpSeed.Text).DisposeWith(disposables);
@ -269,8 +281,12 @@ public partial class AddServerWindow
private void CmbNetwork_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetHeaderType();
SetTips();
SetTransportGridVisibility();
}
private void CmbHeaderTypeRaw_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetRawHttpFieldsVisibility();
}
private void CmbStreamSecurity_SelectionChanged(object sender, SelectionChangedEventArgs e)
@ -299,25 +315,6 @@ public partial class AddServerWindow
txtId5.Text = Utils.GetGuid();
}
private void SetHeaderType()
{
cmbHeaderTypeRaw.ItemsSource = new List<string> { Global.None, Global.RawHeaderHttp };
var kcpHeaderTypes = new List<string> { Global.None };
kcpHeaderTypes.AddRange(Global.KcpHeaderTypes);
cmbHeaderTypeKcp.ItemsSource = kcpHeaderTypes;
cmbHeaderTypeXhttp.ItemsSource = Global.XhttpMode;
cmbHeaderTypeGrpc.ItemsSource = new List<string> { Global.GrpcGunMode, Global.GrpcMultiMode };
SetTransportGridVisibility();
}
private void SetTips()
{
SetTransportGridVisibility();
}
private void SetTransportGridVisibility()
{
var network = cmbNetwork.SelectedItem?.ToString();
@ -357,5 +354,23 @@ public partial class AddServerWindow
gridTransportRaw.Visibility = Visibility.Visible;
break;
}
SetRawHttpFieldsVisibility();
}
private void SetRawHttpFieldsVisibility()
{
var network = cmbNetwork.SelectedItem?.ToString();
if (network.IsNullOrEmpty())
{
network = Global.DefaultNetwork;
}
var rawHeaderType = cmbHeaderTypeRaw.SelectedItem?.ToString();
var showRawHttpFields = network == nameof(ETransport.raw)
&& rawHeaderType == Global.RawHeaderHttp;
gridTransportRawHttp.Visibility = showRawHttpFields
? Visibility.Visible
: Visibility.Collapsed;
}
}

View file

@ -1009,6 +1009,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -1105,6 +1106,20 @@
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="8"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbLegacyProtect}" />
<ToggleButton
x:Name="togEnableLegacyProtect"
Grid.Row="8"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
</Grid>
</TabItem>

View file

@ -121,6 +121,7 @@ public partial class OptionSettingWindow
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunIcmpRouting, v => v.cmbIcmpRoutingPolicy.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunEnableLegacyProtect, v => v.togEnableLegacyProtect.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.Text).DisposeWith(disposables);