using IFramework.Packets;
using System;
namespace IFramework.Net.WebSocket
{
internal class DataFrame
{
///
/// 如果为true则该消息为消息尾部,如果false为零则还有后续数据包;
///
public bool IsEof { get; set; } = true;
///
/// RSV1,RSV2,RSV3,各1位,用于扩展定义的,如果没有扩展约定的情况则必须为0
///
public bool Rsv1 { get; set; }
public bool Rsv2 { get; set; }
public bool Rsv3 { get; set; }
///
///0x0表示附加数据帧
///0x1表示文本数据帧
///0x2表示二进制数据帧
///0x3-7暂时无定义,为以后的非控制帧保留
///0x8表示连接关闭
///0x9表示ping
///0xA表示pong
///0xB-F暂时无定义,为以后的控制帧保留
///
public byte OpCode { get; set; } = 0x01;
///
/// true使用掩码解析消息
///
public bool Mask { get; set; } = false;
public long PayloadLength { get; set; }
//public int Continued { get; set; }
public byte[] MaskKey { get; set; }
//public UInt16 MaskKeyContinued { get; set; }
public SegmentOffset Payload { get; set; }
public byte[] EncodingToBytes()
{
if (Payload == null
|| Payload.buffer.LongLength != PayloadLength)
throw new Exception("payload buffer error");
if (Payload.size > 0)
{
PayloadLength = Payload.size;
}
long headLen = (Mask ? 6 : 2);
if (PayloadLength < 126)
{ }
else if (PayloadLength >= 126 && PayloadLength < 127)
{
headLen += 2;
}
else if (PayloadLength >= 127)
{
headLen += 8;
}
byte[] buffer = new byte[headLen + PayloadLength];
int pos = 0;
buffer[pos] = (byte)(IsEof ? 128 : 0);
buffer[pos] += OpCode;
buffer[++pos] = (byte)(Mask ? 128 : 0);
if (PayloadLength < 0x7e)//126
{
buffer[pos] += (byte)PayloadLength;
}
else if (PayloadLength < 0xffff)//65535
{
buffer[++pos] = 126;
buffer[++pos] = (byte)(buffer.Length >> 8);
buffer[++pos] = (byte)(buffer.Length);
}
else
{
var payLengthBytes = ((ulong)PayloadLength).ToBytes();
buffer[++pos] = 127;
buffer[++pos] = payLengthBytes[0];
buffer[++pos] = payLengthBytes[1];
buffer[++pos] = payLengthBytes[2];
buffer[++pos] = payLengthBytes[3];
buffer[++pos] = payLengthBytes[4];
buffer[++pos] = payLengthBytes[5];
buffer[++pos] = payLengthBytes[6];
buffer[++pos] = payLengthBytes[7];
}
if (Mask)
{
buffer[++pos] = MaskKey[0];
buffer[++pos] = MaskKey[1];
buffer[++pos] = MaskKey[2];
buffer[++pos] = MaskKey[3];
for (long i = 0; i < PayloadLength; ++i)
{
buffer[headLen + i] = (byte)(Payload.buffer[i+Payload.offset] ^ MaskKey[i % 4]);
}
}
else
{
for (long i = 0; i < PayloadLength; ++i)
{
buffer[headLen + i] = Payload.buffer[i+Payload.offset];
}
}
return buffer;
}
public bool DecodingFromBytes(SegmentOffset data, bool isMaskResolve = true)
{
if (data.size < 4) return false;
int pos = data.offset;
IsEof = (data.buffer[pos] >> 7) == 1;
OpCode = (byte)(data.buffer[pos] & 0xf);
Mask = (data.buffer[++pos] >> 7) == 1;
PayloadLength = (data.buffer[pos] & 0x7f);
//校验截取长度
if (PayloadLength >= data.size) return false;
++pos;
//数据包长度超过126,需要解析附加数据
if (PayloadLength < 126)
{
//直接等于消息长度
}
if (PayloadLength == 126)
{
PayloadLength = data.buffer.ToUInt16(pos);// BitConverter.ToUInt16(segOffset.buffer, pos);
pos += 2;
}
else if(PayloadLength==127)
{
PayloadLength = (long)data.buffer.ToUInt64(pos);
pos += 8;
}
Payload = new SegmentOffset()
{
offset = pos,
buffer = data.buffer,
size = (int)PayloadLength
};
//数据体
if (Mask)
{
//获取掩码密钥
MaskKey = new byte[4];
MaskKey[0] = data.buffer[pos];
MaskKey[1] = data.buffer[pos + 1];
MaskKey[2] = data.buffer[pos + 2];
MaskKey[3] = data.buffer[pos + 3];
pos += 4;
Payload.buffer = data.buffer;
Payload.offset = pos;
if (isMaskResolve)
{
long p = 0;
for (long i = 0; i < PayloadLength; ++i)
{
p = (long)pos + i;
Payload.buffer[p] = (byte)(Payload.buffer[p] ^ MaskKey[i % 4]);
}
}
}
else
{
Payload.buffer = data.buffer;
Payload.offset = pos;
}
return true;
}
}
}