HostnameEndpoint.cs 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. using System.Diagnostics.CodeAnalysis;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. namespace STUN;
  5. public class HostnameEndpoint
  6. {
  7. public string Hostname { get; }
  8. public ushort Port { get; }
  9. private HostnameEndpoint(string host, ushort port)
  10. {
  11. Hostname = host;
  12. Port = port;
  13. }
  14. public static bool TryParse(string s, [NotNullWhen(true)] out HostnameEndpoint? result, ushort defaultPort = 0)
  15. {
  16. result = null;
  17. if (string.IsNullOrEmpty(s))
  18. {
  19. return false;
  20. }
  21. int hostLength = s.Length;
  22. int pos = s.LastIndexOf(':');
  23. if (pos > 0)
  24. {
  25. if (s[pos - 1] is ']')
  26. {
  27. hostLength = pos;
  28. }
  29. else if (s.AsSpan(0, pos).LastIndexOf(':') is -1)
  30. {
  31. hostLength = pos;
  32. }
  33. }
  34. string host = s[..hostLength];
  35. UriHostNameType type = Uri.CheckHostName(host);
  36. switch (type)
  37. {
  38. case UriHostNameType.Dns:
  39. case UriHostNameType.IPv4:
  40. case UriHostNameType.IPv6:
  41. {
  42. break;
  43. }
  44. default:
  45. {
  46. return false;
  47. }
  48. }
  49. if (hostLength == s.Length || ushort.TryParse(s.AsSpan(hostLength + 1), out defaultPort))
  50. {
  51. result = new HostnameEndpoint(host, defaultPort);
  52. return true;
  53. }
  54. return false;
  55. }
  56. public override string ToString()
  57. {
  58. if (IPAddress.TryParse(Hostname, out IPAddress? ip) && ip.AddressFamily is AddressFamily.InterNetworkV6)
  59. {
  60. return $@"[{ip}]:{Port}";
  61. }
  62. return $@"{Hostname}:{Port}";
  63. }
  64. }