RFC5780ViewModel.cs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using Dns.Net.Abstractions;
  2. using JetBrains.Annotations;
  3. using Microsoft;
  4. using NatTypeTester.Models;
  5. using ReactiveUI;
  6. using STUN;
  7. using STUN.Client;
  8. using STUN.Proxy;
  9. using STUN.StunResult;
  10. using System;
  11. using System.Net;
  12. using System.Reactive;
  13. using System.Reactive.Linq;
  14. using System.Threading;
  15. using System.Threading.Tasks;
  16. namespace NatTypeTester.ViewModels
  17. {
  18. [UsedImplicitly]
  19. public class RFC5780ViewModel : ViewModelBase, IRoutableViewModel
  20. {
  21. public string UrlPathSegment => @"RFC5780";
  22. public IScreen HostScreen => LazyServiceProvider.LazyGetRequiredService<IScreen>();
  23. private Config Config => LazyServiceProvider.LazyGetRequiredService<Config>();
  24. private IDnsClient DnsClient => LazyServiceProvider.LazyGetRequiredService<IDnsClient>();
  25. public StunResult5389 Result5389 { get; set; }
  26. public ReactiveCommand<Unit, Unit> DiscoveryNatType { get; }
  27. public RFC5780ViewModel()
  28. {
  29. Result5389 = new StunResult5389 { LocalEndPoint = new IPEndPoint(IPAddress.Any, 0) };
  30. DiscoveryNatType = ReactiveCommand.CreateFromTask(DiscoveryNatTypeImpl);
  31. }
  32. private async Task DiscoveryNatTypeImpl(CancellationToken token)
  33. {
  34. Verify.Operation(StunServer.TryParse(Config.StunServer, out var server), @"Wrong STUN Server!");
  35. using var proxy = ProxyFactory.CreateProxy(
  36. Config.ProxyType,
  37. Result5389.LocalEndPoint,
  38. IPEndPoint.Parse(Config.ProxyServer),
  39. Config.ProxyUser, Config.ProxyPassword
  40. );
  41. var ip = await DnsClient.QueryAsync(server.Hostname, token);
  42. using var client = new StunClient5389UDP(ip, server.Port, Result5389.LocalEndPoint, proxy);
  43. Result5389 = client.Status;
  44. using (Observable.Interval(TimeSpan.FromSeconds(0.1))
  45. .ObserveOn(RxApp.MainThreadScheduler)
  46. .Subscribe(_ => this.RaisePropertyChanged(nameof(Result5389))))
  47. {
  48. await client.QueryAsync();
  49. }
  50. var cache = new StunResult5389();
  51. cache.Clone(client.Status);
  52. cache.LocalEndPoint = client.LocalEndPoint;
  53. Result5389 = cache;
  54. this.RaisePropertyChanged(nameof(Result5389));
  55. }
  56. }
  57. }