PayloadData.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #region MIT License
  2. /**
  3. * PayloadData.cs
  4. *
  5. * The MIT License
  6. *
  7. * Copyright (c) 2012 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. using System.Text;
  32. namespace WebSocketSharp.Frame
  33. {
  34. public class PayloadData : IEnumerable<byte>
  35. {
  36. #region Field
  37. public const ulong MaxLength = long.MaxValue;
  38. #endregion
  39. #region Public Constructors
  40. public PayloadData(string appData)
  41. : this(Encoding.UTF8.GetBytes(appData))
  42. {
  43. }
  44. public PayloadData(byte[] appData)
  45. : this(new byte[] { }, appData)
  46. {
  47. }
  48. public PayloadData(byte[] appData, bool masked)
  49. : this(new byte[] { }, appData, masked)
  50. {
  51. }
  52. public PayloadData(byte[] extData, byte[] appData)
  53. : this(extData, appData, false)
  54. {
  55. }
  56. public PayloadData(byte[] extData, byte[] appData, bool masked)
  57. {
  58. if (extData == null)
  59. throw new ArgumentNullException("extData");
  60. if (appData == null)
  61. throw new ArgumentNullException("appData");
  62. if ((ulong)extData.LongLength + (ulong)appData.LongLength > MaxLength)
  63. throw new ArgumentOutOfRangeException("Plus 'extData' length and 'appData' lenght must be less than MaxLength.");
  64. ExtensionData = extData;
  65. ApplicationData = appData;
  66. IsMasked = masked;
  67. }
  68. #endregion
  69. #region Properties
  70. public byte[] ExtensionData { get; private set; }
  71. public byte[] ApplicationData { get; private set; }
  72. public bool IsMasked { get; private set; }
  73. public ulong Length
  74. {
  75. get
  76. {
  77. return (ulong)(ExtensionData.LongLength + ApplicationData.LongLength);
  78. }
  79. }
  80. #endregion
  81. #region Private Methods
  82. IEnumerator IEnumerable.GetEnumerator()
  83. {
  84. return GetEnumerator();
  85. }
  86. private void mask(byte[] src, byte[] key)
  87. {
  88. for (long i = 0; i < src.LongLength; i++)
  89. src[i] = (byte)(src[i] ^ key[i % 4]);
  90. }
  91. #endregion
  92. #region Public Methods
  93. public IEnumerator<byte> GetEnumerator()
  94. {
  95. foreach (byte b in ExtensionData)
  96. yield return b;
  97. foreach (byte b in ApplicationData)
  98. yield return b;
  99. }
  100. public void Mask(byte[] maskingKey)
  101. {
  102. if (maskingKey == null)
  103. throw new ArgumentNullException("maskingKey");
  104. if (maskingKey.Length != 4)
  105. throw new ArgumentOutOfRangeException("maskingKey", "'maskingKey' length must be 4.");
  106. if (ExtensionData.LongLength > 0)
  107. mask(ExtensionData, maskingKey);
  108. if (ApplicationData.LongLength > 0)
  109. mask(ApplicationData, maskingKey);
  110. IsMasked = !IsMasked;
  111. }
  112. public byte[] ToBytes()
  113. {
  114. if (ExtensionData.LongLength <= 0)
  115. return ApplicationData;
  116. var result = new byte[ExtensionData.Length + ApplicationData.Length];
  117. ExtensionData.CopyTo(result, 0);
  118. Array.Copy(ApplicationData, 0, result, ExtensionData.Length, ApplicationData.Length);
  119. return result;
  120. }
  121. public override string ToString()
  122. {
  123. return BitConverter.ToString(ToBytes());
  124. }
  125. #endregion
  126. }
  127. }