2
0

PayloadData.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. namespace SocketHttpListener
  6. {
  7. internal class PayloadData : IEnumerable<byte>
  8. {
  9. #region Private Fields
  10. private byte[] _applicationData;
  11. private byte[] _extensionData;
  12. private bool _masked;
  13. #endregion
  14. #region Public Const Fields
  15. public const ulong MaxLength = long.MaxValue;
  16. #endregion
  17. #region Public Constructors
  18. public PayloadData()
  19. : this(new byte[0], new byte[0], false)
  20. {
  21. }
  22. public PayloadData(byte[] applicationData)
  23. : this(new byte[0], applicationData, false)
  24. {
  25. }
  26. public PayloadData(string applicationData)
  27. : this(new byte[0], Encoding.UTF8.GetBytes(applicationData), false)
  28. {
  29. }
  30. public PayloadData(byte[] applicationData, bool masked)
  31. : this(new byte[0], applicationData, masked)
  32. {
  33. }
  34. public PayloadData(byte[] extensionData, byte[] applicationData, bool masked)
  35. {
  36. _extensionData = extensionData;
  37. _applicationData = applicationData;
  38. _masked = masked;
  39. }
  40. #endregion
  41. #region Internal Properties
  42. internal bool ContainsReservedCloseStatusCode =>
  43. _applicationData.Length > 1 &&
  44. _applicationData.SubArray(0, 2).ToUInt16(ByteOrder.Big).IsReserved();
  45. #endregion
  46. #region Public Properties
  47. public byte[] ApplicationData => _applicationData;
  48. public byte[] ExtensionData => _extensionData;
  49. public bool IsMasked => _masked;
  50. public ulong Length => (ulong)(_extensionData.Length + _applicationData.Length);
  51. #endregion
  52. #region Private Methods
  53. private static void mask(byte[] src, byte[] key)
  54. {
  55. for (long i = 0; i < src.Length; i++)
  56. src[i] = (byte)(src[i] ^ key[i % 4]);
  57. }
  58. #endregion
  59. #region Public Methods
  60. public IEnumerator<byte> GetEnumerator()
  61. {
  62. foreach (byte b in _extensionData)
  63. yield return b;
  64. foreach (byte b in _applicationData)
  65. yield return b;
  66. }
  67. public void Mask(byte[] maskingKey)
  68. {
  69. if (_extensionData.Length > 0)
  70. mask(_extensionData, maskingKey);
  71. if (_applicationData.Length > 0)
  72. mask(_applicationData, maskingKey);
  73. _masked = !_masked;
  74. }
  75. public byte[] ToByteArray()
  76. {
  77. return _extensionData.Length > 0
  78. ? new List<byte>(this).ToArray()
  79. : _applicationData;
  80. }
  81. public override string ToString()
  82. {
  83. return BitConverter.ToString(ToByteArray());
  84. }
  85. #endregion
  86. #region Explicitly Implemented Interface Members
  87. IEnumerator IEnumerable.GetEnumerator()
  88. {
  89. return GetEnumerator();
  90. }
  91. #endregion
  92. }
  93. }