Files
Client/Server/RylServerProject/RylAuthServer/AuthAgentDispatch.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

856 lines
28 KiB
C++

#include "stdafx.h"
#include <Network/Session/Session.h>
#include <Network/Winsock/SocketFactory.h>
#include <Network/Dispatch/ServerRequest.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Packet/PacketStruct/UnifiedCharPacket.h>
#include <Network/Packet/PacketStruct/AuthServerToDBAgentServer.h>
#include <Network/Packet/PacketStruct/PartyPacket.h>
#include <Network/Packet/PacketStruct/GuildPacket.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Utility/Setup/ServerSetup.h>
#include <Creature/Character/CharacterCreate.h>
#include <Item/ItemStructure.h>
#include <Item/ItemConstants.h>
#include <Item/ItemFactory.h>
#include <Item/Item.h>
#include <Log/ServerLog.h>
#include <Log/CharacterLog.h>
#include <Log/LogCommands.h>
#include "AuthAgentDispatch.h"
#include "AuthClientDispatch.h"
#include "AuthAgentServerTable.h"
#include "ItemCreator.h"
#include "SendUserLoginout.h"
// forward decl.
bool SendPartyLeaveToDBAgent(CSendStream& SendStream, unsigned long dwPID, unsigned long dwCID, const char* szName);
bool SendGuildLeaveToDBAgent(CSendStream& SendStream, unsigned long dwGID, unsigned long dwCID, const char* szName);
CAuthAgentDispatch::CAuthAgentDispatch(CSession& Session)
: CRylServerDispatch(Session, 1000)
{
}
CAuthAgentDispatch::~CAuthAgentDispatch()
{
DETLOG1(g_Log, "DP:0x%p/Destroy AuthAgentDispatch", this);
}
CSingleDispatch& CAuthAgentDispatch::GetDispatchTable()
{
static CSingleDispatch singleDispatchTable;
return singleDispatchTable;
}
void CAuthAgentDispatch::Connected()
{
// 연결 성공시에 호출한다(Connected 오버라이딩)
SendSysServerLogin(CServerSetup::GetInstance().GetServerID());
GetDispatchTable().SetDispatch(this);
DETLOG2(g_Log, "SS:0x%p/DP:0x%p/Connected CAuthAgentDispatch", &GetSession(), this);
}
void CAuthAgentDispatch::Disconnected()
{
GetDispatchTable().RemoveDispatch(this);
DETLOG2(g_Log, "SS:0x%p/DP:0x%p/Disconnected CAuthAgentDispatch", &GetSession(), this);
}
bool CAuthAgentDispatch::DispatchPacket(PktBase* lpPktBase)
{
// DBAgent에서 보낸 패킷을 처리하는 루틴이다.
switch (lpPktBase->GetCmd())
{
case CmdSysServerLogin: return ParseSysServerLogin(static_cast<PktSLAck*>(lpPktBase));
case CmdSysServerVerUpdate: return ParseSysServerVerUpdate(static_cast<PktSVU*>(lpPktBase));
case CmdSysChannelUpdate: return ParseSysChannelUpdate(static_cast<PktSCInfo*>(lpPktBase));
case CmdDBGetData: return ParseDBGetData(static_cast<PktDD*>(lpPktBase));
case CmdAgentZone: return ParseAgentZone(static_cast<PktDD*>(lpPktBase));
case CmdUserKill: return ParseUserKill(static_cast<PktUK*>(lpPktBase));
case CmdBillingTimeoutNotify: return ParseBillingTimeoutNotify(static_cast<PktBTN*>(lpPktBase));
case CmdBillingTimeCheckNotify: return ParseBillingTimeCheckNotify(static_cast<PktBTN*>(lpPktBase));
case CmdUnifiedCharInfo: return ParseUnifiedCharInfo(static_cast<PktUnifiedCharInfo*>(lpPktBase));
case CmdUnifiedCharSelect: return ParseUnifiedCharSelectAck(static_cast<PktUnifiedCharSelectAck*>(lpPktBase));
// 보통은 오지않지만 행여나 에러값이 올지도 모른다.
case CmdGuildCmd: return true;
default:
LogErrorPacket("Invalid packet command(AuthAgentDispatch can't process this packet)",
lpPktBase->GetCmd());
break;
}
// 잘못된 패킷이 오더라도 접속은 끊지 않는다.
return true;
}
bool CAuthAgentDispatch::ParseSysServerLogin(PktSLAck* lpPktSLAck)
{
// 아이템 시리얼 초기화
CItemCreator::GetInstance().SetUID(lpPktSLAck->m_dlItemUID);
// 서버 정보 등록.
RylServerInfo ServerInfo;
ServerInfo.m_dwClientVer = lpPktSLAck->m_dwClientVer;
ServerInfo.m_dwChecksum = lpPktSLAck->m_dwCheckSum;
strncpy(ServerInfo.m_szPatchAddress, lpPktSLAck->m_PatchAddress,
RylServerInfo::PATCH_ADDRESS_LENGTH - 1);
ServerInfo.m_szPatchAddress[RylServerInfo::PATCH_ADDRESS_LENGTH - 1] = '\0';
ServerInfo.m_nPatchAddressLen = strlen(ServerInfo.m_szPatchAddress);
// 서버군 등록.
CAuthAgentServerTable::GetInstance().SetAgentServerInfo(ServerInfo);
return true;
}
bool CAuthAgentDispatch::ParseSysChannelUpdate(PktSCInfo* lpPktSCInfo)
{
CAuthAgentServerTable::GetInstance().UpdateChannelUserNum(
lpPktSCInfo->m_usChannelClientNum, lpPktSCInfo->m_cChannelNum);
return true;
}
bool CAuthAgentDispatch::ParseSysServerVerUpdate(PktSVU* lpPktSVU)
{
CAuthAgentServerTable::GetInstance().UpdateServerData(lpPktSVU->m_dwCheckSum,
lpPktSVU->m_dwClientVer, lpPktSVU->m_PatchAddress);
return true;
}
bool CAuthAgentDispatch::ParseDBGetData(PktDD* lpPktDD)
{
// WORK_LIST 2.3 계정 국적 변경 기능 구현
bool bRemoveRequestKey = true;
if ( PktDD::SCmdNationChangeResult == lpPktDD->m_wCmd )
{
bRemoveRequestKey = false;
}
CServerRequest::Result result(lpPktDD->m_dwRequestKey, bRemoveRequestKey);
CAuthClientDispatch* lpAuthClientDispatch =
static_cast<CAuthClientDispatch*>(result.GetDispatch());
if (0 == lpAuthClientDispatch)
{
ERRLOG2(g_Log, "sCmd:0x%02x/RequestKey:%d/DBRequest Failed.",
lpPktDD->m_wCmd, lpPktDD->m_dwRequestKey);
return true;
}
CSession* lpSession = result.GetSession();
if (0 == lpSession)
{
ERRLOG2(g_Log, "sCmd:0x%02x/RequestKey:%d/Get Session Failed.",
lpPktDD->m_wCmd, lpPktDD->m_dwRequestKey);
return true;
}
DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/sCmd:0x%02x/RequestKey:%d/DBRequest Success.",
&lpAuthClientDispatch->GetSession(), lpAuthClientDispatch,
lpAuthClientDispatch->GetRemoteAddr().get_addr_string(),
lpPktDD->m_wCmd, lpPktDD->m_dwRequestKey);
switch(lpPktDD->m_wCmd)
{
case PktDD::SCmdStartSession: // 인증과정 (세션 오픈후 시작)
{
PktSSD* lpPktSSD = static_cast<PktSSD*>(lpPktDD);
unsigned long UserID = lpPktSSD->m_dwUserID;
unsigned long SessionID = lpPktSSD->m_dwSessionID;
unsigned short wError = lpPktSSD->GetError();
unsigned char cAgentServerType = lpPktSSD->m_cAgentServerType; // 중계서버 타입 (Part1:0 / Part1Unified:1 / Part2:2 / Part2Unified:3 / Part2Selectable:4
unsigned char cFirstLogin = lpPktSSD->m_cFirstLogin; // 최초 로그인 여부 (최초 로그인:0 / 여러번 로그인:1)
// 유저 로그인(세션 열림)
if (wError == 0)
{
lpAuthClientDispatch->UserLogin(SessionID, UserID);
if (lpAuthClientDispatch->GetSession().CalledDisconnected())
{
// 이미 연결이 끊어져서, Disconnected를 호출했으면
// 유저를 로그아웃시킴.
lpAuthClientDispatch->UserLogout();
}
else
{
// 통합서버 정보 저장
lpAuthClientDispatch->SetUnifiedInfo(cAgentServerType, cFirstLogin);
// 앞으로 오는 인증 패킷은 무시.
lpAuthClientDispatch->SetPacketProcessFlag(CAuthClientDispatch::AUTHORIZED_SUCCESS);
}
}
if (!AuthSendPacket::SendAuthAccount(lpAuthClientDispatch, UserID, wError))
{
// 다시 인증 패킷을 받을 수 있음.
lpAuthClientDispatch->ResetPacketProcessFlag(CAuthClientDispatch::AUTHORIZED_SUCCESS);
}
break;
}
case PktDD::SCmdUserLogin:
{
PktULDAck* lpULDAck = static_cast<PktULDAck*>(lpPktDD);
unsigned long UserID = lpULDAck->m_dwUserID;
CHAR_VIEW* lpCharView = lpULDAck->m_CharView;
sGuildData* lpGuildData = lpULDAck->m_GuildData;
int nPlayTime = lpULDAck->m_nPlayTime; // BillingType이 정액인 경우는 남은 날짜. 정량인 경우는 남은 시간(분)
unsigned short AdminLevel = lpULDAck->m_usAdminLevel;
unsigned char cBillingType = lpULDAck->m_cBillingType; // D : 정액 T : 정량 0혹은N : 무료
unsigned char cBillingUser = lpULDAck->m_cBillingUser; // 0 : 개인 1 : 피시방
unsigned char cLoginType = lpULDAck->m_cLoginType;
unsigned long dwFlag = lpULDAck->m_sStoreInfo.Flag;
// WORK_LIST 2.1 계정 국적 추가
unsigned char cAccountNation = lpULDAck->m_cAccountNation; // 계정 국적
lpAuthClientDispatch->SetCharacterView(lpCharView);
// Store Info 정보 //
STORE_INFO* pStoreInfo = lpAuthClientDispatch->GetStoreInfo();
memset(pStoreInfo, 0, sizeof(STORE_INFO));
memcpy(pStoreInfo, &lpULDAck->m_sStoreInfo, sizeof(STORE_INFO));
// WORK_LIST 2.1 계정 국적 추가
AuthSendPacket::SendUserLogin(lpAuthClientDispatch->GetSendStream(), lpAuthClientDispatch->GetSessionID(),
UserID, lpCharView, lpGuildData, dwFlag, cAccountNation, nPlayTime, AdminLevel, cBillingType,
cBillingUser, cLoginType, lpULDAck->GetError());
break;
}
// WORK_LIST 2.1 계정 국적 추가
case PktDD::SCmdSelectNation:
{
PktSAND* lpPktSAND = static_cast<PktSAND*>(lpPktDD);
CAuthClientDispatch::SendSelectAccountNation(lpAuthClientDispatch->GetSendStream(), lpPktSAND->m_dwUserID,
lpPktSAND->m_cType, lpPktSAND->m_cAccountNation, lpPktSAND->GetError());
break;
}
// WORK_LIST 2.3 계정 국적 변경 기능 구현
case PktDD::SCmdNationChangeResult:
{
PktANCAck* lpPktANCAck = static_cast<PktANCAck*>(lpPktDD);
CAuthClientDispatch::SendNationChangeResult(lpAuthClientDispatch->GetSendStream(), lpPktANCAck->m_dwUserID,
lpPktANCAck->m_dwGID, lpPktANCAck->m_dwFame, 0);
break;
}
case PktDD::SCmdCharCreate:
{
PktCCDAck* lpPktCCDAck = static_cast<PktCCDAck*>(lpPktDD);
CAuthClientDispatch::SendCharCreate(lpAuthClientDispatch->GetSendStream(), lpPktCCDAck->m_dwCharID,
lpPktCCDAck->m_dwSlot, &lpPktCCDAck->m_CharView, lpPktCCDAck->GetError());
if (0 == lpPktCCDAck->GetError())
{
SendCreateCharEquipItem(lpPktCCDAck->m_dwCharID,
lpPktCCDAck->m_CharView.Equip[Item::EquipmentPos::SHIRT],
lpPktCCDAck->m_CharView.Equip[Item::EquipmentPos::ARMOUR],
lpPktCCDAck->m_CharView.Equip[Item::EquipmentPos::BOOTS],
lpPktCCDAck->m_CharView.Equip[Item::EquipmentPos::WEAPON_HAND1]);
}
lpAuthClientDispatch->ResetPacketProcessFlag(CAuthClientDispatch::PENDED_CHAR_CREATE);
GAMELOG::LogCharCreateDelete(lpAuthClientDispatch->GetUID(),
&lpSession->GetRemoteAddr().get_addr_in(),
lpPktCCDAck->m_dwCharID, GAMELOG::CMD::CHAR_CREATE, lpPktCCDAck->GetError());
break;
}
case PktDD::SCmdCharDelete:
{
PktCDD* lpPktCDD = static_cast<PktCDD*>(lpPktDD);
GET_SINGLE_DISPATCH(lpAuthAgentDispatch, CAuthAgentDispatch,
CAuthAgentDispatch::GetDispatchTable());
// 에러가 없을때 파티, 길드에서 삭제
if(!lpPktCDD->GetError())
{
CHAR_VIEW& CurrentCharView = lpAuthClientDispatch->GetCharacterView(lpPktCDD->m_dwSlotNum);
if(lpAuthAgentDispatch)
{
if(CurrentCharView.PID)
{
// 파티 멤버일 경우 파티에서 탈퇴
SendPartyLeaveToDBAgent(lpAuthAgentDispatch->GetSendStream(),
CurrentCharView.PID, lpPktCDD->m_dwCharID, CurrentCharView.Name);
}
if(CurrentCharView.GID)
{
// 길드 멤버일 경우 길드에서 탈퇴
SendGuildLeaveToDBAgent(lpAuthAgentDispatch->GetSendStream(),
CurrentCharView.GID, lpPktCDD->m_dwCharID, CurrentCharView.Name);
}
}
}
CAuthClientDispatch::SendCharDelete(lpAuthClientDispatch->GetSendStream(), lpPktCDD->m_dwUserID,
lpPktCDD->m_dwSlotNum, lpPktCDD->GetError());
lpAuthClientDispatch->ResetPacketProcessFlag(CAuthClientDispatch::PENDED_CHAR_DELETE);
GAMELOG::LogCharCreateDelete(lpAuthClientDispatch->GetUID(),
&lpSession->GetRemoteAddr().get_addr_in(), lpPktCDD->m_dwCharID, GAMELOG::CMD::CHAR_DELETE, lpPktCDD->GetError());
break;
}
case PktDD::SCmdCharSelect:
{
PktCSDAck* lpPktCSDAck = static_cast<PktCSDAck*>(lpPktDD);
lpAuthClientDispatch->ResetPacketProcessFlag(
CAuthClientDispatch::PENDED_CHAR_SELECT);
unsigned long dwChannelCount = std::accumulate(lpPktCSDAck->m_wChannelNum,
lpPktCSDAck->m_wChannelNum + PktCSDAck::MAX_CHANNEL_NUM, 0);
if (0 == lpPktCSDAck->GetError() && 0 < dwChannelCount)
{
lpAuthClientDispatch->SetPacketProcessFlag(
CAuthClientDispatch::CHAR_SELECT_SUCCESS);
}
if (!CAuthClientDispatch::SendCharSelect(lpAuthClientDispatch->GetSendStream(), lpPktCSDAck->m_cZone,
lpPktCSDAck->m_wChannelNum, lpPktCSDAck->GetError()))
{
lpAuthClientDispatch->ResetPacketProcessFlag(
CAuthClientDispatch::CHAR_SELECT_SUCCESS);
}
break;
}
default:
{
ERRLOG2(g_Log, "DB로부터 이상한 패킷이 들어왔습니다. 커맨드는 %x, 유저 세션 포인터는 0x%p 입니다.",
lpPktDD->GetCmd(), lpSession);
break;
}
}
return true;
}
bool SendPartyLeaveToDBAgent(CSendStream& SendStream, unsigned long dwPID,
unsigned long dwCID, const char* szName)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktPMD));
if (0 != lpBuffer)
{
PktPMD* lpPktPMD = reinterpret_cast<PktPMD *>(lpBuffer);
lpPktPMD->InitPtSubCmd(0, PktCCD::SCmdDeletePartyMem);
lpPktPMD->m_dwPartyID = dwPID;
lpPktPMD->m_dwSenderID = dwCID;
lpPktPMD->m_dwGID = dwCID;
if(0 != szName)
{
strncpy(lpPktPMD->m_strSenderName, szName, CHAR_INFOST::MAX_NAME_LEN);
}
else
{
memset(lpPktPMD->m_strSenderName, 0, CHAR_INFOST::MAX_NAME_LEN);
}
return SendStream.WrapHeader(sizeof(PktPMD), CmdAgentParty, 0, 0);
}
return false;
}
bool CAuthAgentDispatch::ParseAgentZone(PktDD* lpPktDD)
{
CServerRequest::Result result(lpPktDD->m_dwRequestKey);
CAuthClientDispatch* lpAuthClientDispatch =
static_cast<CAuthClientDispatch*>(result.GetDispatch());
if (0 == lpAuthClientDispatch)
{
ERRLOG2(g_Log, "sCmd:0x%02x/RequestKey:%d/DBRequest Failed.",
lpPktDD->m_wCmd, lpPktDD->m_dwRequestKey);
return true;
}
CSession* lpSession = result.GetSession();
if (0 == lpSession)
{
ERRLOG2(g_Log, "sCmd:0x%02x/RequestKey:%d/Get Session Failed.",
lpPktDD->m_wCmd, lpPktDD->m_dwRequestKey);
return true;
}
DETLOG4(g_Log, "SS:0x%p/DP:0x%p/sCmd:0x%02x/RequestKey:%d/DBRequest Success.",
&lpAuthClientDispatch->GetSession(), lpAuthClientDispatch,
lpPktDD->m_wCmd, lpPktDD->m_dwRequestKey);
switch(lpPktDD->m_wCmd)
{
case PktDD::SCmdServerZone:
{
PktSAAck* lpPktSAAck = static_cast<PktSAAck*>(lpPktDD);
lpAuthClientDispatch->ResetPacketProcessFlag(
CAuthClientDispatch::PENDED_SERVER_ZONE);
if (0 == lpPktSAAck->GetError())
{
// 유저 로그 아웃 처리
// (... 클라이언트가 와서 붙는 것보다 이게 늦게 가면 대략 낭패.)
lpAuthClientDispatch->UserMove();
lpAuthClientDispatch->SetPacketProcessFlag(
CAuthClientDispatch::SERVER_ZONE_SUCCESS);
}
else
{
lpAuthClientDispatch->ResetPacketProcessFlag(
CAuthClientDispatch::CHAR_SELECT_SUCCESS);
}
lpAuthClientDispatch->SetMoveAddress(lpPktSAAck->m_dwServerID,
INET_Addr(lpPktSAAck->m_GameAddress, CServerSetup::GetGameServerTCPPort(lpPktSAAck->m_dwServerID)));
if (0 != lpPktSAAck->GetError())
{
if (!AuthSendPacket::SendServerZone(lpAuthClientDispatch->GetSendStream(), lpPktSAAck->m_dwServerID,
lpAuthClientDispatch->GetMoveAddress().get_addr_in(), lpPktSAAck->GetError()))
{
lpAuthClientDispatch->ResetPacketProcessFlag(
CAuthClientDispatch::SERVER_ZONE_SUCCESS);
}
}
else
{
char* lpBuffer = GetSendStream().GetBuffer(sizeof(PktDD));
if (0 != lpBuffer)
{
unsigned long dwRequestKey = CServerRequest::GetInstance().AddRequest(
lpAuthClientDispatch, this, 100);
if (0 != dwRequestKey)
{
PktDD* lpPktDD = reinterpret_cast<PktDD*>(lpBuffer);
lpPktDD->InitPtSubCmd(dwRequestKey, PktDD::SCmdServerZoneEnd);
if (GetSendStream().WrapHeader(sizeof(PktDD), CmdAgentZone, 0, 0))
{
DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/sCmd:0x%02x/RequestKey:%d/DBRequest Send success.",
&lpAuthClientDispatch->GetSession(), lpAuthClientDispatch,
lpAuthClientDispatch->GetRemoteAddr().get_addr_string(),
PktSA::SCmdServerZoneEnd, dwRequestKey);
break;
}
else
{
CServerRequest::GetInstance().RemoveRequest(dwRequestKey);
}
}
}
}
break;
}
case PktDD::SCmdServerZoneEnd:
if (!AuthSendPacket::SendServerZone(lpAuthClientDispatch->GetSendStream(),
lpAuthClientDispatch->GetMoveServerID(), lpAuthClientDispatch->GetMoveAddress().get_addr_in(), 0))
{
lpAuthClientDispatch->ResetPacketProcessFlag(
CAuthClientDispatch::SERVER_ZONE_SUCCESS);
}
break;
default:
ERRLOG2(g_Log, "DB로부터 이상한 패킷이 들어왔습니다. 커맨드는 %x, 유저 세션 포인터는 0x%p 입니다.",
lpPktDD->GetCmd(), lpSession);
return true;
}
return true;
}
bool CAuthAgentDispatch::ParseUserKill(PktUK* lpPktUK)
{
// 유저 얻기
GET_MULTI_DISPATCH(lpAuthClientDispatch, lpPktUK->m_dwUserID,
CAuthClientDispatch, CAuthClientDispatch::GetDispatchTable());
if (0 == lpAuthClientDispatch)
{
ERRLOG1(g_Log, "UID:%u/GetUser failed.", lpPktUK->m_dwUserID);
SendUserKill(lpPktUK->m_dwUserID, 2);
}
else
{
// 소켓 클로즈
ERRLOG3(g_Log, "SS:0x%p/DP:0x%p/UID:%u/Process UserKill.",
&lpAuthClientDispatch->GetSession(),
lpAuthClientDispatch, lpPktUK->m_dwUserID);
lpAuthClientDispatch->Shutdown();
}
return true;
}
bool CAuthAgentDispatch::SendUserKill(unsigned long dwUserID, unsigned short usError)
{
char* lpBuffer = GetSendStream().GetBuffer(sizeof(PktUK));
if (0 != lpBuffer)
{
PktUK* lpPktUK = reinterpret_cast<PktUK*>(lpBuffer);
lpPktUK->m_dwServerID = CServerSetup::GetInstance().GetServerID();
lpPktUK->m_dwUserID = dwUserID;
lpPktUK->m_dwCharID = 0;
return GetSendStream().WrapCrypt(sizeof(PktUK), CmdUserKill, 0, usError);
}
return false;
}
bool CAuthAgentDispatch::SendSysServerLogin(unsigned long ServerID_In)
{
char* lpBuffer = GetSendStream().GetBuffer(sizeof(PktSL));
if (0 != lpBuffer)
{
PktSL* lpPktSL = reinterpret_cast<PktSL*>(lpBuffer);
const int MAX_ADDRESS_SIZE = 128;
char szAddress[MAX_ADDRESS_SIZE];
GetSession().GetPolicy().GetSocketFactory().GetNetworkInfo(szAddress, MAX_ADDRESS_SIZE);
lpPktSL->m_Address.S_un.S_addr = inet_addr(szAddress);
lpPktSL->m_dwServerID = ServerID_In;
return GetSendStream().WrapHeader(sizeof(PktSL), CmdSysServerLogin, 0, 0);
}
return false;
}
bool CAuthAgentDispatch::SendStartSession(CAuthClientDispatch* lpDispatch_In, unsigned long dwSessionID_In,
const char* AccountName_In, const char* Password_In,
unsigned long dwUserID_In, unsigned short usCnFlag_In)
{
GET_SINGLE_DISPATCH(lpAuthAgentDispatch, CAuthAgentDispatch,
CAuthAgentDispatch::GetDispatchTable());
if (0 != lpAuthAgentDispatch && 0 != lpDispatch_In)
{
CSendStream& SendStream = lpAuthAgentDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSSD));
if (0 != lpBuffer)
{
unsigned long dwRequestKey = CServerRequest::GetInstance().AddRequest(
lpDispatch_In, lpAuthAgentDispatch, 100);
if (0 != dwRequestKey)
{
// edith 2008.01.15 Auth에서 Agent에 세션시작 패킷을 보낸다.??
// PktSSD 에 패스워드를 추가해서 Agent에 보내도록 해야한다. 함수를 수정해야함.
PktSSD* lpPktSSDPt = reinterpret_cast<PktSSD*>(lpBuffer);
lpPktSSDPt->InitPtSubCmd(dwRequestKey, PktSSD::SCmdStartSession);
lpPktSSDPt->m_dwSessionID = dwSessionID_In;
lpPktSSDPt->m_dwUserID = dwUserID_In;
if (0 != AccountName_In && strlen(AccountName_In) > 0)
{
memcpy(lpPktSSDPt->m_AccountName, AccountName_In, sizeof(char) * PktSSD::MaxName);
}
else
ZeroMemory(lpPktSSDPt->m_AccountName, sizeof(char) * PktSSD::MaxName);
if (0 != Password_In && strlen(Password_In) > 0)
{
memcpy(lpPktSSDPt->m_Password, Password_In, sizeof(char) * PktSSD::MaxPass);
}
else
ZeroMemory(lpPktSSDPt->m_Password, sizeof(char) * PktSSD::MaxPass);
lpPktSSDPt->m_Address = lpDispatch_In->GetSession().GetRemoteAddr().get_addr_in().sin_addr;
if (SendStream.WrapCrypt(sizeof(PktSSD), CmdDBGetData, 0, usCnFlag_In))
{
INFLOG4(g_Log, "UID:%10u / DP:0x%p / SessionID:%10u / Account:%s / 로그인 성공. DB중계로 세션 시작 보냄",
dwUserID_In, lpDispatch_In, dwSessionID_In, AccountName_In);
DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/sCmd:0x%02x/RequestKey:%d/DBRequest Send success.",
&lpDispatch_In->GetSession(), lpDispatch_In,
lpDispatch_In->GetRemoteAddr().get_addr_string(),
PktSSD::SCmdStartSession, dwRequestKey);
return true;
}
}
}
}
if (lpDispatch_In)
{
AuthSendPacket::SendAuthAccount(lpDispatch_In, lpDispatch_In->GetUID(), 1);
}
return false;
}
bool CAuthAgentDispatch::SendCreateCharEquipItem(unsigned long CharID_In, unsigned short Shirt_In,
unsigned short Armour_In, unsigned short Boots_In, unsigned short Weapon_In)
{
const size_t nMaxPacketLen = sizeof(PktCCID) + Item::MAX_ITEM_SIZE * 4;
char* lpBuffer = GetSendStream().GetBuffer(nMaxPacketLen);
if (NULL != lpBuffer)
{
char* lpItemPos = lpBuffer + sizeof(PktCCID);
PktCCID* lpPktCCID = reinterpret_cast<PktCCID*>(lpBuffer);
size_t nSize = 0;
size_t nTotalSize = 0;
// 아이템 생성
CItemCreator& ItemCreator = CItemCreator::GetInstance();
Item::CItem* lpShirt = (0 != Shirt_In) ? ItemCreator.Create(Shirt_In) : 0;
Item::CItem* lpAmour = (0 != Armour_In) ? ItemCreator.Create(Armour_In) : 0;
Item::CItem* lpBoots = (0 != Boots_In) ? ItemCreator.Create(Boots_In) : 0;
Item::CItem* lpWeapon = (0 != Weapon_In) ? ItemCreator.Create(Weapon_In) : 0;
Item::CEquipment* lpEquip = NULL;
lpEquip = Item::CEquipment::DowncastToEquipment(lpShirt);
if (NULL != lpEquip) { lpEquip->SetNewEquip(); }
lpEquip = Item::CEquipment::DowncastToEquipment(lpAmour);
if (NULL != lpEquip) { lpEquip->SetNewEquip(); }
lpEquip = Item::CEquipment::DowncastToEquipment(lpBoots);
if (NULL != lpEquip) { lpEquip->SetNewEquip(); }
lpEquip = Item::CEquipment::DowncastToEquipment(lpWeapon);
if (NULL != lpEquip) { lpEquip->SetNewEquip(); }
// 셔츠 생성
if (NULL != lpShirt)
{
nSize = nMaxPacketLen - nTotalSize;
lpShirt->MoveItem(Item::ItemPos(1, Item::EquipmentPos::SHIRT));
lpShirt->SerializeOut(lpItemPos, nSize);
lpItemPos += nSize;
nTotalSize += nSize;
DELETE_ITEM(lpShirt);
}
// 아머 생성
if (NULL != lpAmour)
{
nSize = nMaxPacketLen - nTotalSize;
lpAmour->MoveItem(Item::ItemPos(1, Item::EquipmentPos::ARMOUR));
lpAmour->SerializeOut(lpItemPos, nSize);
lpItemPos += nSize;
nTotalSize += nSize;
DELETE_ITEM(lpAmour);
}
// 부츠 생성
if (NULL != lpBoots)
{
nSize = nMaxPacketLen - nTotalSize;
lpBoots->MoveItem(Item::ItemPos(1, Item::EquipmentPos::BOOTS));
lpBoots->SerializeOut(lpItemPos, nSize);
lpItemPos += nSize;
nTotalSize += nSize;
DELETE_ITEM(lpBoots);
}
// 기본 무기 생성
if (NULL != lpWeapon)
{
nSize = nMaxPacketLen - nTotalSize;
lpWeapon->MoveItem(Item::ItemPos(1, Item::EquipmentPos::WEAPON_HAND1));
lpWeapon->SerializeOut(lpItemPos, nSize);
lpItemPos += nSize;
nTotalSize += nSize;
DELETE_ITEM(lpWeapon);
}
lpPktCCID->InitPtSubCmd(0, PktCCID::SCmdCharCreateItem);
lpPktCCID->m_dwItemSerial = ItemCreator.GetUID();
lpPktCCID->m_dwCharID = CharID_In;
lpPktCCID->m_dwSize = (unsigned long)nTotalSize;
return GetSendStream().WrapHeader(
static_cast<unsigned short>(sizeof(PktCCID) + nTotalSize), CmdDBGetData, 0, 0);
}
return false;
}
bool CAuthAgentDispatch::ParseBillingTimeoutNotify(PktBTN* lpPktBTN)
{
GET_MULTI_DISPATCH(lpAuthClientDispatch, lpPktBTN->m_dwUserID,
CAuthClientDispatch, CAuthClientDispatch::GetDispatchTable());
if (0 == lpAuthClientDispatch)
{
ERRLOG1(g_Log, "UID:0x%08d 유저 얻기 실패.", lpPktBTN->m_dwUserID);
}
else
{
CSendStream& SendStream = lpAuthClientDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktBTN));
if (0 != lpBuffer)
{
memcpy(lpBuffer, lpPktBTN, sizeof(PktBTN));
return SendStream.WrapCrypt(sizeof(PktBTN), CmdBillingTimeoutNotify, 0, 0);
}
}
return false;
}
bool CAuthAgentDispatch::ParseBillingTimeCheckNotify(PktBTN* lpPktBTN)
{
GET_MULTI_DISPATCH(lpAuthClientDispatch, lpPktBTN->m_dwUserID,
CAuthClientDispatch, CAuthClientDispatch::GetDispatchTable());
if (0 == lpAuthClientDispatch)
{
ERRLOG1(g_Log, "UID:0x%08d 유저 얻기 실패.", lpPktBTN->m_dwUserID);
}
else
{
CSendStream& SendStream = lpAuthClientDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktBTN));
if (0 != lpBuffer)
{
memcpy(lpBuffer, lpPktBTN, sizeof(PktBTN));
return SendStream.WrapCrypt(sizeof(PktBTN), CmdBillingTimeCheckNotify, 0, 0);
}
}
return false;
}
bool CAuthAgentDispatch::ParseUnifiedCharInfo(PktUnifiedCharInfo* lpPktUnifiedCharInfo)
{
// DB중계서버에서 받은 데이터를 클라이언트로 넘겨준다.
GET_MULTI_DISPATCH(lpAuthClientDispatch, lpPktUnifiedCharInfo->dwUID,
CAuthClientDispatch, CAuthClientDispatch::GetDispatchTable());
if(0 != lpAuthClientDispatch)
{
// 통합서버 정보를 클라이언트로 넘겨준다.
lpAuthClientDispatch->GetSendStream().WrapCompress(
reinterpret_cast<char*>(lpPktUnifiedCharInfo), lpPktUnifiedCharInfo->GetLen(),
CmdUnifiedCharInfo, 0, lpPktUnifiedCharInfo->GetError());
}
return true;
}
bool CAuthAgentDispatch::ParseUnifiedCharSelectAck(PktUnifiedCharSelectAck* lpPktUnifiedCharSelectAck)
{
unsigned long dwRequestKey = lpPktUnifiedCharSelectAck->dwRequestKey;
CServerRequest::Result result(dwRequestKey);
CAuthClientDispatch* lpAuthClientDispatch =
static_cast<CAuthClientDispatch*>(result.GetDispatch());
if(0 == lpAuthClientDispatch)
{
ERRLOG1(g_Log, "RequestKey:%d/DBRequest Failed.", dwRequestKey);
return true;
}
CSession* lpSession = result.GetSession();
if(0 == lpSession)
{
ERRLOG1(g_Log, "RequestKey:%d/Get Session Failed.", dwRequestKey);
return true;
}
DETLOG3(g_Log, "SS:0x%p/DP:0x%p/RequestKey:%d/DBRequest Success.",
&lpAuthClientDispatch->GetSession(), lpAuthClientDispatch, dwRequestKey);
AuthSendPacket::SendUnifiedCharSelectAck(lpAuthClientDispatch->GetSendStream(),
lpPktUnifiedCharSelectAck->dwUID, 0, lpPktUnifiedCharSelectAck->GetError());
return true;
}