diff --git a/NatTypeTester.ViewModels/NatTypeTesterViewModelModule.cs b/NatTypeTester.ViewModels/NatTypeTesterViewModelModule.cs index 3c89b1ff1..341d241c6 100644 --- a/NatTypeTester.ViewModels/NatTypeTesterViewModelModule.cs +++ b/NatTypeTester.ViewModels/NatTypeTesterViewModelModule.cs @@ -12,5 +12,7 @@ public class NatTypeTesterViewModelModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.TryAddTransient(); + context.Services.TryAddTransient(); + context.Services.TryAddTransient(); } } diff --git a/NatTypeTester.ViewModels/RFC3489ViewModel.cs b/NatTypeTester.ViewModels/RFC3489ViewModel.cs index 69adddcf9..af1dd612a 100644 --- a/NatTypeTester.ViewModels/RFC3489ViewModel.cs +++ b/NatTypeTester.ViewModels/RFC3489ViewModel.cs @@ -1,4 +1,5 @@ using Dns.Net.Abstractions; +using Dns.Net.Clients; using JetBrains.Annotations; using Microsoft; using NatTypeTester.Models; @@ -24,19 +25,16 @@ public class RFC3489ViewModel : ViewModelBase, IRoutableViewModel private Config Config => LazyServiceProvider.LazyGetRequiredService(); private IDnsClient DnsClient => LazyServiceProvider.LazyGetRequiredService(); + private IDnsClient AAAADnsClient => LazyServiceProvider.LazyGetRequiredService(); + private IDnsClient ADnsClient => LazyServiceProvider.LazyGetRequiredService(); public ClassicStunResult Result3489 { get; set; } public ReactiveCommand TestClassicNatType { get; } - private static readonly IPEndPoint DefaultLocalEndpoint = new(IPAddress.Any, 0); - public RFC3489ViewModel() { - Result3489 = new ClassicStunResult - { - LocalEndPoint = DefaultLocalEndpoint - }; + Result3489 = new ClassicStunResult(); TestClassicNatType = ReactiveCommand.CreateFromTask(TestClassicNatTypeAsync); } @@ -60,22 +58,37 @@ private async Task TestClassicNatTypeAsync(CancellationToken token) } }; - Result3489.LocalEndPoint ??= DefaultLocalEndpoint; + IPAddress? serverIp; + if (Result3489.LocalEndPoint is null) + { + serverIp = await DnsClient.QueryAsync(server.Hostname, token); + Result3489.LocalEndPoint = serverIp.AddressFamily is AddressFamily.InterNetworkV6 ? new IPEndPoint(IPAddress.IPv6Any, IPEndPoint.MinPort) : new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); + } + else + { + if (Result3489.LocalEndPoint.AddressFamily is AddressFamily.InterNetworkV6) + { + serverIp = await AAAADnsClient.QueryAsync(server.Hostname, token); + } + else + { + serverIp = await ADnsClient.QueryAsync(server.Hostname, token); + } + } + using IUdpProxy proxy = ProxyFactory.CreateProxy(Config.ProxyType, Result3489.LocalEndPoint, socks5Option); - IPAddress ip = await DnsClient.QueryAsync(server.Hostname, token); - using StunClient3489 client = new(new IPEndPoint(ip, server.Port), Result3489.LocalEndPoint, proxy); + using StunClient3489 client = new(new IPEndPoint(serverIp, server.Port), Result3489.LocalEndPoint, proxy); Result3489 = client.State; using (Observable.Interval(TimeSpan.FromSeconds(0.1)) - .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(_ => this.RaisePropertyChanged(nameof(Result3489)))) + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(_ => this.RaisePropertyChanged(nameof(Result3489)))) { await client.ConnectProxyAsync(token); try { await client.QueryAsync(token); - Result3489.LocalEndPoint = new IPEndPoint(client.LocalEndPoint.AddressFamily is AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, client.LocalEndPoint.Port); } finally { diff --git a/NatTypeTester.ViewModels/RFC5780ViewModel.cs b/NatTypeTester.ViewModels/RFC5780ViewModel.cs index 44aa2342b..284cc70ae 100644 --- a/NatTypeTester.ViewModels/RFC5780ViewModel.cs +++ b/NatTypeTester.ViewModels/RFC5780ViewModel.cs @@ -1,4 +1,5 @@ using Dns.Net.Abstractions; +using Dns.Net.Clients; using JetBrains.Annotations; using Microsoft; using NatTypeTester.Models; @@ -24,13 +25,13 @@ public class RFC5780ViewModel : ViewModelBase, IRoutableViewModel private Config Config => LazyServiceProvider.LazyGetRequiredService(); private IDnsClient DnsClient => LazyServiceProvider.LazyGetRequiredService(); + private IDnsClient AAAADnsClient => LazyServiceProvider.LazyGetRequiredService(); + private IDnsClient ADnsClient => LazyServiceProvider.LazyGetRequiredService(); public StunResult5389 Result5389 { get; set; } public ReactiveCommand DiscoveryNatType { get; } - private static readonly IPEndPoint DefaultLocalEndpoint = new(IPAddress.Any, 0); - public RFC5780ViewModel() { Result5389 = new StunResult5389(); @@ -57,11 +58,27 @@ private async Task DiscoveryNatTypeAsync(CancellationToken token) } }; - Result5389.LocalEndPoint ??= DefaultLocalEndpoint; + IPAddress? serverIp; + if (Result5389.LocalEndPoint is null) + { + serverIp = await DnsClient.QueryAsync(server.Hostname, token); + Result5389.LocalEndPoint = serverIp.AddressFamily is AddressFamily.InterNetworkV6 ? new IPEndPoint(IPAddress.IPv6Any, IPEndPoint.MinPort) : new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); + } + else + { + if (Result5389.LocalEndPoint.AddressFamily is AddressFamily.InterNetworkV6) + { + serverIp = await AAAADnsClient.QueryAsync(server.Hostname, token); + } + else + { + serverIp = await ADnsClient.QueryAsync(server.Hostname, token); + } + } + using IUdpProxy proxy = ProxyFactory.CreateProxy(Config.ProxyType, Result5389.LocalEndPoint, socks5Option); - IPAddress ip = await DnsClient.QueryAsync(server.Hostname, token); - using StunClient5389UDP client = new(new IPEndPoint(ip, server.Port), Result5389.LocalEndPoint, proxy); + using StunClient5389UDP client = new(new IPEndPoint(serverIp, server.Port), Result5389.LocalEndPoint, proxy); Result5389 = client.State; using (Observable.Interval(TimeSpan.FromSeconds(0.1)) @@ -72,7 +89,6 @@ private async Task DiscoveryNatTypeAsync(CancellationToken token) try { await client.QueryAsync(token); - Result5389.LocalEndPoint = new IPEndPoint(client.LocalEndPoint.AddressFamily is AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, client.LocalEndPoint.Port); } finally { diff --git a/NatTypeTester.ViewModels/ValueConverters/StringToIPEndpointTypeConverter.cs b/NatTypeTester.ViewModels/ValueConverters/StringToIPEndpointTypeConverter.cs index ce3afe780..9960e3f8f 100644 --- a/NatTypeTester.ViewModels/ValueConverters/StringToIPEndpointTypeConverter.cs +++ b/NatTypeTester.ViewModels/ValueConverters/StringToIPEndpointTypeConverter.cs @@ -44,7 +44,7 @@ public bool TryConvert(object? from, Type toType, object? conversionHint, out ob } else { - result = @"AUTO"; + result = string.Empty; } return true; diff --git a/NatTypeTester/MainWindow.xaml b/NatTypeTester/MainWindow.xaml index ec7a92a36..acd60e314 100644 --- a/NatTypeTester/MainWindow.xaml +++ b/NatTypeTester/MainWindow.xaml @@ -1,32 +1,32 @@ + xmlns:ui="http://schemas.modernwpf.com/2019" + Title="NatTypeTester" + WindowStartupLocation="CenterScreen" + Height="480" Width="500" + MinHeight="480" MinWidth="500" + ui:WindowHelper.UseModernWindowStyle="True"> - - - - - - - - - + + + + + + + + + - + diff --git a/NatTypeTester/NatTypeTester.csproj b/NatTypeTester/NatTypeTester.csproj index 850faa323..73624e1cb 100644 --- a/NatTypeTester/NatTypeTester.csproj +++ b/NatTypeTester/NatTypeTester.csproj @@ -1,4 +1,4 @@ - + @@ -10,6 +10,10 @@ icon.ico + + + + @@ -23,4 +27,12 @@ + + + True + Designer + MSBuild:Compile + + + diff --git a/NatTypeTester/Properties/DesignTimeResources.xaml b/NatTypeTester/Properties/DesignTimeResources.xaml new file mode 100644 index 000000000..846a8230c --- /dev/null +++ b/NatTypeTester/Properties/DesignTimeResources.xaml @@ -0,0 +1,7 @@ + + + + + diff --git a/NatTypeTester/Views/RFC3489View.xaml b/NatTypeTester/Views/RFC3489View.xaml index 0a56a8fb3..c2cb4ed1f 100644 --- a/NatTypeTester/Views/RFC3489View.xaml +++ b/NatTypeTester/Views/RFC3489View.xaml @@ -22,10 +22,14 @@ Margin="10,5" IsReadOnly="True" VerticalContentAlignment="Center" VerticalAlignment="Center" ui:ControlHelper.Header="NAT type" /> - + + 0.0.0.0:0 + [::]:0 + vm.Result3489.NatType, v => v.NatTypeTextBox.Text).DisposeWith(d); - this.Bind(ViewModel, vm => vm.Result3489.LocalEndPoint, v => v.LocalEndTextBox.Text).DisposeWith(d); + this.Bind(ViewModel, vm => vm.Result3489.LocalEndPoint, v => v.LocalEndComboBox.Text).DisposeWith(d); + + LocalEndComboBox.Events().LostKeyboardFocus.Subscribe(_ => LocalEndComboBox.Text = ViewModel.Result3489.LocalEndPoint?.ToString() ?? string.Empty).DisposeWith(d); this.OneWayBind(ViewModel, vm => vm.Result3489.PublicEndPoint, v => v.PublicEndTextBox.Text).DisposeWith(d); diff --git a/NatTypeTester/Views/RFC5780View.xaml b/NatTypeTester/Views/RFC5780View.xaml index 81b958de2..46b534a9c 100644 --- a/NatTypeTester/Views/RFC5780View.xaml +++ b/NatTypeTester/Views/RFC5780View.xaml @@ -34,11 +34,14 @@ Margin="10,5" IsReadOnly="True" VerticalContentAlignment="Center" VerticalAlignment="Center" ui:ControlHelper.Header="Filtering behavior" /> - + + 0.0.0.0:0 + [::]:0 + vm.Result5389.FilteringBehavior, v => v.FilteringBehaviorTextBox.Text).DisposeWith(d); - this.Bind(ViewModel, vm => vm.Result5389.LocalEndPoint, v => v.LocalAddressTextBox.Text).DisposeWith(d); + this.Bind(ViewModel, vm => vm.Result5389.LocalEndPoint, v => v.LocalAddressComboBox.Text).DisposeWith(d); + + LocalAddressComboBox.Events().LostKeyboardFocus.Subscribe(_ => LocalAddressComboBox.Text = ViewModel.Result5389.LocalEndPoint?.ToString() ?? string.Empty).DisposeWith(d); this.OneWayBind(ViewModel, vm => vm.Result5389.PublicEndPoint, v => v.MappingAddressTextBox.Text).DisposeWith(d);