69 lines
2.3 KiB
C#
69 lines
2.3 KiB
C#
|
using System.Buffers.Binary;
|
|||
|
|
|||
|
namespace RPG.Services.Gateserver.Network;
|
|||
|
internal class NetPacket
|
|||
|
{
|
|||
|
public const int Overhead = 16;
|
|||
|
|
|||
|
private const uint HeadMagic = 0x01234567;
|
|||
|
private const uint TailMagic = 0x89ABCDEF;
|
|||
|
|
|||
|
public ushort CmdType { get; }
|
|||
|
public ReadOnlyMemory<byte> Head { get; }
|
|||
|
public ReadOnlyMemory<byte> Body { get; }
|
|||
|
|
|||
|
public int Size => Overhead + Head.Length + Body.Length;
|
|||
|
|
|||
|
public NetPacket(ushort cmdType, ReadOnlyMemory<byte> head, ReadOnlyMemory<byte> body)
|
|||
|
{
|
|||
|
CmdType = cmdType;
|
|||
|
Head = head;
|
|||
|
Body = body;
|
|||
|
}
|
|||
|
|
|||
|
public static DeserializationResult TryDeserialize(ReadOnlyMemory<byte> buffer, out NetPacket? packet, out int bytesRead)
|
|||
|
{
|
|||
|
packet = null;
|
|||
|
bytesRead = 0;
|
|||
|
if (buffer.Length < Overhead) return DeserializationResult.BufferExceeded;
|
|||
|
|
|||
|
ReadOnlySpan<byte> span = buffer.Span;
|
|||
|
|
|||
|
if (BinaryPrimitives.ReadUInt32BigEndian(span[..4]) != HeadMagic) return DeserializationResult.Corrupted;
|
|||
|
|
|||
|
ushort cmdType = BinaryPrimitives.ReadUInt16BigEndian(span[4..6]);
|
|||
|
int headSize = BinaryPrimitives.ReadUInt16BigEndian(span[6..8]);
|
|||
|
int bodySize = BinaryPrimitives.ReadInt32BigEndian(span[8..12]);
|
|||
|
|
|||
|
if (buffer.Length < Overhead + headSize + bodySize) return DeserializationResult.BufferExceeded;
|
|||
|
if (BinaryPrimitives.ReadUInt32BigEndian(span[(12 + headSize + bodySize)..]) != TailMagic) return DeserializationResult.Corrupted;
|
|||
|
|
|||
|
packet = new(cmdType, buffer.Slice(12, headSize), buffer.Slice(12 + headSize, bodySize));
|
|||
|
bytesRead = Overhead + headSize + bodySize;
|
|||
|
|
|||
|
return DeserializationResult.Success;
|
|||
|
}
|
|||
|
|
|||
|
public void Serialize(Memory<byte> buffer)
|
|||
|
{
|
|||
|
Span<byte> span = buffer.Span;
|
|||
|
|
|||
|
BinaryPrimitives.WriteUInt32BigEndian(span[..4], HeadMagic);
|
|||
|
BinaryPrimitives.WriteUInt16BigEndian(span[4..6], CmdType);
|
|||
|
BinaryPrimitives.WriteUInt16BigEndian(span[6..8], (ushort)Head.Length);
|
|||
|
BinaryPrimitives.WriteInt32BigEndian(span[8..12], Body.Length);
|
|||
|
|
|||
|
Head.CopyTo(buffer[12..]);
|
|||
|
Body.CopyTo(buffer[(12 + Head.Length)..]);
|
|||
|
|
|||
|
BinaryPrimitives.WriteUInt32BigEndian(span[(12 + Head.Length + Body.Length)..], TailMagic);
|
|||
|
}
|
|||
|
|
|||
|
public enum DeserializationResult
|
|||
|
{
|
|||
|
Success,
|
|||
|
BufferExceeded,
|
|||
|
Corrupted
|
|||
|
}
|
|||
|
}
|