FragmentCommand.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using SuperSocket.SocketBase.Command;
  6. using SuperWebSocket.Protocol;
  7. namespace SuperWebSocket.Command
  8. {
  9. /// <summary>
  10. /// FragmentCommand
  11. /// </summary>
  12. /// <typeparam name="TWebSocketSession">The type of the web socket session.</typeparam>
  13. abstract class FragmentCommand<TWebSocketSession> : CommandBase<TWebSocketSession, IWebSocketFragment>
  14. where TWebSocketSession : WebSocketSession<TWebSocketSession>, new()
  15. {
  16. /// <summary>
  17. /// Gets the UTF8 encoding which has been set ExceptionFallback.
  18. /// </summary>
  19. protected Encoding Utf8Encoding { get; private set; }
  20. /// <summary>
  21. /// Initializes a new instance of the <see cref="FragmentCommand&lt;TWebSocketSession&gt;"/> class.
  22. /// </summary>
  23. public FragmentCommand()
  24. {
  25. Utf8Encoding = Encoding.GetEncoding(65001, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
  26. }
  27. /// <summary>
  28. /// Checks the frame.
  29. /// </summary>
  30. /// <param name="frame">The frame.</param>
  31. /// <returns></returns>
  32. protected bool CheckFrame(WebSocketDataFrame frame)
  33. {
  34. //Check RSV
  35. return (frame.InnerData[0] & 0x70) == 0x00;
  36. }
  37. /// <summary>
  38. /// Checks the control frame.
  39. /// </summary>
  40. /// <param name="frame">The frame.</param>
  41. /// <returns></returns>
  42. protected bool CheckControlFrame(WebSocketDataFrame frame)
  43. {
  44. if (!CheckFrame(frame))
  45. return false;
  46. //http://tools.ietf.org/html/rfc6455#section-5.5
  47. //All control frames MUST have a payload length of 125 bytes or less and MUST NOT be fragmented
  48. if (!frame.FIN || frame.ActualPayloadLength > 125)
  49. {
  50. return false;
  51. }
  52. return true;
  53. }
  54. /// <summary>
  55. /// Gets data from websocket frames.
  56. /// </summary>
  57. /// <param name="frames">The frames.</param>
  58. /// <returns></returns>
  59. protected byte[] GetWebSocketData(IList<WebSocketDataFrame> frames)
  60. {
  61. int offset, length;
  62. var resultBuffer = new byte[frames.Sum(f => (int)f.ActualPayloadLength)];
  63. int copied = 0;
  64. for (var i = 0; i < frames.Count; i++)
  65. {
  66. var frame = frames[i];
  67. offset = frame.InnerData.Count - (int)frame.ActualPayloadLength;
  68. length = (int)frame.ActualPayloadLength;
  69. if (length > 0)
  70. {
  71. if (frame.HasMask)
  72. {
  73. frame.InnerData.DecodeMask(frame.MaskKey, offset, length);
  74. }
  75. frame.InnerData.CopyTo(resultBuffer, offset, copied, length);
  76. copied += length;
  77. }
  78. }
  79. return resultBuffer;
  80. }
  81. /// <summary>
  82. /// Gets text string from websocket frames.
  83. /// </summary>
  84. /// <param name="frames">The frames.</param>
  85. /// <returns></returns>
  86. protected string GetWebSocketText(IList<WebSocketDataFrame> frames)
  87. {
  88. var data = GetWebSocketData(frames);
  89. return Utf8Encoding.GetString(data);
  90. }
  91. /// <summary>
  92. /// Gets data from a websocket frame.
  93. /// </summary>
  94. /// <param name="frame">The frame.</param>
  95. /// <returns></returns>
  96. protected byte[] GetWebSocketData(WebSocketDataFrame frame)
  97. {
  98. int offset = frame.InnerData.Count - (int)frame.ActualPayloadLength;
  99. int length = (int)frame.ActualPayloadLength;
  100. if (frame.HasMask && length > 0)
  101. {
  102. frame.InnerData.DecodeMask(frame.MaskKey, offset, length);
  103. }
  104. byte[] data;
  105. if (length > 0)
  106. data = frame.InnerData.ToArrayData(offset, length);
  107. else
  108. data = new byte[0];
  109. return data;
  110. }
  111. /// <summary>
  112. /// Gets text string from a websocket frame.
  113. /// </summary>
  114. /// <param name="frame">The frame.</param>
  115. /// <returns></returns>
  116. protected string GetWebSocketText(WebSocketDataFrame frame)
  117. {
  118. int offset = frame.InnerData.Count - (int)frame.ActualPayloadLength;
  119. int length = (int)frame.ActualPayloadLength;
  120. if (frame.HasMask && length > 0)
  121. {
  122. frame.InnerData.DecodeMask(frame.MaskKey, offset, length);
  123. }
  124. string text;
  125. if (length > 0)
  126. {
  127. text = frame.InnerData.Decode(Utf8Encoding, offset, length);
  128. }
  129. else
  130. {
  131. text = string.Empty;
  132. }
  133. return text;
  134. }
  135. }
  136. }