AddressStunAttributeValue.cs 1.6 KB

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