feat : 토큰 -> 해시키 생성 로직 구조 변경 / 토큰 관리 로직 추가
This commit is contained in:
@@ -85,7 +85,11 @@ public class GameServer : ServerBase
|
|||||||
{
|
{
|
||||||
AccTokenPacket accTokenPacket = Serializer.Deserialize<AccTokenPacket>(new ReadOnlyMemory<byte>(payload));
|
AccTokenPacket accTokenPacket = Serializer.Deserialize<AccTokenPacket>(new ReadOnlyMemory<byte>(payload));
|
||||||
string token = accTokenPacket.Token;
|
string token = accTokenPacket.Token;
|
||||||
long hashKey = UuidGeneratorManager.Instance.GetOrCreate(token);
|
tokenHash.TryGetValue(token, out long hashKey);
|
||||||
|
if (hashKey <= 1000)
|
||||||
|
{
|
||||||
|
hashKey = UuidGeneratorManager.Instance.Create();
|
||||||
|
}
|
||||||
|
|
||||||
if (sessions.TryGetValue(hashKey, out NetPeer? existing))
|
if (sessions.TryGetValue(hashKey, out NetPeer? existing))
|
||||||
{
|
{
|
||||||
@@ -102,6 +106,7 @@ public class GameServer : ServerBase
|
|||||||
if (username == null)
|
if (username == null)
|
||||||
{
|
{
|
||||||
Log.Warning("[Server] 토큰 검증 실패 - 연결 거부 PeerId={Id}", peer.Id);
|
Log.Warning("[Server] 토큰 검증 실패 - 연결 거부 PeerId={Id}", peer.Id);
|
||||||
|
UuidGeneratorManager.Instance.Release(hashKey);
|
||||||
peer.Disconnect();
|
peer.Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,17 +115,11 @@ public class GameServer : ServerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
peer.Tag = new Session(hashKey, peer);
|
peer.Tag = new Session(hashKey, peer);
|
||||||
|
((Session)peer.Tag).Token = token;
|
||||||
sessions[hashKey] = peer;
|
sessions[hashKey] = peer;
|
||||||
|
tokenHash[token] = hashKey;
|
||||||
pendingPeers.Remove(peer.Id);
|
pendingPeers.Remove(peer.Id);
|
||||||
|
|
||||||
if (hashKey <= 1000)
|
|
||||||
{
|
|
||||||
// 더미 클라이언트면 에러
|
|
||||||
Log.Error("[Server] Dummy 클라이언트가 입니다. 연결을 종료합니다. HashKey={Key} PeerId={Id}", hashKey, peer.Id);
|
|
||||||
peer.Disconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Information("[Server] 인증 완료 HashKey={Key} PeerId={Id}", hashKey, peer.Id);
|
Log.Information("[Server] 인증 완료 HashKey={Key} PeerId={Id}", hashKey, peer.Id);
|
||||||
OnSessionConnected(peer, hashKey);
|
OnSessionConnected(peer, hashKey);
|
||||||
}
|
}
|
||||||
@@ -152,6 +151,7 @@ public class GameServer : ServerBase
|
|||||||
{
|
{
|
||||||
Log.Information("[GameServer] 세션 해제 HashKey={Key} Reason={Reason}", hashKey, info.Reason);
|
Log.Information("[GameServer] 세션 해제 HashKey={Key} Reason={Reason}", hashKey, info.Reason);
|
||||||
}
|
}
|
||||||
|
UuidGeneratorManager.Instance.Release(hashKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void HandlePacket(NetPeer peer, long hashKey, ushort type, byte[] payload)
|
protected override void HandlePacket(NetPeer peer, long hashKey, ushort type, byte[] payload)
|
||||||
|
|||||||
@@ -1,21 +1,35 @@
|
|||||||
using System.Collections.Concurrent;
|
|
||||||
|
|
||||||
namespace MMOserver.Utils;
|
namespace MMOserver.Utils;
|
||||||
|
|
||||||
public class UuidGeneratorManager : Singleton<UuidGeneratorManager>
|
public class UuidGeneratorManager : Singleton<UuidGeneratorManager>
|
||||||
{
|
{
|
||||||
private long counter = 0;
|
// 0 ~ 1000 은 더미 클라이언트 예약 범위
|
||||||
private readonly ConcurrentDictionary<string, long> tokenMap = new();
|
private const long DUMMY_RANGE_MAX = 1000;
|
||||||
|
|
||||||
// string token → 고유 long ID 변환 (멀티스레드 안전)
|
private readonly object idLock = new();
|
||||||
// 동일 token은 항상 같은 ID 반환
|
private readonly HashSet<long> usedIds = new();
|
||||||
public long GetOrCreate(string token)
|
|
||||||
|
// 고유 랜덤 long ID 발급 (1001번 이상, 충돌 시 재생성)
|
||||||
|
public long Create()
|
||||||
{
|
{
|
||||||
return tokenMap.GetOrAdd(token, _ => Interlocked.Increment(ref counter));
|
lock (idLock)
|
||||||
|
{
|
||||||
|
long id;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
id = Random.Shared.NextInt64(DUMMY_RANGE_MAX + 1, long.MaxValue);
|
||||||
|
} while (usedIds.Contains(id));
|
||||||
|
|
||||||
|
usedIds.Add(id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGet(string token, out long id)
|
// 로그아웃 / 세션 만료 시 ID 반납
|
||||||
|
public bool Release(long id)
|
||||||
{
|
{
|
||||||
return tokenMap.TryGetValue(token, out id);
|
lock (idLock)
|
||||||
|
{
|
||||||
|
return usedIds.Remove(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public abstract class ServerBase : INetEventListener
|
|||||||
// peer → hashKey 역방향은 peer.Tag as Session 으로 대체
|
// peer → hashKey 역방향은 peer.Tag as Session 으로 대체
|
||||||
protected readonly Dictionary<long, NetPeer> sessions = new();
|
protected readonly Dictionary<long, NetPeer> sessions = new();
|
||||||
|
|
||||||
|
// Token / HashKey 관리
|
||||||
|
protected readonly Dictionary<string, long> tokenHash = new();
|
||||||
|
|
||||||
// 재사용 NetDataWriter (단일 스레드 폴링이므로 안전)
|
// 재사용 NetDataWriter (단일 스레드 폴링이므로 안전)
|
||||||
private readonly NetDataWriter cachedWriter = new();
|
private readonly NetDataWriter cachedWriter = new();
|
||||||
|
|
||||||
@@ -123,6 +126,12 @@ public abstract class ServerBase : INetEventListener
|
|||||||
// (재연결로 이미 교체된 경우엔 건드리지 않음)
|
// (재연결로 이미 교체된 경우엔 건드리지 않음)
|
||||||
if (sessions.TryGetValue(session.HashKey, out NetPeer? current) && current.Id == peer.Id)
|
if (sessions.TryGetValue(session.HashKey, out NetPeer? current) && current.Id == peer.Id)
|
||||||
{
|
{
|
||||||
|
// 더미 클라 아니면 token관리
|
||||||
|
if (!string.IsNullOrEmpty(session.Token))
|
||||||
|
{
|
||||||
|
tokenHash.Remove(session.Token);
|
||||||
|
}
|
||||||
|
|
||||||
sessions.Remove(session.HashKey);
|
sessions.Remove(session.HashKey);
|
||||||
Log.Information("[Server] 세션 해제 HashKey={Key} Reason={Reason}", session.HashKey, disconnectInfo.Reason);
|
Log.Information("[Server] 세션 해제 HashKey={Key} Reason={Reason}", session.HashKey, disconnectInfo.Reason);
|
||||||
OnSessionDisconnected(peer, session.HashKey, disconnectInfo);
|
OnSessionDisconnected(peer, session.HashKey, disconnectInfo);
|
||||||
|
|||||||
@@ -4,12 +4,28 @@ namespace ServerLib.Service;
|
|||||||
|
|
||||||
public class Session
|
public class Session
|
||||||
{
|
{
|
||||||
public long HashKey { get; init; }
|
public string? Token
|
||||||
public NetPeer Peer { get; set; }
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long HashKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetPeer Peer
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public Session(long hashKey, NetPeer peer)
|
public Session(long hashKey, NetPeer peer)
|
||||||
{
|
{
|
||||||
HashKey = hashKey;
|
HashKey = hashKey;
|
||||||
Peer = peer;
|
Peer = peer;
|
||||||
|
Token = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user