working tcp (kinda), send still brokey

This commit is contained in:
rfi 2023-10-10 16:56:08 +07:00
parent 0eacd1bfe2
commit 8c53541d7f
7 changed files with 2279 additions and 10 deletions

View File

@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="Config.Net" Version="5.1.5" />
<PackageReference Include="MessagePack" Version="2.5.129" />
<PackageReference Include="MongoDB.Driver" Version="2.21.0" />
</ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
using AscNet.Common.MsgPack;
using MessagePack;
namespace AscNet.GameServer.Handlers
{
internal class AccountModule
{
[PacketHandler("HandshakeRequest")]
public static void HandshakeRequestHandler(Session session, byte[] packet)
{
HandshakeRequest request = MessagePackSerializer.Deserialize<HandshakeRequest>(packet);
HandshakeResponse response = new()
{
Code = 0,
UtcOpenTime = 0,
Sha1Table = null
};
session.SendResponse(response);
}
}
}

View File

@ -1,4 +1,6 @@
using MessagePack;
using System.Reflection;
using AscNet.Common.Util;
using MessagePack;
namespace AscNet.GameServer
{
@ -73,4 +75,49 @@ namespace AscNet.GameServer
}
}
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
[AttributeUsage(AttributeTargets.Method)]
public class PacketHandler : Attribute
{
public string Name { get; }
public PacketHandler(string name)
{
Name = name;
}
}
public delegate void PacketHandlerDelegate(Session session, byte[] packet);
public static class PacketFactory
{
public static readonly Dictionary<string, PacketHandlerDelegate> Handlers = new();
static readonly Logger c = new("Factory", ConsoleColor.Yellow);
public static void LoadPacketHandlers()
{
c.Log("Loading Packet Handlers...");
IEnumerable<Type> classes = from t in Assembly.GetExecutingAssembly().GetTypes()
select t;
foreach (var method in classes.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)))
{
var attr = method.GetCustomAttribute<PacketHandler>(false);
if (attr == null || Handlers.ContainsKey(attr.Name)) continue;
Handlers.Add(attr.Name, (PacketHandlerDelegate)Delegate.CreateDelegate(typeof(PacketHandlerDelegate), method));
#if DEBUG
c.Log($"Loaded {method.Name}");
#endif
}
c.Log("Finished Loading Packet Handlers");
}
public static PacketHandlerDelegate? GetPacketHandler(string name)
{
Handlers.TryGetValue(name, out PacketHandlerDelegate? handler);
return handler;
}
}
}

View File

@ -1,5 +1,8 @@
using System.Net.Sockets;
using System.Buffers.Binary;
using System.Net.Mail;
using System.Net.Sockets;
using AscNet.Common.Util;
using MessagePack;
namespace AscNet.GameServer
{
@ -9,7 +12,8 @@ namespace AscNet.GameServer
public readonly TcpClient client;
public readonly Logger c;
private long lastPacketTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
// private ushort packetNo = 0;
private ushort packetNo = 0;
private readonly MessagePackSerializerOptions lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4Block);
public Session(string id, TcpClient tcpClient)
{
@ -35,7 +39,55 @@ namespace AscNet.GameServer
if (len > 0)
{
lastPacketTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
List<Packet> packets = new();
int readbytes = 0;
while (readbytes < len)
{
int packetLen = BinaryPrimitives.ReadInt32LittleEndian(msg.AsSpan()[readbytes..]);
readbytes += 4;
if (packetLen < 4)
break;
else
{
byte[] packet = GC.AllocateUninitializedArray<byte>(packetLen);
Array.Copy(msg, readbytes, packet, 0, packetLen);
readbytes += packetLen;
Crypto.HaruCrypt.Decrypt(packet);
try
{
packets.Add(MessagePackSerializer.Deserialize<Packet>(packet, lz4Options));
}
catch (Exception)
{
c.Error("Failed to deserialize packet: " + BitConverter.ToString(packet).Replace("-", ""));
}
}
}
foreach (var packet in packets)
{
switch (packet.Type)
{
case Packet.ContentType.Request:
Packet.Request request = MessagePackSerializer.Deserialize<Packet.Request>(packet.Content);
c.Log(request.Name);
PacketFactory.GetPacketHandler(request.Name)?.Invoke(this, request.Content);
break;
case Packet.ContentType.Push:
Packet.Push push = MessagePackSerializer.Deserialize<Packet.Push>(packet.Content);
c.Log(push.Name);
PacketFactory.GetPacketHandler(push.Name)?.Invoke(this, push.Content);
break;
case Packet.ContentType.Exception:
Packet.Exception exception = MessagePackSerializer.Deserialize<Packet.Exception>(packet.Content);
c.Error($"Exception packet received: {exception.Code}, {exception.Message}");
break;
default:
break;
}
}
}
}
@ -52,6 +104,55 @@ namespace AscNet.GameServer
DisconnectProtocol();
}
public void SendPush<T>(T push)
{
Packet.Push packet = new()
{
Name = typeof(T).Name,
Content = MessagePackSerializer.Serialize(push)
};
Send(new Packet()
{
No = packetNo,
Type = Packet.ContentType.Push,
Content = MessagePackSerializer.Serialize(packet)
});
c.Log(packet.Name);
packetNo++;
}
public void SendResponse<T>(T response)
{
Packet.Response packet = new()
{
Id = 0,
Name = typeof(T).Name,
Content = MessagePackSerializer.Serialize(response)
};
Send(new Packet()
{
No = packetNo,
Type = Packet.ContentType.Response,
Content = MessagePackSerializer.Serialize(packet)
});
c.Log(packet.Name);
packetNo++;
}
private void Send(Packet packet)
{
byte[] serializedPacket = MessagePackSerializer.Serialize(packet, lz4Options);
byte[] sendBytes = GC.AllocateUninitializedArray<byte>(serializedPacket.Length + 4);
BinaryPrimitives.WriteInt32LittleEndian(sendBytes, serializedPacket.Length);
Array.Copy(serializedPacket, 0, sendBytes, 4, serializedPacket.Length);
Crypto.HaruCrypt.Encrypt(sendBytes);
client.GetStream().Write(sendBytes);
}
public void DisconnectProtocol()
{
if (Server.Instance.Sessions.GetValueOrDefault(id) is null)

View File

@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AscNet.Common\AscNet.Common.csproj" />
<ProjectReference Include="..\AscNet.GameServer\AscNet.GameServer.csproj" />
<ProjectReference Include="..\AscNet.SDKServer\AscNet.SDKServer.csproj" />
</ItemGroup>

File diff suppressed because one or more lines are too long