PayloadData.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. {
  44. get
  45. {
  46. return _applicationData.Length > 1 &&
  47. _applicationData.SubArray(0, 2).ToUInt16(ByteOrder.Big).IsReserved();
  48. }
  49. }
  50. #endregion
  51. #region Public Properties
  52. public byte[] ApplicationData
  53. {
  54. get
  55. {
  56. return _applicationData;
  57. }
  58. }
  59. public byte[] ExtensionData
  60. {
  61. get
  62. {
  63. return _extensionData;
  64. }
  65. }
  66. public bool IsMasked
  67. {
  68. get
  69. {
  70. return _masked;
  71. }
  72. }
  73. public ulong Length
  74. {
  75. get
  76. {
  77. return (ulong)(_extensionData.Length + _applicationData.Length);
  78. }
  79. }
  80. #endregion
  81. #region Private Methods
  82. private static void mask(byte[] src, byte[] key)
  83. {
  84. for (long i = 0; i < src.Length; i++)
  85. src[i] = (byte)(src[i] ^ key[i % 4]);
  86. }
  87. #endregion
  88. #region Public Methods
  89. public IEnumerator<byte> GetEnumerator()
  90. {
  91. foreach (byte b in _extensionData)
  92. yield return b;
  93. foreach (byte b in _applicationData)
  94. yield return b;
  95. }
  96. public void Mask(byte[] maskingKey)
  97. {
  98. if (_extensionData.Length > 0)
  99. mask(_extensionData, maskingKey);
  100. if (_applicationData.Length > 0)
  101. mask(_applicationData, maskingKey);
  102. _masked = !_masked;
  103. }
  104. public byte[] ToByteArray()
  105. {
  106. return _extensionData.Length > 0
  107. ? new List<byte>(this).ToArray()
  108. : _applicationData;
  109. }
  110. public override string ToString()
  111. {
  112. return BitConverter.ToString(ToByteArray());
  113. }
  114. #endregion
  115. #region Explicitly Implemented Interface Members
  116. IEnumerator IEnumerable.GetEnumerator()
  117. {
  118. return GetEnumerator();
  119. }
  120. #endregion
  121. }
  122. }