LengthFieldBasedFrameBuilder.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System;
  2. using MECF.Framework.Common.Communications.Tcp.Socket.Framing.Base;
  3. namespace MECF.Framework.Common.Communications.Tcp.Socket.Framing
  4. {
  5. public enum LengthField
  6. {
  7. OneByte = 1,
  8. TwoBytes = 2,
  9. FourBytes = 4,
  10. EigthBytes = 8,
  11. }
  12. public sealed class LengthFieldBasedFrameBuilder : FrameBuilder
  13. {
  14. public LengthFieldBasedFrameBuilder()
  15. : this(LengthField.FourBytes)
  16. {
  17. }
  18. public LengthFieldBasedFrameBuilder(LengthField lengthField)
  19. : this(new LengthFieldBasedFrameEncoder(lengthField), new LengthFieldBasedFrameDecoder(lengthField))
  20. {
  21. }
  22. public LengthFieldBasedFrameBuilder(LengthFieldBasedFrameEncoder encoder, LengthFieldBasedFrameDecoder decoder)
  23. : base(encoder, decoder)
  24. {
  25. }
  26. }
  27. public sealed class LengthFieldBasedFrameEncoder : IFrameEncoder
  28. {
  29. public LengthFieldBasedFrameEncoder(LengthField lengthField)
  30. {
  31. LengthField = lengthField;
  32. }
  33. public LengthField LengthField { get; private set; }
  34. public void EncodeFrame(byte[] payload, int offset, int count, out byte[] frameBuffer, out int frameBufferOffset, out int frameBufferLength)
  35. {
  36. byte[] buffer = null;
  37. switch (this.LengthField)
  38. {
  39. case LengthField.OneByte:
  40. {
  41. if (count > byte.MaxValue)
  42. {
  43. throw new ArgumentOutOfRangeException("count");
  44. }
  45. buffer = new byte[1 + count];
  46. buffer[0] = (byte)count;
  47. Array.Copy(payload, offset, buffer, 1, count);
  48. }
  49. break;
  50. case LengthField.TwoBytes:
  51. {
  52. if (count > short.MaxValue)
  53. {
  54. throw new ArgumentOutOfRangeException("count");
  55. }
  56. buffer = new byte[2 + count];
  57. buffer[0] = (byte)((ushort)count >> 8);
  58. buffer[1] = (byte)count;
  59. Array.Copy(payload, offset, buffer, 2, count);
  60. }
  61. break;
  62. case LengthField.FourBytes:
  63. {
  64. buffer = new byte[4 + count];
  65. uint unsignedValue = (uint)count;
  66. buffer[0] = (byte)(unsignedValue >> 24);
  67. buffer[1] = (byte)(unsignedValue >> 16);
  68. buffer[2] = (byte)(unsignedValue >> 8);
  69. buffer[3] = (byte)unsignedValue;
  70. Array.Copy(payload, offset, buffer, 4, count);
  71. }
  72. break;
  73. case LengthField.EigthBytes:
  74. {
  75. buffer = new byte[8 + count];
  76. ulong unsignedValue = (ulong)count;
  77. buffer[0] = (byte)(unsignedValue >> 56);
  78. buffer[1] = (byte)(unsignedValue >> 48);
  79. buffer[2] = (byte)(unsignedValue >> 40);
  80. buffer[3] = (byte)(unsignedValue >> 32);
  81. buffer[4] = (byte)(unsignedValue >> 24);
  82. buffer[5] = (byte)(unsignedValue >> 16);
  83. buffer[6] = (byte)(unsignedValue >> 8);
  84. buffer[7] = (byte)unsignedValue;
  85. Array.Copy(payload, offset, buffer, 8, count);
  86. }
  87. break;
  88. default:
  89. throw new NotSupportedException("Specified length field is not supported.");
  90. }
  91. frameBuffer = buffer;
  92. frameBufferOffset = 0;
  93. frameBufferLength = buffer.Length;
  94. }
  95. }
  96. public sealed class LengthFieldBasedFrameDecoder : IFrameDecoder
  97. {
  98. public LengthFieldBasedFrameDecoder(LengthField lengthField)
  99. {
  100. LengthField = lengthField;
  101. }
  102. public LengthField LengthField { get; private set; }
  103. public bool TryDecodeFrame(byte[] buffer, int offset, int count, out int frameLength, out byte[] payload, out int payloadOffset, out int payloadCount)
  104. {
  105. frameLength = 0;
  106. payload = null;
  107. payloadOffset = 0;
  108. payloadCount = 0;
  109. byte[] output = null;
  110. long length = 0;
  111. switch (this.LengthField)
  112. {
  113. case LengthField.OneByte:
  114. {
  115. if (count < 1)
  116. return false;
  117. length = buffer[offset];
  118. if (count - 1 < length)
  119. return false;
  120. output = new byte[length];
  121. Array.Copy(buffer, offset + 1, output, 0, length);
  122. }
  123. break;
  124. case LengthField.TwoBytes:
  125. {
  126. if (count < 2)
  127. return false;
  128. length = (short)(buffer[offset] << 8 | buffer[offset + 1]);
  129. if (count - 2 < length)
  130. return false;
  131. output = new byte[length];
  132. Array.Copy(buffer, offset + 2, output, 0, length);
  133. }
  134. break;
  135. case LengthField.FourBytes:
  136. {
  137. if (count < 4)
  138. return false;
  139. length = buffer[offset] << 24 |
  140. buffer[offset + 1] << 16 |
  141. buffer[offset + 2] << 8 |
  142. buffer[offset + 3];
  143. if (count - 4 < length)
  144. return false;
  145. output = new byte[length];
  146. Array.Copy(buffer, offset + 4, output, 0, length);
  147. }
  148. break;
  149. case LengthField.EigthBytes:
  150. {
  151. if (count < 8)
  152. return false;
  153. int i1 = buffer[offset] << 24 |
  154. buffer[offset + 1] << 16 |
  155. buffer[offset + 2] << 8 |
  156. buffer[offset + 3];
  157. int i2 = buffer[offset + 4] << 24 |
  158. buffer[offset + 5] << 16 |
  159. buffer[offset + 6] << 8 |
  160. buffer[offset + 7];
  161. length = (uint)i2 | ((long)i1 << 32);
  162. if (count - 8 < length)
  163. return false;
  164. output = new byte[length];
  165. Array.Copy(buffer, offset + 8, output, 0, length);
  166. }
  167. break;
  168. default:
  169. throw new NotSupportedException("Specified length field is not supported.");
  170. }
  171. payload = output;
  172. payloadOffset = 0;
  173. payloadCount = output.Length;
  174. frameLength = (int)this.LengthField + output.Length;
  175. return true;
  176. }
  177. }
  178. }