Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/Communications/Tcp/Socket/Framing/LengthPrefixedFrameDecoder.cs

124 lines
2.9 KiB
C#

using MECF.Framework.Common.Communications.Tcp.Socket.Framing.Base;
namespace MECF.Framework.Common.Communications.Tcp.Socket.Framing
{
public sealed class LengthPrefixedFrameDecoder : IFrameDecoder
{
internal sealed class Header
{
public bool IsMasked { get; set; }
public int PayloadLength { get; set; }
public int MaskingKeyOffset { get; set; }
public int Length { get; set; }
public override string ToString()
{
return $"IsMasked[{IsMasked}], PayloadLength[{PayloadLength}], MaskingKeyOffset[{MaskingKeyOffset}], Length[{Length}]";
}
}
private static readonly int MaskingKeyLength = 4;
public bool IsMasked { get; private set; }
public LengthPrefixedFrameDecoder(bool isMasked = false)
{
IsMasked = isMasked;
}
public bool TryDecodeFrame(byte[] buffer, int offset, int count, out int frameLength, out byte[] payload, out int payloadOffset, out int payloadCount)
{
frameLength = 0;
payload = null;
payloadOffset = 0;
payloadCount = 0;
Header header = DecodeHeader(buffer, offset, count);
if (header != null && header.Length + header.PayloadLength <= count)
{
if (IsMasked)
{
payload = DecodeMaskedPayload(buffer, offset, header.MaskingKeyOffset, header.Length, header.PayloadLength);
payloadOffset = 0;
payloadCount = payload.Length;
}
else
{
payload = buffer;
payloadOffset = offset + header.Length;
payloadCount = header.PayloadLength;
}
frameLength = header.Length + header.PayloadLength;
return true;
}
return false;
}
private static Header DecodeHeader(byte[] buffer, int offset, int count)
{
if (count < 1)
{
return null;
}
Header header = new Header
{
IsMasked = ((buffer[offset] & 0x80) == 128),
PayloadLength = (buffer[offset] & 0x7F),
Length = 1
};
if (header.PayloadLength >= 126)
{
if (header.PayloadLength == 126)
{
header.Length += 2;
}
else
{
header.Length += 8;
}
if (count < header.Length)
{
return null;
}
if (header.PayloadLength == 126)
{
header.PayloadLength = buffer[offset + 1] * 256 + buffer[offset + 2];
}
else
{
int num = 0;
int num2 = 1;
for (int num3 = 7; num3 >= 0; num3--)
{
num += buffer[offset + num3 + 1] * num2;
num2 *= 256;
}
header.PayloadLength = num;
}
}
if (header.IsMasked)
{
if (count < header.Length + MaskingKeyLength)
{
return null;
}
header.MaskingKeyOffset = header.Length;
header.Length += MaskingKeyLength;
}
return header;
}
private static byte[] DecodeMaskedPayload(byte[] buffer, int offset, int maskingKeyOffset, int payloadOffset, int payloadCount)
{
byte[] array = new byte[payloadCount];
for (int i = 0; i < payloadCount; i++)
{
array[i] = (byte)(buffer[offset + payloadOffset + i] ^ buffer[offset + maskingKeyOffset + i % MaskingKeyLength]);
}
return array;
}
}
}