mirror of
https://github.com/2dust/v2rayN.git
synced 2026-10-01 11:02:07 +03:00
Add MASQUE support (#10233)
* Add MASQUE support * Add SettingsCoreType
This commit is contained in:
@@ -501,6 +501,31 @@ public class Utils
|
||||
};
|
||||
}
|
||||
|
||||
public static List<(string, string)> ParseHeaders(string? headers)
|
||||
{
|
||||
var result = new List<(string, string)>();
|
||||
if (headers.IsNullOrEmpty())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
var lines = headers.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var parts = line.Split(new[] { ':' }, 2);
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var key = parts[0].Trim();
|
||||
var value = parts[1].Trim();
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
result.Add((key, value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion Conversion Functions
|
||||
|
||||
#region Data Checks
|
||||
|
||||
@@ -15,6 +15,7 @@ public enum EConfigType
|
||||
Anytls = 11,
|
||||
Naive = 12,
|
||||
Outbound = 13,
|
||||
MASQUE = 14,
|
||||
PolicyGroup = 101,
|
||||
ProxyChain = 102,
|
||||
}
|
||||
|
||||
@@ -261,7 +261,8 @@ public class Global
|
||||
{ EConfigType.TUIC, "tuic" },
|
||||
{ EConfigType.WireGuard, "wireguard" },
|
||||
{ EConfigType.Anytls, "anytls" },
|
||||
{ EConfigType.Naive, "naive" }
|
||||
{ EConfigType.Naive, "naive" },
|
||||
{ EConfigType.MASQUE, "masque" },
|
||||
};
|
||||
|
||||
public static readonly List<string> VmessSecurities =
|
||||
@@ -371,6 +372,7 @@ public class Global
|
||||
EConfigType.Trojan,
|
||||
EConfigType.Hysteria2,
|
||||
EConfigType.WireGuard,
|
||||
EConfigType.MASQUE,
|
||||
EConfigType.SOCKS,
|
||||
EConfigType.HTTP,
|
||||
];
|
||||
@@ -386,6 +388,7 @@ public class Global
|
||||
EConfigType.Anytls,
|
||||
EConfigType.Naive,
|
||||
EConfigType.WireGuard,
|
||||
EConfigType.MASQUE,
|
||||
EConfigType.SOCKS,
|
||||
EConfigType.HTTP,
|
||||
];
|
||||
|
||||
@@ -292,6 +292,7 @@ public static class ConfigHandler
|
||||
EConfigType.WireGuard => await AddWireguardServer(config, item),
|
||||
EConfigType.Anytls => await AddAnytlsServer(config, item),
|
||||
EConfigType.Naive => await AddNaiveServer(config, item),
|
||||
EConfigType.MASQUE => await AddMasqueServer(config, item),
|
||||
_ => -1,
|
||||
};
|
||||
return ret;
|
||||
@@ -992,6 +993,29 @@ public static class ConfigHandler
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static async Task<int> AddMasqueServer(Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.ConfigType = EConfigType.MASQUE;
|
||||
|
||||
profileItem.Address = profileItem.Address.TrimEx();
|
||||
profileItem.Username = profileItem.Username.TrimEx();
|
||||
profileItem.Password = profileItem.Password.TrimEx();
|
||||
profileItem.Fingerprint = string.Empty;
|
||||
profileItem.Alpn = string.Empty;
|
||||
profileItem.Network = string.Empty;
|
||||
profileItem.AllowInsecure = string.Empty;
|
||||
if (profileItem.StreamSecurity.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.StreamSecurity = Global.StreamSecurity;
|
||||
}
|
||||
if (profileItem.Password.IsNullOrEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
await AddServerCommon(config, profileItem, toFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort the server list by the specified column
|
||||
/// Updates the sort order in the profile extension data
|
||||
@@ -1684,6 +1708,7 @@ public static class ConfigHandler
|
||||
EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false),
|
||||
EConfigType.Anytls => await AddAnytlsServer(config, profileItem, false),
|
||||
EConfigType.Naive => await AddNaiveServer(config, profileItem, false),
|
||||
EConfigType.MASQUE => await AddMasqueServer(config, profileItem, false),
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
|
||||
@@ -128,8 +128,6 @@ public class User4Sbox
|
||||
|
||||
public class Outbound4Sbox : BaseServer4Sbox
|
||||
{
|
||||
public string? server { get; set; }
|
||||
public int? server_port { get; set; }
|
||||
public List<string>? server_ports { get; set; }
|
||||
public string? uuid { get; set; }
|
||||
public string? security { get; set; }
|
||||
@@ -171,6 +169,10 @@ public class Endpoints4Sbox : BaseServer4Sbox
|
||||
public string? udp_timeout { get; set; }
|
||||
public int? workers { get; set; }
|
||||
public List<Peer4Sbox> peers { get; set; }
|
||||
public string? username { get; set; }
|
||||
public string? password { get; set; }
|
||||
public string? path { get; set; }
|
||||
public Dictionary<string, List<string>>? headers { get; set; }
|
||||
}
|
||||
|
||||
public class Peer4Sbox
|
||||
@@ -271,10 +273,8 @@ public class Server4Sbox : BaseServer4Sbox
|
||||
public string? inet4_range { get; set; }
|
||||
public string? inet6_range { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
public string? server { get; set; }
|
||||
public new string? domain_resolver { get; set; }
|
||||
[JsonPropertyName("interface")] public string? Interface { get; set; }
|
||||
public int? server_port { get; set; }
|
||||
public string? path { get; set; }
|
||||
public Headers4Sbox? headers { get; set; }
|
||||
|
||||
@@ -359,4 +359,6 @@ public abstract class BaseServer4Sbox : DialFields4Sbox
|
||||
{
|
||||
public string type { get; set; }
|
||||
public string tag { get; set; }
|
||||
public string? server { get; set; }
|
||||
public int? server_port { get; set; }
|
||||
}
|
||||
|
||||
@@ -315,6 +315,7 @@ public class StreamSettings4Ray
|
||||
public GrpcSettings4Ray? grpcSettings { get; set; }
|
||||
|
||||
public HysteriaSettings4Ray? hysteriaSettings { get; set; }
|
||||
public MasqueSettings4Ray? masqueSettings { get; set; }
|
||||
|
||||
public object? finalmask { get; set; }
|
||||
|
||||
@@ -443,6 +444,12 @@ public class HysteriaSettings4Ray
|
||||
public string? auth { get; set; }
|
||||
}
|
||||
|
||||
public class MasqueSettings4Ray
|
||||
{
|
||||
public string? path { get; set; }
|
||||
public Dictionary<string, string>? headers { get; set; }
|
||||
}
|
||||
|
||||
public class UdpHop4Ray
|
||||
{
|
||||
public string? ports { get; set; }
|
||||
|
||||
@@ -46,6 +46,10 @@ public record ProtocolExtraItem
|
||||
public int? InsecureConcurrency { get; init; }
|
||||
public bool? NaiveQuic { get; init; }
|
||||
|
||||
// MASQUE
|
||||
public string? MasquePath { get; init; }
|
||||
public string? MasqueHeaders { get; init; }
|
||||
|
||||
// group profile
|
||||
public string? GroupType { get; init; }
|
||||
public string? ChildItems { get; init; }
|
||||
|
||||
Generated
+9
@@ -789,6 +789,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add [MASQUE] 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuAddMasqueServer {
|
||||
get {
|
||||
return ResourceManager.GetString("menuAddMasqueServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add [NaïveProxy] 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -1899,4 +1899,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||
<data name="TbSortingProcess" xml:space="preserve">
|
||||
<value>Process</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="menuAddMasqueServer" xml:space="preserve">
|
||||
<value>Add [MASQUE]</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1891,4 +1891,7 @@
|
||||
<data name="TbSortingProcess" xml:space="preserve">
|
||||
<value>进程</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="menuAddMasqueServer" xml:space="preserve">
|
||||
<value>添加 [MASQUE]</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -77,7 +77,7 @@ public partial class CoreConfigSingboxService
|
||||
}
|
||||
}
|
||||
|
||||
if (_node.ConfigType == EConfigType.WireGuard)
|
||||
if (_node.ConfigType is EConfigType.WireGuard or EConfigType.MASQUE)
|
||||
{
|
||||
var endpoint = JsonUtils.Deserialize<Endpoints4Sbox>(txtOutbound);
|
||||
FillEndpoint(endpoint);
|
||||
@@ -350,13 +350,13 @@ public partial class CoreConfigSingboxService
|
||||
{
|
||||
var protocolExtra = _node.GetProtocolExtra();
|
||||
|
||||
endpoint.address = Utils.String2List(protocolExtra.WgInterfaceAddress)?.Select(s => s.Trim()).ToList() ?? ["172.16.0.2/32"];
|
||||
endpoint.type = Global.ProtocolTypes[_node.ConfigType];
|
||||
|
||||
switch (_node.ConfigType)
|
||||
{
|
||||
case EConfigType.WireGuard:
|
||||
{
|
||||
endpoint.address = Utils.String2List(protocolExtra.WgInterfaceAddress)?.Select(s => s.Trim()).ToList() ?? ["172.16.0.2/32"];
|
||||
var peer = new Peer4Sbox
|
||||
{
|
||||
public_key = protocolExtra.WgPublicKey ?? string.Empty,
|
||||
@@ -371,6 +371,28 @@ public partial class CoreConfigSingboxService
|
||||
endpoint.peers = [peer];
|
||||
break;
|
||||
}
|
||||
case EConfigType.MASQUE:
|
||||
{
|
||||
endpoint.type = "masque-client";
|
||||
endpoint.server = _node.Address;
|
||||
endpoint.server_port = _node.Port;
|
||||
endpoint.username = _node.Username;
|
||||
endpoint.password = _node.Password;
|
||||
endpoint.path = protocolExtra?.MasquePath.NullIfEmpty();
|
||||
if (!string.IsNullOrEmpty(protocolExtra?.MasqueHeaders))
|
||||
{
|
||||
var headers = Utils.ParseHeaders(protocolExtra.MasqueHeaders)
|
||||
.GroupBy(x => x.Item1, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(
|
||||
g => g.Key,
|
||||
g => g.Select(x => x.Item2).ToList(),
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
);
|
||||
endpoint.headers = headers.Count > 0 ? headers : null;
|
||||
}
|
||||
FillOutboundTls(endpoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -402,7 +424,7 @@ public partial class CoreConfigSingboxService
|
||||
}
|
||||
}
|
||||
|
||||
private void FillOutboundTls(Outbound4Sbox outbound)
|
||||
private void FillOutboundTls(BaseServer4Sbox server)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -476,7 +498,7 @@ public partial class CoreConfigSingboxService
|
||||
{
|
||||
tls.ech = ech;
|
||||
}
|
||||
outbound.tls = tls;
|
||||
server.tls = tls;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -182,6 +182,12 @@ public partial class CoreConfigV2rayService
|
||||
outboundSettings.version = 2;
|
||||
break;
|
||||
}
|
||||
case EConfigType.MASQUE:
|
||||
{
|
||||
outboundSettings.address = _node.Address;
|
||||
outboundSettings.port = _node.Port;
|
||||
break;
|
||||
}
|
||||
case EConfigType.WireGuard:
|
||||
{
|
||||
var address = _node.Address;
|
||||
@@ -257,8 +263,13 @@ public partial class CoreConfigV2rayService
|
||||
{
|
||||
network = "hysteria";
|
||||
}
|
||||
else if (_node.ConfigType == EConfigType.MASQUE)
|
||||
{
|
||||
network = "masque";
|
||||
}
|
||||
streamSettings.network = network;
|
||||
var transport = _node.GetTransportExtra();
|
||||
var protocolExtra = _node.GetProtocolExtra();
|
||||
var host = string.Empty;
|
||||
var path = string.Empty;
|
||||
var kcpSeed = string.Empty;
|
||||
@@ -502,7 +513,6 @@ public partial class CoreConfigV2rayService
|
||||
break;
|
||||
|
||||
case "hysteria":
|
||||
var protocolExtra = _node.GetProtocolExtra();
|
||||
var ports = protocolExtra?.Ports;
|
||||
int? upMbps = protocolExtra?.UpMbps is { } su and >= 0
|
||||
? su
|
||||
@@ -574,6 +584,32 @@ public partial class CoreConfigV2rayService
|
||||
streamSettings.finalmask = hy2Finalmask;
|
||||
break;
|
||||
|
||||
case "masque":
|
||||
var headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
var authValue = $"Basic {Utils.Base64Encode($"{_node.Username}:{_node.Password}")}";
|
||||
headers.Add("Authorization", authValue);
|
||||
if (!string.IsNullOrEmpty(protocolExtra?.MasqueHeaders))
|
||||
{
|
||||
var userHeaders = Utils.ParseHeaders(protocolExtra.MasqueHeaders)
|
||||
.GroupBy(x => x.Item1, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(
|
||||
g => g.Key,
|
||||
g => string.Join(", ", g.Select(x => x.Item2)),
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
);
|
||||
if (userHeaders.TryGetValue("Authorization", out var userAuthValue))
|
||||
{
|
||||
headers["Authorization"] = userAuthValue;
|
||||
}
|
||||
headers = userHeaders;
|
||||
}
|
||||
streamSettings.masqueSettings = new()
|
||||
{
|
||||
path = protocolExtra?.MasquePath.NullIfEmpty(),
|
||||
headers = headers.Count > 0 ? headers : null,
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
// raw
|
||||
if (headerType == Global.RawHeaderHttp)
|
||||
|
||||
@@ -97,6 +97,12 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
|
||||
[Reactive]
|
||||
public partial int GeckoMaxPacketSize { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public partial string MasquePath { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public partial string MasqueHeaders { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public partial string RawHeaderType { get; set; }
|
||||
|
||||
@@ -322,6 +328,8 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
|
||||
Hy2RealmUrl = protocolExtra.Hy2RealmUrl ?? string.Empty;
|
||||
GeckoMinPacketSize = protocolExtra.GeckoMinPacketSize.ToInt();
|
||||
GeckoMaxPacketSize = protocolExtra.GeckoMaxPacketSize.ToInt();
|
||||
MasquePath = protocolExtra.MasquePath ?? string.Empty;
|
||||
MasqueHeaders = protocolExtra.MasqueHeaders ?? string.Empty;
|
||||
|
||||
RawHeaderType = transport.RawHeaderType ?? Global.None;
|
||||
Host = transport.Host ?? string.Empty;
|
||||
@@ -443,6 +451,8 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
|
||||
Hy2RealmUrl = realm?.ToUri().NullIfEmpty(),
|
||||
GeckoMinPacketSize = GeckoMinPacketSize > 0 ? GeckoMinPacketSize.ToString() : null,
|
||||
GeckoMaxPacketSize = GeckoMaxPacketSize > 0 ? GeckoMaxPacketSize.ToString() : null,
|
||||
MasquePath = MasquePath.NullIfEmpty(),
|
||||
MasqueHeaders = MasqueHeaders.NullIfEmpty(),
|
||||
});
|
||||
SelectedSource.SetTransportExtra(transport);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddWireguardServerCmd { get; }
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddAnytlsServerCmd { get; }
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddNaiveServerCmd { get; }
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddMasqueServerCmd { get; }
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddCustomServerCmd { get; }
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddCustomOutboundServerCmd { get; }
|
||||
public ReactiveCommand<RxVoid, RxVoid> AddPolicyGroupServerCmd { get; }
|
||||
@@ -140,6 +141,10 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
{
|
||||
await AddServerAsync(EConfigType.Naive);
|
||||
});
|
||||
AddMasqueServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await AddServerAsync(EConfigType.MASQUE);
|
||||
});
|
||||
AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await AddServerAsync(EConfigType.Custom);
|
||||
|
||||
@@ -113,6 +113,7 @@ public partial class OptionSettingViewModel : MyReactiveObject, ICloseable
|
||||
[Reactive] public partial string CoreType6 { get; set; }
|
||||
[Reactive] public partial string CoreType7 { get; set; }
|
||||
[Reactive] public partial string CoreType9 { get; set; }
|
||||
[Reactive] public partial string CoreType14 { get; set; }
|
||||
|
||||
#endregion CoreType
|
||||
|
||||
@@ -283,6 +284,10 @@ public partial class OptionSettingViewModel : MyReactiveObject, ICloseable
|
||||
case 9:
|
||||
CoreType9 = type;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
CoreType14 = type;
|
||||
break;
|
||||
}
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
@@ -451,6 +456,10 @@ public partial class OptionSettingViewModel : MyReactiveObject, ICloseable
|
||||
type = CoreType9;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
type = CoreType14;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -783,6 +783,70 @@
|
||||
HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
|
||||
|
||||
<Grid
|
||||
x:Name="gridMasque"
|
||||
Grid.Row="2"
|
||||
ColumnDefinitions="300,Auto"
|
||||
IsVisible="False"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbUsername}" />
|
||||
<TextBox
|
||||
x:Name="txtId14"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbId3}" />
|
||||
<TextBox
|
||||
x:Name="txtSecurity14"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbPath}" />
|
||||
<TextBox
|
||||
x:Name="txtPath14"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbHttpOutboundHeaders}" />
|
||||
<TextBox
|
||||
x:Name="txtHttpHeaders14"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
AcceptsReturn="True"
|
||||
Classes="TextArea"
|
||||
PlaceholderText="Header: Value"
|
||||
TextWrapping="NoWrap" />
|
||||
</Grid>
|
||||
|
||||
<Separator
|
||||
x:Name="sepa2"
|
||||
Grid.Row="3"
|
||||
|
||||
@@ -141,6 +141,14 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
this.Bind(ViewModel, vm => vm.InsecureConcurrency, v => v.txtInsecureConcurrency12.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.Uot, v => v.togUotEnabled12.IsChecked).DisposeWith(currentTypeDisposables);
|
||||
break;
|
||||
|
||||
case EConfigType.MASQUE:
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId14.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity14.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.MasquePath, v => v.txtPath14.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.MasqueHeaders, v => v.txtHttpHeaders14.Text).DisposeWith(currentTypeDisposables);
|
||||
break;
|
||||
|
||||
}
|
||||
})
|
||||
.DisposeWith(disposables);
|
||||
@@ -284,6 +292,14 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
|
||||
cmbCongestionControl12.ItemsSource = Global.NaiveCongestionControls;
|
||||
break;
|
||||
|
||||
case EConfigType.MASQUE:
|
||||
gridMasque.IsVisible = true;
|
||||
sepa2.IsVisible = false;
|
||||
gridTransport.IsVisible = false;
|
||||
cmbFingerprint.IsEnabled = false;
|
||||
cmbAlpn.IsEnabled = false;
|
||||
break;
|
||||
}
|
||||
cmbStreamSecurity.ItemsSource = lstStreamSecurity;
|
||||
cmbStreamSecurity.SelectedItem = profileItem.StreamSecurity;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<MenuItem x:Name="menuAddTrojanServer" Header="{x:Static resx:ResUI.menuAddTrojanServer}" />
|
||||
<MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" />
|
||||
<MenuItem x:Name="menuAddWireguardServer" Header="{x:Static resx:ResUI.menuAddWireguardServer}" />
|
||||
<MenuItem x:Name="menuAddMasqueServer" Header="{x:Static resx:ResUI.menuAddMasqueServer}" />
|
||||
<MenuItem x:Name="menuAddSocksServer" Header="{x:Static resx:ResUI.menuAddSocksServer}" />
|
||||
<MenuItem x:Name="menuAddHttpServer" Header="{x:Static resx:ResUI.menuAddHttpServer}" />
|
||||
<Separator />
|
||||
|
||||
@@ -46,6 +46,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddNaiveServerCmd, v => v.menuAddNaiveServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddMasqueServerCmd, v => v.menuAddMasqueServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomOutboundServerCmd, v => v.menuAddCustomOutboundServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddPolicyGroupServerCmd, v => v.menuAddPolicyGroupServer).DisposeWith(disposables);
|
||||
|
||||
@@ -1192,7 +1192,7 @@
|
||||
<Grid
|
||||
Margin="{StaticResource Margin4}"
|
||||
ColumnDefinitions="Auto,Auto"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
@@ -1296,6 +1296,19 @@
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="9"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="MASQUE" />
|
||||
<ComboBox
|
||||
x:Name="cmbCoreType14"
|
||||
Grid.Row="9"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
@@ -46,6 +46,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||
cmbCoreType6.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType7.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType9.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType14.ItemsSource = Global.CoreTypes;
|
||||
|
||||
cmbMixedConcurrencyCount.ItemsSource = Enumerable.Range(Global.SpeedTestConcurrencyCountMin, 20).ToList();
|
||||
cmbSpeedTestTimeout.ItemsSource = Enumerable.Range(2, 5).Select(i => i * 5).ToList();
|
||||
@@ -145,6 +146,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||
this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType7, v => v.cmbCoreType7.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType9, v => v.cmbCoreType9.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType14, v => v.cmbCoreType14.SelectedValue).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
@@ -1000,6 +1000,89 @@
|
||||
HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
x:Name="gridMasque"
|
||||
Grid.Row="2"
|
||||
Visibility="Collapsed">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="300" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbUsername}" />
|
||||
<TextBox
|
||||
x:Name="txtId14"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbId3}" />
|
||||
<TextBox
|
||||
x:Name="txtSecurity14"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbPath}" />
|
||||
<TextBox
|
||||
x:Name="txtPath14"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbHttpOutboundHeaders}" />
|
||||
<TextBox
|
||||
x:Name="txtHeaders14"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
materialDesign:HintAssist.Hint="Header: Value"
|
||||
AcceptsReturn="True"
|
||||
MaxLines="12"
|
||||
MinLines="3"
|
||||
Style="{StaticResource MyOutlinedTextBox}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
|
||||
<Separator
|
||||
x:Name="sepa2"
|
||||
Grid.Row="3"
|
||||
|
||||
@@ -139,6 +139,13 @@ public partial class AddServerWindow
|
||||
this.Bind(ViewModel, vm => vm.InsecureConcurrency, v => v.txtInsecureConcurrency12.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.Uot, v => v.togUotEnabled12.IsChecked).DisposeWith(currentTypeDisposables);
|
||||
break;
|
||||
|
||||
case EConfigType.MASQUE:
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId14.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity14.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.MasquePath, v => v.txtPath14.Text).DisposeWith(currentTypeDisposables);
|
||||
this.Bind(ViewModel, vm => vm.MasqueHeaders, v => v.txtHeaders14.Text).DisposeWith(currentTypeDisposables);
|
||||
break;
|
||||
}
|
||||
})
|
||||
.DisposeWith(disposables);
|
||||
@@ -284,6 +291,14 @@ public partial class AddServerWindow
|
||||
|
||||
cmbCongestionControl12.ItemsSource = Global.NaiveCongestionControls;
|
||||
break;
|
||||
|
||||
case EConfigType.MASQUE:
|
||||
gridMasque.Visibility = Visibility.Visible;
|
||||
sepa2.Visibility = Visibility.Collapsed;
|
||||
gridTransport.Visibility = Visibility.Collapsed;
|
||||
cmbFingerprint.IsEnabled = false;
|
||||
cmbAlpn.IsEnabled = false;
|
||||
break;
|
||||
}
|
||||
cmbStreamSecurity.ItemsSource = lstStreamSecurity;
|
||||
cmbStreamSecurity.SelectedItem = profileItem.StreamSecurity;
|
||||
|
||||
@@ -112,6 +112,10 @@
|
||||
x:Name="menuAddWireguardServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAddWireguardServer}" />
|
||||
<MenuItem
|
||||
x:Name="menuAddMasqueServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAddMasqueServer}" />
|
||||
<MenuItem
|
||||
x:Name="menuAddSocksServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
|
||||
@@ -46,6 +46,7 @@ public partial class MainWindow
|
||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddNaiveServerCmd, v => v.menuAddNaiveServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddMasqueServerCmd, v => v.menuAddMasqueServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomOutboundServerCmd, v => v.menuAddCustomOutboundServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddPolicyGroupServerCmd, v => v.menuAddPolicyGroupServer).DisposeWith(disposables);
|
||||
|
||||
@@ -1473,6 +1473,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -1597,6 +1598,21 @@
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="9"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="MASQUE" />
|
||||
<ComboBox
|
||||
x:Name="cmbCoreType14"
|
||||
Grid.Row="9"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
@@ -42,6 +42,7 @@ public partial class OptionSettingWindow
|
||||
cmbCoreType6.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType7.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType9.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType14.ItemsSource = Global.CoreTypes;
|
||||
|
||||
cmbMixedConcurrencyCount.ItemsSource = Enumerable.Range(Global.SpeedTestConcurrencyCountMin, 20).ToList();
|
||||
cmbSpeedTestTimeout.ItemsSource = Enumerable.Range(2, 5).Select(i => i * 5).ToList();
|
||||
@@ -141,6 +142,7 @@ public partial class OptionSettingWindow
|
||||
this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType7, v => v.cmbCoreType7.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType9, v => v.cmbCoreType9.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType14, v => v.cmbCoreType14.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user