PayloadData.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #region License
  2. /*
  3. * PayloadData.cs
  4. *
  5. * The MIT License
  6. *
  7. * Copyright (c) 2012-2022 sta.blockhead
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #endregion
  28. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. namespace WebSocketSharp
  32. {
  33. internal class PayloadData : IEnumerable<byte>
  34. {
  35. #region Private Fields
  36. private byte[] _data;
  37. private long _extDataLength;
  38. private long _length;
  39. #endregion
  40. #region Public Fields
  41. /// <summary>
  42. /// Represents the empty payload data.
  43. /// </summary>
  44. public static readonly PayloadData Empty;
  45. /// <summary>
  46. /// Represents the allowable max length of payload data.
  47. /// </summary>
  48. /// <remarks>
  49. /// <para>
  50. /// A <see cref="WebSocketException"/> is thrown when the length of
  51. /// incoming payload data is greater than the value of this field.
  52. /// </para>
  53. /// <para>
  54. /// If you would like to change the value of this field, it must be
  55. /// a number between <see cref="WebSocket.FragmentLength"/> and
  56. /// <see cref="Int64.MaxValue"/> inclusive.
  57. /// </para>
  58. /// </remarks>
  59. public static readonly ulong MaxLength;
  60. #endregion
  61. #region Static Constructor
  62. static PayloadData ()
  63. {
  64. Empty = new PayloadData (WebSocket.EmptyBytes, 0);
  65. MaxLength = Int64.MaxValue;
  66. }
  67. #endregion
  68. #region Internal Constructors
  69. internal PayloadData (byte[] data)
  70. : this (data, data.LongLength)
  71. {
  72. }
  73. internal PayloadData (byte[] data, long length)
  74. {
  75. _data = data;
  76. _length = length;
  77. }
  78. internal PayloadData (ushort code, string reason)
  79. {
  80. _data = code.Append (reason);
  81. _length = _data.LongLength;
  82. }
  83. #endregion
  84. #region Internal Properties
  85. internal ushort Code {
  86. get {
  87. return _length >= 2
  88. ? _data.SubArray (0, 2).ToUInt16 (ByteOrder.Big)
  89. : (ushort) 1005;
  90. }
  91. }
  92. internal long ExtensionDataLength {
  93. get {
  94. return _extDataLength;
  95. }
  96. set {
  97. _extDataLength = value;
  98. }
  99. }
  100. internal bool HasReservedCode {
  101. get {
  102. return _length >= 2 && Code.IsReservedStatusCode ();
  103. }
  104. }
  105. internal string Reason {
  106. get {
  107. if (_length <= 2)
  108. return String.Empty;
  109. var bytes = _data.SubArray (2, _length - 2);
  110. string reason;
  111. return bytes.TryGetUTF8DecodedString (out reason)
  112. ? reason
  113. : String.Empty;
  114. }
  115. }
  116. #endregion
  117. #region Public Properties
  118. public byte[] ApplicationData {
  119. get {
  120. return _extDataLength > 0
  121. ? _data.SubArray (_extDataLength, _length - _extDataLength)
  122. : _data;
  123. }
  124. }
  125. public byte[] ExtensionData {
  126. get {
  127. return _extDataLength > 0
  128. ? _data.SubArray (0, _extDataLength)
  129. : WebSocket.EmptyBytes;
  130. }
  131. }
  132. public ulong Length {
  133. get {
  134. return (ulong) _length;
  135. }
  136. }
  137. #endregion
  138. #region Internal Methods
  139. internal void Mask (byte[] key)
  140. {
  141. for (long i = 0; i < _length; i++)
  142. _data[i] = (byte) (_data[i] ^ key[i % 4]);
  143. }
  144. #endregion
  145. #region Public Methods
  146. public IEnumerator<byte> GetEnumerator ()
  147. {
  148. foreach (var b in _data)
  149. yield return b;
  150. }
  151. public byte[] ToArray ()
  152. {
  153. return _data;
  154. }
  155. public override string ToString ()
  156. {
  157. return BitConverter.ToString (_data);
  158. }
  159. #endregion
  160. #region Explicit Interface Implementations
  161. IEnumerator IEnumerable.GetEnumerator ()
  162. {
  163. return GetEnumerator ();
  164. }
  165. #endregion
  166. }
  167. }