using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using NLog.Layouts; using NLog.Internal.Fakeables; using Google.Protobuf; using Google.Protobuf.Reflection; using Amazon.Runtime.Internal.Transform; using RabbitMQ.Client.Events; using ServerCore; using ServerBase; namespace ServerBase; //============================================================================================= // 패킷 수신 관리자 // // author : kangms // //============================================================================================= public class PacketReceiver { private readonly ISession m_owner; private readonly Dictionary m_packet_recv_handlers = new(); private readonly Dictionary m_p2p_packet_recv_handler = new(); public delegate bool FnIsValidPacketNamespace(string toCheckNamespace, IPacketCommand packetCommand); public PacketReceiver(ISession session) { m_owner = session; } public async Task registerRecvHandlerAll() { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); FnIsValidPacketNamespace fn_is_valid_packet_namespace; var packet_namespace_verifier = m_owner as IWithPacketNamespaceVerifier; if (null != packet_namespace_verifier) { fn_is_valid_packet_namespace = packet_namespace_verifier.isValidPacketNamespace; } else { fn_is_valid_packet_namespace = isValidDefaultNamespace; } return await Task.Run(() => { foreach(var assembly in assemblies) { foreach (Type type in assembly.GetTypes()) { var custom_attribs = (PacketHandlerAttribute[])type.GetCustomAttributes(typeof(PacketHandlerAttribute), true); if (custom_attribs.Length <= 0) { continue; } foreach (var each in custom_attribs) { if (false == m_owner.GetType().Equals(each.getHandlerOwner())) { break; } if (false == fn_is_valid_packet_namespace(type.Namespace ?? string.Empty, each.getPacketCommand())) { break; } var packet_command = each.getPacketCommand(); if (false == isValidPacketRecvHander(each.getHandlerClass())) { break; } if (true == hasRecvHandler(packet_command)) { Log.getLogger().error($"Already register PacketCommand !!! : packetCommnad:{packet_command.toBasicString()}"); return false; } var handler_class = Activator.CreateInstance(each.getHandlerClass()) as PacketRecvHandler; if (null == handler_class) { Log.getLogger().error($"Failed to create PacketRecvHandler !!! : packetCommnad:{packet_command.toBasicString()}"); return false; } registerRecvHandler(packet_command, handler_class); break; } } } if(0 >= m_packet_recv_handlers.Count) { Log.getLogger().error($"No PacketRecvHandler registered !!!"); return false; } return true; }); } public bool registerRecvHandler(IPacketCommand packetCommand, PacketRecvHandler toRegisterRecvHandler) { if (true == m_packet_recv_handlers.ContainsKey(packetCommand.getCommandKey())) { Log.getLogger().error($"Already registered Recv Handler !!! : {packetCommand.toBasicString()}"); return false; } m_packet_recv_handlers.Add(packetCommand.getCommandKey(), toRegisterRecvHandler); return true; } public bool fillupProudNetPacketCommand(Google.Protobuf.IMessage protoMessage, out ProudNetPacketCommand? packetCommand) { packetCommand = null; if (null == protoMessage) { Log.getLogger().fatal($"Invalid param Protobuf Message !!!"); return false; } if(false == protoMessage.makeProudNetPacketCommand(out packetCommand)) { Log.getLogger().fatal($"Failed to make ProudNet PacketCommand !!! : {protoMessage.toBasicString()}"); return false; } return true; } public bool fillupRabbitMqPacketCommand(BasicDeliverEventArgs ea, Google.Protobuf.IMessage protoMessage, out RabbitMqPacketCommand? packetCommand) { packetCommand = null; if (null == protoMessage) { ServerCore.Log.getLogger().fatal($"Invalid param Protobuf Message !!!"); return false; } if (false == protoMessage.makeRabbitMqPacketCommand(ea, out packetCommand)) { ServerCore.Log.getLogger().fatal($"Failed to make RabbitMq PacketCommand !!! : {protoMessage.toBasicString()}"); return false; } return true; } public bool isValidPacketRecvHander(Type pakcetRecvHandler) { if (false == pakcetRecvHandler.IsSubclassOf(typeof(PacketRecvHandler))) { return false; } return true; } public PacketRecvHandler? findRecvHandler(IPacketCommand packetCommand) { if (false == m_packet_recv_handlers.ContainsKey(packetCommand.getCommandKey())) { return null; } return m_packet_recv_handlers[packetCommand.getCommandKey()]; } public bool hasRecvHandler(IPacketCommand packetCommand) { if (true == m_packet_recv_handlers.ContainsKey(packetCommand.getCommandKey())) { return true; } return false; } public bool isValidDefaultNamespace(string toCheckNamespace, IPacketCommand packetCommand) { var packet_namespace = ".PacketHandler"; if ( null != toCheckNamespace && true == toCheckNamespace.Contains(packet_namespace)) { return true; } else { ServerCore.Log.getLogger().error($"Invalid Default PacketNamespace !!!, not included Namespace : {packet_namespace} ⊆ {toCheckNamespace}, packetCommnad:{packetCommand.toBasicString()}"); } return false; } public static bool isEqualPacket(Google.Protobuf.IMessage recvMessage) where T : class { if (false == typeof(T).Equals(recvMessage)) { return false; } return true; } public async Task registerP2PRecvHandlerAll() { await Task.CompletedTask; var assemblies = AppDomain.CurrentDomain.GetAssemblies(); //추후 packet 단위로 쪼개야 할때 이부분 수정해야한다. foreach(var assembly in assemblies) { foreach (Type type in assembly.GetTypes()) { if (typeof(P2PPacketRecvHandler).IsAssignableFrom(type) && !type.IsAbstract) { try { var obj = Activator.CreateInstance(type); if (obj is P2PPacketRecvHandler instance) { m_p2p_packet_recv_handler.Add(instance.getTypeName(), instance); } else { Log.getLogger().error($"Failed to create instance of {type.FullName} or not P2PPacketRecvHandler"); } } catch (Exception ex) { Log.getLogger().error($"Failed to create instance of {type.FullName}: {ex.Message}"); } } } } if (m_p2p_packet_recv_handler.Count == 0) { Log.getLogger().debug("P2PPacketRecvHandler instance is zero"); } return true; } public P2PPacketRecvHandler? findP2PPacketHandler(string key) { if (false == m_p2p_packet_recv_handler.ContainsKey(key)) { return null; } //일단 handler 1개만 등록 해놓고 거기서 처리 하도록 한다. 패킷별로 로직 처리 해야되면 패킷별로 핸들러 등록한다. return m_p2p_packet_recv_handler.Values.ToArray()[0]; } }