AddressStunAttributeValue.cs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using Microsoft;
  2. using STUN.Enums;
  3. using System.Buffers.Binary;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. namespace STUN.Messages.StunAttributeValues;
  7. /// <summary>
  8. /// https://tools.ietf.org/html/rfc5389#section-15.1
  9. /// </summary>
  10. public abstract class AddressStunAttributeValue : IStunAttributeValue
  11. {
  12. public IpFamily Family { get; set; }
  13. public ushort Port { get; set; }
  14. public IPAddress? Address { get; set; }
  15. public virtual int WriteTo(Span<byte> buffer)
  16. {
  17. Verify.Operation(Address is not null, @"You should set Address info!");
  18. Requires.Range(buffer.Length >= 4 + 4, nameof(buffer));
  19. buffer[0] = 0;
  20. buffer[1] = (byte)Family;
  21. BinaryPrimitives.WriteUInt16BigEndian(buffer[2..], Port);
  22. Requires.Range(Address.TryWriteBytes(buffer[4..], out var bytesWritten), nameof(buffer));
  23. return 4 + bytesWritten;
  24. }
  25. public virtual bool TryParse(ReadOnlySpan<byte> buffer)
  26. {
  27. var length = 4;
  28. if (buffer.Length < length)
  29. {
  30. return false;
  31. }
  32. Family = (IpFamily)buffer[1];
  33. switch (Family)
  34. {
  35. case IpFamily.IPv4:
  36. length += 4;
  37. break;
  38. case IpFamily.IPv6:
  39. length += 16;
  40. break;
  41. default:
  42. return false;
  43. }
  44. if (buffer.Length != length)
  45. {
  46. return false;
  47. }
  48. Port = BinaryPrimitives.ReadUInt16BigEndian(buffer[2..]);
  49. Address = new IPAddress(buffer[4..]);
  50. return true;
  51. }
  52. public override string? ToString()
  53. {
  54. return Address?.AddressFamily switch
  55. {
  56. AddressFamily.InterNetwork => $@"{Address}:{Port}",
  57. AddressFamily.InterNetworkV6 => $@"[{Address}]:{Port}",
  58. _ => base.ToString()
  59. };
  60. }
  61. }