recv packet and protos

This commit is contained in:
rfi
2024-02-18 18:07:38 +07:00
parent a737edc7ca
commit 72615243a0
34 changed files with 20443 additions and 11 deletions

View File

@@ -1,6 +1,11 @@
using BLHX.Server.Common.Utils;
using BHXY.Server.Common.Proto.p10;
using BLHX.Server.Common.Proto;
using BLHX.Server.Common.Utils;
using ProtoBuf;
using System.Buffers.Binary;
using System.Net;
using System.Net.Sockets;
using System.Text.Json;
namespace BLHX.Server.Game
{
@@ -10,11 +15,15 @@ namespace BLHX.Server.Game
readonly Logger c;
readonly CancellationTokenSource cts = new();
readonly Task loopTask;
ushort packetIdx = 0;
public static JsonSerializerOptions jsonSerializerOptions = new() { IncludeFields = true };
private ushort NextPacketIdx => packetIdx++;
public IPEndPoint EndPoint => (IPEndPoint)tcpClient.Client.RemoteEndPoint!;
public Connection(TcpClient tcpClient)
{
this.tcpClient = tcpClient;
GameServer.c.Log($"{EndPoint} connected");
c = new(EndPoint.ToString());
loopTask = Task.Run(ClientLoop, cts.Token);
}
@@ -22,27 +31,71 @@ namespace BLHX.Server.Game
private async Task ClientLoop()
{
var ns = tcpClient.GetStream();
var buf = GC.AllocateUninitializedArray<byte>(8 << 13);
var buf = GC.AllocateUninitializedArray<byte>(ushort.MaxValue);
var pos = 0;
while (!cts.Token.IsCancellationRequested)
{
await Task.Delay(1);
int len = ns.Read(buf, pos, buf.Length - pos);
len += pos;
if (len == 0)
continue;
try
{
int len = await ns.ReadAsync(buf.AsMemory(pos, buf.Length - pos), cts.Token);
c.Debug(BitConverter.ToString(buf[..len]).Replace("-", ""));
len += pos;
if (len < 1)
continue;
int readLen = 0;
while (readLen < len)
{
if (len - readLen < Packet.HEADER_SIZE + Packet.LENGTH_SIZE)
break;
var packet = new Packet(buf[readLen..]);
if (packet.command == Command.Cs10800)
{
var dec = packet.Decode<Cs10800>();
c.Debug(JsonSerializer.Serialize(dec, jsonSerializerOptions));
}
readLen += packet.length + Packet.LENGTH_SIZE;
}
pos += len - readLen;
if (pos > 0)
Array.Copy(buf, readLen, buf, 0, pos);
}
catch (Exception ex)
{
c.Error($"An error occured while reading packets {ex}");
}
}
}
public void Send<T>(T packet) where T : IExtensible
{
Command command = Enum.Parse<Command>(packet.GetType().Name);
var ns = tcpClient.GetStream();
using var ms = new MemoryStream();
Serializer.Serialize(ms, packet);
byte[] sendBuf = GC.AllocateUninitializedArray<byte>(Packet.LENGTH_SIZE + Packet.HEADER_SIZE + (int)ms.Length);
BinaryPrimitives.WriteUInt16BigEndian(sendBuf, (ushort)(ms.Length + Packet.HEADER_SIZE));
sendBuf[Packet.LENGTH_SIZE] = 0;
BinaryPrimitives.WriteUInt16BigEndian(sendBuf.AsSpan(Packet.LENGTH_SIZE + 1), (ushort)command);
BinaryPrimitives.WriteUInt16BigEndian(sendBuf.AsSpan(Packet.HEADER_SIZE), NextPacketIdx);
ms.ToArray().CopyTo(sendBuf.AsSpan(Packet.LENGTH_SIZE + Packet.HEADER_SIZE));
c.Debug(BitConverter.ToString(sendBuf).Replace("-", ""));
ns.Write(sendBuf);
}
public void EndProtocol()
{
cts.Cancel();
loopTask.Wait();
loopTask.Dispose();
loopTask.GetAwaiter().OnCompleted(loopTask.Dispose);
GameServer.c.Log($"{EndPoint} disconnected");
GameServer.connections.Remove(EndPoint);
tcpClient.Dispose();
}
}

View File

@@ -0,0 +1,29 @@
using BLHX.Server.Common.Proto;
using ProtoBuf;
using System.Buffers.Binary;
namespace BLHX.Server.Game
{
readonly struct Packet
{
public const int LENGTH_SIZE = 2;
public const int HEADER_SIZE = 5;
public readonly ushort length;
public readonly byte flag;
public readonly Command command;
public readonly ushort id;
public readonly byte[] bytes;
public Packet(byte[] recv)
{
length = BinaryPrimitives.ReadUInt16BigEndian(recv);
flag = recv[LENGTH_SIZE];
command = (Command)BinaryPrimitives.ReadUInt16BigEndian(recv.AsSpan(LENGTH_SIZE + 1));
id = BinaryPrimitives.ReadUInt16BigEndian(recv.AsSpan(HEADER_SIZE));
bytes = GC.AllocateUninitializedArray<byte>(length - HEADER_SIZE);
Array.Copy(recv, HEADER_SIZE + LENGTH_SIZE, bytes, 0, length - HEADER_SIZE);
}
public T Decode<T>() where T : IExtensible => Serializer.Deserialize<T>(bytes.AsSpan());
}
}