85 lines
2.1 KiB
C#
85 lines
2.1 KiB
C#
using System;
|
|
using MECF.Framework.Common.Communications.Tcp.Socket.Framing.Base;
|
|
|
|
namespace MECF.Framework.Common.Communications.Tcp.Socket.Framing
|
|
{
|
|
public sealed class LengthPrefixedFrameEncoder : IFrameEncoder
|
|
{
|
|
private static readonly Random _rng = new Random(DateTime.UtcNow.Millisecond);
|
|
|
|
private static readonly int MaskingKeyLength = 4;
|
|
|
|
public bool IsMasked { get; private set; }
|
|
|
|
public LengthPrefixedFrameEncoder(bool isMasked = false)
|
|
{
|
|
IsMasked = isMasked;
|
|
}
|
|
|
|
public void EncodeFrame(byte[] payload, int offset, int count, out byte[] frameBuffer, out int frameBufferOffset, out int frameBufferLength)
|
|
{
|
|
byte[] array = (frameBuffer = Encode(payload, offset, count, IsMasked));
|
|
frameBufferOffset = 0;
|
|
frameBufferLength = array.Length;
|
|
}
|
|
|
|
private static byte[] Encode(byte[] payload, int offset, int count, bool isMasked = false)
|
|
{
|
|
byte[] array;
|
|
if (count < 126)
|
|
{
|
|
array = new byte[1 + (isMasked ? MaskingKeyLength : 0) + count];
|
|
array[0] = (byte)count;
|
|
}
|
|
else if (count < 65536)
|
|
{
|
|
array = new byte[3 + (isMasked ? MaskingKeyLength : 0) + count];
|
|
array[0] = 126;
|
|
array[1] = (byte)(count / 256);
|
|
array[2] = (byte)(count % 256);
|
|
}
|
|
else
|
|
{
|
|
array = new byte[9 + (isMasked ? MaskingKeyLength : 0) + count];
|
|
array[0] = 127;
|
|
int num = count;
|
|
for (int num2 = 8; num2 > 0; num2--)
|
|
{
|
|
array[num2] = (byte)(num % 256);
|
|
num /= 256;
|
|
if (num == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (isMasked)
|
|
{
|
|
array[0] = (byte)(array[0] | 0x80u);
|
|
}
|
|
if (isMasked)
|
|
{
|
|
int num3 = array.Length - (MaskingKeyLength + count);
|
|
for (int i = num3; i < num3 + MaskingKeyLength; i++)
|
|
{
|
|
array[i] = (byte)_rng.Next(0, 255);
|
|
}
|
|
if (count > 0)
|
|
{
|
|
int num4 = array.Length - count;
|
|
for (int j = 0; j < count; j++)
|
|
{
|
|
array[num4 + j] = (byte)(payload[offset + j] ^ array[num3 + j % MaskingKeyLength]);
|
|
}
|
|
}
|
|
}
|
|
else if (count > 0)
|
|
{
|
|
int destinationIndex = array.Length - count;
|
|
Array.Copy(payload, offset, array, destinationIndex, count);
|
|
}
|
|
return array;
|
|
}
|
|
}
|
|
}
|