PayloadData.cs 2.9 KB

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