StunClient5389UDP.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using STUN.Enums;
  2. using STUN.Interfaces;
  3. using STUN.Message;
  4. using STUN.StunResult;
  5. using STUN.Utils;
  6. using System;
  7. using System.Diagnostics;
  8. using System.Linq;
  9. using System.Net;
  10. using System.Threading.Tasks;
  11. namespace STUN.Client
  12. {
  13. public class StunClient5389UDP : StunClient3489
  14. {
  15. public StunClient5389UDP(string server, ushort port = 3478, IPEndPoint local = null, IDnsQuery dnsQuery = null)
  16. : base(server, port, local, dnsQuery)
  17. {
  18. Timeout = TimeSpan.FromSeconds(3);
  19. }
  20. public override IStunResult Query()
  21. {
  22. throw new NotImplementedException();
  23. }
  24. public override async Task<IStunResult> QueryAsync()
  25. {
  26. return await BindingTestAsync();
  27. }
  28. public async Task<StunResult5389> BindingTestAsync()
  29. {
  30. BindingTestResult res;
  31. var test = new StunMessage5389 { StunMessageType = StunMessageType.BindingRequest };
  32. var (response1, _, local1) = await TestAsync(test, RemoteEndPoint, RemoteEndPoint);
  33. var mappedAddress1 = AttributeExtensions.GetXorMappedAddressAttribute(response1);
  34. if (response1 == null)
  35. {
  36. res = BindingTestResult.Fail;
  37. }
  38. else if (mappedAddress1 == null)
  39. {
  40. res = BindingTestResult.UnsupportedServer;
  41. }
  42. else
  43. {
  44. res = BindingTestResult.Success;
  45. }
  46. return new StunResult5389
  47. {
  48. BindingTestResult = res,
  49. LocalEndPoint = local1 == null ? null : new IPEndPoint(local1, LocalEndPoint.Port),
  50. PublicEndPoint = mappedAddress1
  51. };
  52. }
  53. private async Task<(StunMessage5389, IPEndPoint, IPAddress)> TestAsync(StunMessage5389 sendMessage, IPEndPoint remote, IPEndPoint receive)
  54. {
  55. try
  56. {
  57. var b1 = sendMessage.Bytes.ToArray();
  58. //var t = DateTime.Now;
  59. // Simple retransmissions
  60. //https://tools.ietf.org/html/rfc5389#section-7.2.1
  61. //while (t + TimeSpan.FromSeconds(6) > DateTime.Now)
  62. {
  63. try
  64. {
  65. var (receive1, ipe, local) = await UdpClient.UdpReceiveAsync(b1, remote, receive);
  66. var message = new StunMessage5389();
  67. if (message.TryParse(receive1) &&
  68. message.ClassicTransactionId.IsEqual(sendMessage.ClassicTransactionId))
  69. {
  70. return (message, ipe, local);
  71. }
  72. }
  73. catch (Exception ex)
  74. {
  75. Debug.WriteLine(ex);
  76. }
  77. }
  78. }
  79. catch (Exception ex)
  80. {
  81. Debug.WriteLine(ex);
  82. }
  83. return (null, null, null);
  84. }
  85. }
  86. }