초기커밋
This commit is contained in:
831
ServerBase/ProudNet/Session/SessionBase.cs
Normal file
831
ServerBase/ProudNet/Session/SessionBase.cs
Normal file
@@ -0,0 +1,831 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
using Google.Protobuf;
|
||||
using Nettention.Proud;
|
||||
using OtpNet;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
|
||||
using MODULE_ID = System.UInt32;
|
||||
using HostID = Nettention.Proud.HostID;
|
||||
using SESSION_ID = System.Int32;
|
||||
|
||||
|
||||
namespace ServerBase;
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
// 네트워크 세션 기반 클래스 이다.
|
||||
//
|
||||
// author : kangms
|
||||
//
|
||||
//=============================================================================================
|
||||
|
||||
public abstract partial class SessionBase : ISession, IInitializer
|
||||
{
|
||||
private readonly IRmiHost m_net_host;
|
||||
|
||||
private ConcurrentDictionary<Type, Nettention.Proud.RmiStub> m_stubs = new();
|
||||
private ConcurrentDictionary<Type, Nettention.Proud.RmiProxy> m_proxies = new();
|
||||
|
||||
public delegate bool onRecv<T>(Nettention.Proud.HostID remote, Nettention.Proud.RmiContext rmiContext, T recvProtocol);
|
||||
|
||||
public delegate bool FnProudNetIOPacketToHost(Nettention.Proud.HostID remote, Nettention.Proud.RmiContext rmiContext, IMessage msg);
|
||||
public FnProudNetIOPacketToHost? FnSendPacketToHost;
|
||||
|
||||
public delegate bool FnProudNetIOPacketToHosts(Nettention.Proud.HostID[] remotes, Nettention.Proud.RmiContext rmiContext, IMessage msg);
|
||||
public FnProudNetIOPacketToHosts? FnSendPacketToHosts;
|
||||
|
||||
private readonly PacketReceiver m_packet_receiver;
|
||||
private readonly PacketSender m_packet_sender;
|
||||
|
||||
private int m_large_packet_check_size = Constant.LARGE_PACKET_CHECK_DEFAULT_SIZE;
|
||||
private int m_packet_chunk_size = Constant.PACKET_CHUNK_DEFAULT_SIZE;
|
||||
|
||||
private LargePacketHandler m_large_packet_handler = new();
|
||||
|
||||
public enum ConnectionState
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Disconnected = 1,
|
||||
TryConnecting = 2,
|
||||
Connected = 3,
|
||||
}
|
||||
|
||||
private ConnectionState m_connection_state = ConnectionState.Disconnected;
|
||||
|
||||
public SessionBase(IRmiHost rmiHost)
|
||||
{
|
||||
m_net_host = rmiHost;
|
||||
|
||||
m_packet_receiver = new PacketReceiver(this);
|
||||
m_packet_sender = new PacketSender(this);
|
||||
}
|
||||
|
||||
// for IInitializer
|
||||
public virtual async Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg = string.Empty;
|
||||
|
||||
var rmi_host = getRmiHost();
|
||||
if(null == rmi_host)
|
||||
{
|
||||
err_msg = $"Rmi Host is Null !!! - {toBasicString()}";
|
||||
result.setFail(ServerErrorCode.RmiHostIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if(false == onBindRmiHostHandler(rmi_host))
|
||||
{
|
||||
err_msg = $"Failed to bind Rmi Host Handler !!! - {toBasicString()}";
|
||||
result.setFail(ServerErrorCode.RmiHostHandlerBindFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (false == await m_packet_receiver.registerRecvHandlerAll())
|
||||
{
|
||||
err_msg = $"Failed to register RecvHandler All !!! - {toBasicString()}";
|
||||
result.setFail(ServerErrorCode.PacketRecvHandlerRegisterFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (false == await m_packet_sender.registerSendHandlerAll())
|
||||
{
|
||||
err_msg = $"Failed to register SendHandler All !!! - {toBasicString()}";
|
||||
result.setFail(ServerErrorCode.PacketSendHandlerRegisterFailed, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (false == await m_packet_receiver.registerP2PRecvHandlerAll())
|
||||
{
|
||||
//P2PPacketRecvHandler 여러개 추가 할시 Result 필요
|
||||
var msg = $"Failed to register P2P RecvHandler All !!! - {toBasicString()}";
|
||||
//result.setFail(ServerErrorCode.PacketRecvHandlerRegisterFailed, err_msg);
|
||||
Log.getLogger().warn(msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool resisterStub<TStub>(TStub stub)
|
||||
where TStub : Nettention.Proud.RmiStub
|
||||
{
|
||||
var net_server = getRmiHost();
|
||||
NullReferenceCheckHelper.throwIfNull(net_server, () => $"net_server is null !!!");
|
||||
|
||||
if (false == m_stubs.TryAdd(typeof(TStub), stub))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
net_server.AttachStub(stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool unresisterStub(Type type)
|
||||
{
|
||||
return m_stubs.TryRemove(type, out _);
|
||||
}
|
||||
|
||||
public TStub findStub<TStub>()
|
||||
where TStub : Nettention.Proud.RmiStub
|
||||
{
|
||||
m_stubs.TryGetValue(typeof(TStub), out var found_stub);
|
||||
var casted_stub = found_stub as TStub;
|
||||
NullReferenceCheckHelper.throwIfNull(casted_stub, () => $"casted_stub is null !!! : type:{typeof(TStub).getTypeName()}");
|
||||
return casted_stub;
|
||||
}
|
||||
|
||||
public bool resisterProxy<TProxy>(TProxy proxy)
|
||||
where TProxy : Nettention.Proud.RmiProxy
|
||||
{
|
||||
var net_server = getRmiHost();
|
||||
NullReferenceCheckHelper.throwIfNull(net_server, () => $"net_server is null !!!");
|
||||
|
||||
if(false == m_proxies.TryAdd(typeof(TProxy), proxy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
net_server.AttachProxy(proxy);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool unresisterProxy(Type type)
|
||||
{
|
||||
return m_proxies.TryRemove(type, out _);
|
||||
}
|
||||
|
||||
public TProxy findProxy<TProxy>()
|
||||
where TProxy : Nettention.Proud.RmiProxy
|
||||
{
|
||||
m_proxies.TryGetValue(typeof(TProxy), out var found_proxy);
|
||||
var casted_proxy = found_proxy as TProxy;
|
||||
NullReferenceCheckHelper.throwIfNull(casted_proxy, () => $"casted_proxy is null !!! : type:{typeof(TProxy).getTypeName()}");
|
||||
return casted_proxy;
|
||||
}
|
||||
|
||||
#region 재정의 해야 하는 함수들
|
||||
protected abstract bool onBindRmiHostHandler(IRmiHost currRmiHost);
|
||||
|
||||
protected abstract bool onBindStubHandler();
|
||||
|
||||
#endregion 재정의 해야 하는 함수들
|
||||
|
||||
public abstract IEntityWithSession? onLookupEntityWithSession(SESSION_ID targetSessionId);
|
||||
|
||||
protected bool onRecvProtocol<T>(Nettention.Proud.HostID remote, Nettention.Proud.RmiContext rmiContext, T recvProtocol)
|
||||
where T : Google.Protobuf.IMessage
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var session_id = 0;
|
||||
var recv_protocol_type = string.Empty;
|
||||
var entity_basic_string = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(rmiContext, () => $"rmiContext is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(recvProtocol, () => $"recvProtocol is null !!!");
|
||||
|
||||
Log.getLogger().debug($"recvProtocol:{recvProtocol.ToString()} - HostID:{remote}");
|
||||
|
||||
session_id = remote.toSESSION_ID();
|
||||
recv_protocol_type = recvProtocol.ToString();
|
||||
|
||||
var found_entity_with_session = onLookupEntityWithSession(session_id);
|
||||
if (found_entity_with_session == null)
|
||||
{
|
||||
err_msg = $"Not found remoteSession !!! - sessionId:{session_id}, recvProtocolType:{recv_protocol_type}, HostID:{remote}";
|
||||
Log.getLogger().warn(err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
entity_basic_string = found_entity_with_session.toBasicString();
|
||||
Log.getLogger().debug($"recvByEntitySession:{recvProtocol.ToString()} - {entity_basic_string}");
|
||||
|
||||
var task_serializer = found_entity_with_session as IWithTaskSerializer;
|
||||
if (null == task_serializer)
|
||||
{
|
||||
err_msg = $"Failed to cast IWithTaskSerializer - sessionId:{session_id}, recvProtocolType:{recv_protocol_type}, HostID:{remote}, entityBasicString:{entity_basic_string}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
recvProtocol.makeProudNetPacketCommand(out var packetCommand);
|
||||
NullReferenceCheckHelper.throwIfNull(packetCommand, () => $"packetCommand is null !!! - entityBasicString:{entity_basic_string}");
|
||||
|
||||
var func = getCallProtocolHandler(found_entity_with_session, recvProtocol, packetCommand);
|
||||
_ = task_serializer.getTaskSerializer().postLogicFunc(func, packetCommand.toBasicString());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.getLogger().fatal($"Exception !!!, Failed to perform in SessionBase.onRecvProtocol<{recvProtocol.getTypeName()}>() : exception:{e} - sessionId:{session_id}, recvProtocolType:{recv_protocol_type}, HostID:{remote}, entityBasicString:{entity_basic_string}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Func<Task> getCallProtocolHandler<T>(IEntityWithSession session, T recvProtocol, ProudNetPacketCommand packetCommand)
|
||||
where T : Google.Protobuf.IMessage
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(session, () => $"Session is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(recvProtocol, () => $"recvProtocol is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(packetCommand, () => $"packetCommand is null !!!");
|
||||
|
||||
System.Type command_type = packetCommand.getCommandType();
|
||||
switch (command_type)
|
||||
{
|
||||
case var _ when command_type == typeof(ClientToGameReq.Types.C2S_REQ_LARGE_PACKET):
|
||||
return async () => await onCallLargeSizeProtocolHandler(session, recvProtocol);
|
||||
default:
|
||||
return async () => await onCallProtocolHandler(session, recvProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> onCallProtocolHandler<T>(IEntityWithSession session, T recvProtocol)
|
||||
where T : Google.Protobuf.IMessage
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
ProudNetPacketCommand? fillup_packet_command = null;
|
||||
PacketRecvHandler? found_recv_packet_handler = null;
|
||||
|
||||
try
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(recvProtocol, () => $"recvProtocol is null !!! - {session.toBasicString()}");
|
||||
|
||||
Stopwatch? stopwatch = null;
|
||||
var event_tid = string.Empty;
|
||||
|
||||
var server_logic = ServerLogicApp.getServerLogicApp();
|
||||
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {session.toBasicString()}");
|
||||
|
||||
var config = server_logic.getServerConfig();
|
||||
NullReferenceCheckHelper.throwIfNull(config, () => $"config is null !!! - {session.toBasicString()}");
|
||||
|
||||
if (true == config.PerformanceCheckEnable)
|
||||
{
|
||||
event_tid = System.Guid.NewGuid().ToString("N");
|
||||
stopwatch = Stopwatch.StartNew();
|
||||
}
|
||||
|
||||
var receiver = getPacketReceiver();
|
||||
NullReferenceCheckHelper.throwIfNull(receiver, fnLog: () => $"receiver is null !!! - {session.toBasicString()}");
|
||||
|
||||
if (false == receiver.fillupProudNetPacketCommand(recvProtocol, out fillup_packet_command))
|
||||
{
|
||||
err_msg = $"Failed to PacketReceiver.fillupProudNetPacketCommand() !!! : {recvProtocol.ToString()} - {session.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.PacketRecvInvalid, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(fillup_packet_command, fnLog: () => $"fillup_packet_command is null !!! - {session.toBasicString()}");
|
||||
|
||||
found_recv_packet_handler = receiver.findRecvHandler(fillup_packet_command);
|
||||
if (null == found_recv_packet_handler)
|
||||
{
|
||||
err_msg = $"Not found Recv Packet Handler !!! : {recvProtocol.ToString()} - {session.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.RacketRecvHandlerNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await found_recv_packet_handler.onCheckValid(session, recvProtocol);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed to onCheckValid() !!! : {result.toBasicString()} - {fillup_packet_command.toBasicString()}");
|
||||
return result;
|
||||
}
|
||||
|
||||
result = await found_recv_packet_handler.onProcessPacket(session, recvProtocol);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().error($"Failed to onProcessPacket() !!! : {result.toBasicString()} - {fillup_packet_command.toBasicString()}");
|
||||
}
|
||||
|
||||
if (null != stopwatch)
|
||||
{
|
||||
var elapsed_msec = stopwatch.ElapsedMilliseconds;
|
||||
stopwatch.Stop();
|
||||
Log.getLogger().debug($"{GetType()} CSPacket Stopwatch Stop : ETID:{event_tid}, ElapsedMSec:{elapsed_msec} - {recvProtocol.toBasicString()}");
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
err_msg = $"Exception !!!, Failed to perform in SessionBase.onCallProtocolHandler() !!! : exception:{e} - PacketCommand:{fillup_packet_command?.toBasicString()}, {session?.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.TryCatchException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
if (null != found_recv_packet_handler && null != session)
|
||||
{
|
||||
await found_recv_packet_handler.onProcessPacketException(session, recvProtocol, result);
|
||||
}
|
||||
}
|
||||
catch(Exception innerException)
|
||||
{
|
||||
err_msg = $"InnerException !!!, Failed to perform in SessionBase.onCallProtocolHandler() !!! : exception:{innerException}";
|
||||
result.setFail(ServerErrorCode.TryCatchException, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> onCallLargeSizeProtocolHandler<T>(IEntityWithSession session, T recvProtocol)
|
||||
where T : Google.Protobuf.IMessage
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var network_session = m_large_packet_handler.getNetworkSession();
|
||||
NullReferenceCheckHelper.throwIfNull(network_session, () => $"network_session is null !!! - {session.toBasicString()}");
|
||||
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(session, fnLog: () => $"session is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(recvProtocol, fnLog: () => $"recvProtocol is null !!! - {session.toBasicString()}");
|
||||
|
||||
var recv_msg = recvProtocol as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, fnLog: () => $"recv_msg is null !!! - {session.toBasicString()}");
|
||||
|
||||
var request = recv_msg.Request.ReqLargePacket;
|
||||
NullReferenceCheckHelper.throwIfNull(request, fnLog: () => $"request is null !!! - {session.toBasicString()}");
|
||||
|
||||
string packet_uid = request.Uid;
|
||||
Int32 packet_index = request.PacketIndex;
|
||||
Int32 total_packet_count = request.TotalPacketCount;
|
||||
|
||||
m_large_packet_handler.collectPacket(session, packet_uid, total_packet_count, packet_index, request.Data);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
var error_coce = ServerErrorCode.TryCatchException;
|
||||
err_msg = $"Exception !!!, Failed to perform in onCallLargeSizeProtocolHandler() !!! : errorCode:{error_coce}, exception:{e} - PacketCommand:{recvProtocol?.toBasicString()}, {session?.toBasicString()}";
|
||||
result.setFail(error_coce, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
#region 패킷 송신용 함수들
|
||||
public bool onSendPacket<T>(IEntityWithSession session, T msg)
|
||||
where T : class, IMessage
|
||||
{
|
||||
return sendPacket<T>(session, msg, RmiContext.ReliableSend);
|
||||
}
|
||||
|
||||
public bool onSendPacket<T>(IEntityWithSession[] sessions, T msg)
|
||||
where T : class, IMessage
|
||||
{
|
||||
return sendPacket<T>(sessions, msg, ServerCore.ProudNetHelper.compressRmi());
|
||||
}
|
||||
|
||||
public bool onSendPacketWithSecure<T>(IEntityWithSession session, T msg)
|
||||
where T : class, IMessage
|
||||
{
|
||||
return sendPacket<T>(session, msg, RmiContext.SecureReliableSend);
|
||||
}
|
||||
|
||||
public bool onSendPacketWithSecure<T>(IEntityWithSession[] sessions, T msg)
|
||||
where T : class, IMessage
|
||||
{
|
||||
return sendPacket<T>(sessions, msg, RmiContext.SecureReliableSend);
|
||||
}
|
||||
|
||||
private bool sendPacket<T>(IEntityWithSession session, T msg, RmiContext rmiContext)
|
||||
where T : class, IMessage
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!!");
|
||||
|
||||
var host_id = session.getHostId();
|
||||
|
||||
var base_msg = msg as IMessage;
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(base_msg, () => $"base_msg is null !!! - {session.toBasicString()}");
|
||||
|
||||
var msg_size = base_msg.CalculateSize();
|
||||
|
||||
var to_send_msgs = checkSizeAndConvertMessage(msg, msg_size);
|
||||
foreach (var to_send_msg in to_send_msgs)
|
||||
{
|
||||
var send_msg = to_send_msg as IMessage;
|
||||
NullReferenceCheckHelper.throwIfNull(send_msg, () => $"send_msg is null !!! - {session.toBasicString()}");
|
||||
|
||||
var send_msg_size = send_msg.CalculateSize();
|
||||
|
||||
string send_message = send_msg.ToString() ?? string.Empty;
|
||||
var err_msg = $"{toTrySendString(host_id, send_message, send_msg_size)} - {session.toBasicString()}";
|
||||
Log.getLogger().debug(err_msg);
|
||||
|
||||
var is_success = FnSendPacketToHost?.Invoke(host_id, rmiContext, send_msg);
|
||||
if (false == is_success)
|
||||
{
|
||||
err_msg = $"{toFailedSendString(host_id, send_message, msg_size)} - {session.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool sendPacket<T>(IEntityWithSession[] sessions, T msg, RmiContext rmiContext)
|
||||
where T : class, IMessage
|
||||
{
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(sessions, () => $"sessions is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(rmiContext, () => $"rmiContext is null !!!");
|
||||
|
||||
var host_ids = new Nettention.Proud.HostID[sessions.Length];
|
||||
for(var i = 0; i < host_ids.Length; i++)
|
||||
{
|
||||
host_ids[i] = sessions[i].getHostId();
|
||||
}
|
||||
|
||||
var base_msg = msg as IMessage;
|
||||
NullReferenceCheckHelper.throwIfNull(base_msg, () => $"base_msg is null !!! - {toBasicString()}");
|
||||
|
||||
var msg_size = base_msg.CalculateSize();
|
||||
|
||||
var to_send_msgs = checkSizeAndConvertMessage(msg, msg_size);
|
||||
foreach (var to_send_msg in to_send_msgs)
|
||||
{
|
||||
var send_msg = to_send_msg as IMessage;
|
||||
NullReferenceCheckHelper.throwIfNull(send_msg, () => $"send_msg is null !!! - {toBasicString()}");
|
||||
|
||||
var send_msg_size = send_msg.CalculateSize();
|
||||
string send_message = send_msg.ToString() ?? string.Empty;
|
||||
var err_msg = $"{toTrySendStrings(host_ids, send_message, send_msg_size)}";
|
||||
Log.getLogger().debug(err_msg);
|
||||
|
||||
var is_success = FnSendPacketToHosts?.Invoke(host_ids, rmiContext, send_msg);
|
||||
if (false == is_success)
|
||||
{
|
||||
err_msg = $"{toFailedSendStrings(host_ids, send_message, msg_size)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<T> checkSizeAndConvertMessage<T>(T msg, int msg_size)
|
||||
where T : class, IMessage
|
||||
{
|
||||
var msgs = new List<T>();
|
||||
|
||||
if (false == Constant.IS_LARGE_PACKET_PROTOCOL_ACTIVE)
|
||||
{
|
||||
msgs.Add(msg);
|
||||
return msgs;
|
||||
}
|
||||
|
||||
if (msg_size > getLargePacketCheckSize())
|
||||
{
|
||||
var byte_string = msg.ToByteString();
|
||||
byte[] byteArray = byte_string.ToByteArray();
|
||||
|
||||
int chunkSize = getPacketChunkSize();
|
||||
int numberOfChunks = (int)Math.Ceiling((double)byteArray.Length / chunkSize);
|
||||
|
||||
var uid = KeyGeneration.GenerateRandomKey(20);
|
||||
var otp_encoding_by_base32 = Base32Encoding.ToString(uid);
|
||||
for (int i = 0; i < numberOfChunks; i++)
|
||||
{
|
||||
int startIndex = i * chunkSize;
|
||||
int length = Math.Min(chunkSize, byteArray.Length - startIndex);
|
||||
|
||||
byte[] chunk = new byte[length];
|
||||
Array.Copy(byteArray, startIndex, chunk, 0, length);
|
||||
|
||||
ByteString chunkByteString = ByteString.CopyFrom(chunk);
|
||||
|
||||
var cToG = new ClientToGame();
|
||||
cToG.Response = new();
|
||||
cToG.Response.AckLargePacket = new();
|
||||
|
||||
cToG.Response.AckLargePacket.PacketIndex = i;
|
||||
cToG.Response.AckLargePacket.Uid = otp_encoding_by_base32;
|
||||
cToG.Response.AckLargePacket.Data = chunkByteString;
|
||||
cToG.Response.AckLargePacket.TotalPacketCount = numberOfChunks;
|
||||
var chunk_msg = cToG as IMessage;
|
||||
|
||||
msgs.Add((T)chunk_msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msgs.Add(msg);
|
||||
}
|
||||
|
||||
return msgs;
|
||||
|
||||
}
|
||||
|
||||
protected bool onRecvP2PMotionSync(Nettention.Proud.HostID remote,Nettention.Proud.RmiContext rmiContext, System.String id, Nettention.Proud.ByteArray data)
|
||||
{
|
||||
|
||||
var session_id = remote.toSESSION_ID();
|
||||
var found_entity_with_session = onLookupEntityWithSession(session_id);
|
||||
if (found_entity_with_session == null)
|
||||
{
|
||||
//err_msg = $"Not found remoteSession !!! - sessionId:{session_id}, recvProtocolType:{recv_protocol_type}, HostID:{remote}";
|
||||
//Log.getLogger().warn(err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
PacketReceiver receiver = getPacketReceiver();
|
||||
NullReferenceCheckHelper.throwIfNull(receiver, fnLog: () => $"receiver is null !!! - {found_entity_with_session.toBasicString()}");
|
||||
var p2p_recv_handler = receiver.findP2PPacketHandler("");
|
||||
if (null == p2p_recv_handler)
|
||||
{
|
||||
var err_msg = $"Not found Recv Packet Handler !!! : {found_entity_with_session.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
p2p_recv_handler.onProcessP2PPacket(found_entity_with_session, data);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion 패킷 송신용 함수들
|
||||
|
||||
#region 로그용 문자열 함수들
|
||||
public abstract string toBasicString();
|
||||
|
||||
public virtual string toTrySendString(Nettention.Proud.HostID hostId, string msgType, Int32 length) => $"Packet Try Send2Net - TargetHostId:{hostId}, msgType:{msgType}, length:{length}";
|
||||
public virtual string toFailedSendString(Nettention.Proud.HostID hostId, string msgType, Int32 length) => $"Packet Failed !!! Send2Net - TargetHostId:{hostId}, msgType:{msgType}, length:{length}";
|
||||
|
||||
public virtual string toTrySendStrings(Nettention.Proud.HostID[] hostIds, string msgType, Int32 length) => $"Packet Try Send2Net - TargetHostIds:{hostIds}..., msgType:{msgType}, length:{length}";
|
||||
public virtual string toFailedSendStrings(Nettention.Proud.HostID[] hostIds, string msgType, Int32 length) => $"Packet Failed !!! Send2Net - TargetHostIds:{hostIds}..., msgType:{msgType}, length:{length}";
|
||||
|
||||
#endregion 로그용 문자열 함수들
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// 리슨 역할을 하는 세션 기반 클래스 이다. (서버 역할용)
|
||||
//
|
||||
// author : kangms
|
||||
//
|
||||
//=============================================================================================
|
||||
public abstract partial class ListenSessionBase : SessionBase
|
||||
{
|
||||
private readonly string m_server_type = string.Empty;
|
||||
|
||||
private NetworkAddress m_listen_address = new();
|
||||
|
||||
private LargePacketHandler m_large_packet_handler = new();
|
||||
|
||||
// SESSION_ID 는 Pround.HostID 와 같다 !!!
|
||||
private readonly ConcurrentDictionary<SESSION_ID, IEntityWithSession> m_entity_with_sessions = new();
|
||||
|
||||
|
||||
public ListenSessionBase(IRmiHost netForServer, string serverType)
|
||||
: base(netForServer)
|
||||
{
|
||||
m_server_type = serverType;
|
||||
}
|
||||
|
||||
protected override bool onBindRmiHostHandler(IRmiHost currRmiHost)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var rmi_host_for_server = currRmiHost as NetServer;
|
||||
if(null == rmi_host_for_server)
|
||||
{
|
||||
err_msg = $"Invalid Param !!!, NetServer is null - {toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
rmi_host_for_server.ClientJoinHandler = onConnectedClient;
|
||||
rmi_host_for_server.ClientLeaveHandler = onDisconnectedClient;
|
||||
|
||||
rmi_host_for_server.ErrorHandler = onError;
|
||||
rmi_host_for_server.WarningHandler = onWarning;
|
||||
rmi_host_for_server.InformationHandler = onInformation;
|
||||
rmi_host_for_server.ExceptionHandler = onException;
|
||||
rmi_host_for_server.NoRmiProcessedHandler = onNoRmiProcessed;
|
||||
rmi_host_for_server.ClientHackSuspectedHandler = onClientHackSuspected;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void onConnectedClient(NetClientInfo clientInfo)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var new_entity_with_session = await onNewEntityWithSession(clientInfo);
|
||||
if(null == new_entity_with_session)
|
||||
{
|
||||
err_msg = $"Failed to create New EnityWithSession - {toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if(false == m_entity_with_sessions.TryAdd(clientInfo.getSessionId(), new_entity_with_session))
|
||||
{
|
||||
err_msg = $"Already registered EnityWithSession !!! : {new_entity_with_session.toBasicString()} - {toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
new_entity_with_session.setListenSessionBase(this);
|
||||
|
||||
NamedPipeMonitor.SetCurrentClientConnection(m_entity_with_sessions.Count, getServerType().toServerType());
|
||||
|
||||
var initializer = new_entity_with_session as IInitializer;
|
||||
if(null != initializer)
|
||||
{
|
||||
var result = await initializer.onInit();
|
||||
if(result.isFail())
|
||||
{
|
||||
Log.getLogger().fatal(result.toBasicString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var hostId = clientInfo.hostID;
|
||||
err_msg = $"Client connected, in onConnectedClient() : hostPublicIP:{clientInfo.tcpAddrFromServer.IPToString()}, HostId:{hostId}, {new_entity_with_session.toBasicString()} - {toBasicString()}";
|
||||
Log.getLogger().debug(err_msg);
|
||||
}
|
||||
|
||||
private async void onDisconnectedClient(NetClientInfo clientInfo, ErrorInfo errorinfo, ByteArray comment)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (clientInfo == null || errorinfo == null)
|
||||
{
|
||||
string clientInfo_log = clientInfo == null ? "Null" : "Not Null";
|
||||
string errorInfo_log = errorinfo == null ? "Null" : "Not Null";
|
||||
|
||||
err_msg = $"onDisconnectedClient clientInfo is null !!! clientInfo : {clientInfo_log}, errorinfo : {errorInfo_log}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var hostId = clientInfo.hostID;
|
||||
var errInfo = errorinfo.GetString();
|
||||
var comm = comment == null ? string.Empty : Encoding.Default.GetString(comment.data);
|
||||
|
||||
err_msg = $"Client Disconnected, in onDisconnectedClient() : hostPublicIP:{clientInfo.tcpAddrFromServer.IPToString()}, HostId:{hostId}, ErrorInfo:{errInfo}, comment:{comm} - {toBasicString()}";
|
||||
Log.getLogger().debug(err_msg);
|
||||
|
||||
if (false == m_entity_with_sessions.TryGetValue(clientInfo.getSessionId(), out var found_entity_with_session))
|
||||
{
|
||||
NamedPipeMonitor.SetCurrentClientConnection(m_entity_with_sessions.Count, getServerType().toServerType());
|
||||
err_msg = $"Not found EnityWithSession !!! : toDisconnectSessionId:{clientInfo.getSessionId()} - {toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if(false == m_entity_with_sessions.TryRemove(clientInfo.getSessionId(), out _))
|
||||
{
|
||||
NamedPipeMonitor.SetCurrentClientConnection(m_entity_with_sessions.Count, getServerType().toServerType());
|
||||
err_msg = $"Failed to remove EnityWithSession !!! : {found_entity_with_session.toBasicString()} - {toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
NamedPipeMonitor.SetCurrentClientConnection(m_entity_with_sessions.Count, getServerType().toServerType());
|
||||
|
||||
await onDisconnectedEntityWithSession(found_entity_with_session);
|
||||
}
|
||||
|
||||
public bool disconnectClient(SESSION_ID sessionId)
|
||||
{
|
||||
var rmi_host_for_server = getRmiHost() as NetServer;
|
||||
if (rmi_host_for_server == null)
|
||||
return false;
|
||||
|
||||
return rmi_host_for_server.CloseConnection(sessionId.toHostID());
|
||||
}
|
||||
|
||||
private void onError(ErrorInfo errorInfo)
|
||||
{
|
||||
var err_msg = errorInfo == null ? string.Empty : errorInfo.GetString() ?? string.Empty;
|
||||
Log.getLogger().error($"ProudNet Error !!!, called onError() : errMsg:{err_msg} - {toBasicString()}");
|
||||
}
|
||||
|
||||
private void onWarning(ErrorInfo errorInfo)
|
||||
{
|
||||
var err_msg = errorInfo == null ? string.Empty : errorInfo.GetString() ?? string.Empty;
|
||||
Log.getLogger().warn($"ProudNet Warning !!!, called onWarning() : errMsg:{err_msg} - {toBasicString()}");
|
||||
}
|
||||
|
||||
private void onInformation(ErrorInfo errorInfo)
|
||||
{
|
||||
var err_msg = errorInfo == null ? string.Empty : errorInfo.GetString() ?? string.Empty;
|
||||
Log.getLogger().info($"ProudNet Information !!!, called onInformation() : errMsg:{err_msg} - {toBasicString()}");
|
||||
}
|
||||
|
||||
private void onException(Exception e)
|
||||
{
|
||||
Log.getLogger().error($"ProudNet Exception !!!, called onException() : errMsg:{e} - {toBasicString()}");
|
||||
}
|
||||
|
||||
private void onNoRmiProcessed(RmiID rmiID)
|
||||
{
|
||||
Log.getLogger().warn($"ProudNet NoRmiProcessed !!!, called onNoRmiProcessed() : RmiId:{rmiID} - {toBasicString()}");
|
||||
}
|
||||
|
||||
private void onClientHackSuspected(Nettention.Proud.HostID clientID, HackType hackType)
|
||||
{
|
||||
Log.getLogger().error($"ProudNet Client Hack Suspencted !!!, called onClientHackSuspected() : HostId:{clientID}), HackType:{hackType} - {toBasicString()}");
|
||||
}
|
||||
|
||||
public override IEntityWithSession? onLookupEntityWithSession(SESSION_ID sessionId)
|
||||
{
|
||||
m_entity_with_sessions.TryGetValue(sessionId, out var found_entity_with_session);
|
||||
return found_entity_with_session;
|
||||
}
|
||||
|
||||
#region 로그용 문자열 함수들
|
||||
public override string toBasicString() => $"NetServerInfo: ServerType:{getServerType()}";
|
||||
#endregion 로그용 문자열 함수들
|
||||
|
||||
#region 재정의 해야 하는 함수들
|
||||
protected abstract Task<IEntityWithSession?> onNewEntityWithSession(NetClientInfo clientInfo);
|
||||
|
||||
protected abstract Task onDisconnectedEntityWithSession(IEntityWithSession disconnectedEntity);
|
||||
|
||||
public abstract int getMaxConnectionCount();
|
||||
#endregion 재정의 해야 하는 함수들
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================================
|
||||
// 서버로 연결할 세션 기반 클래스 이다. (클라이언트 역할용)
|
||||
//
|
||||
// author : kangms
|
||||
//
|
||||
//===========================================================================================
|
||||
public abstract partial class ConnectToServerSessionBase : SessionBase
|
||||
{
|
||||
private string m_to_connect_server_type = string.Empty;
|
||||
|
||||
// 연결할 호스트 정보
|
||||
private string m_host_ip = string.Empty;
|
||||
private UInt16 m_host_port;
|
||||
private string m_host_address = string.Empty;
|
||||
|
||||
public ConnectToServerSessionBase(IRmiHost netForClient)
|
||||
: base(netForClient)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override bool onBindRmiHostHandler(IRmiHost currRmiHost)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var rmi_host_for_client = currRmiHost as NetClient;
|
||||
if (null == rmi_host_for_client)
|
||||
{
|
||||
err_msg = $"Invalid Param !!!, NetClient is null - {toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region 로그용 문자열 함수들
|
||||
public override string toBasicString() => $"NetClientInfo: TargetServerType:{getToConnectServerType()}, TargetAddress:{getHostAddress()}";
|
||||
#endregion 로그용 문자열 함수들
|
||||
}
|
||||
Reference in New Issue
Block a user