Files
2022-10-26 12:25:11 +08:00

400 lines
13 KiB
C++

#include "StdAfx.h"
#include ".\handler_sa.h"
#include <PacketStruct_SA.h>
#include <PacketStruct_SM.h>
#include <PacketStruct_AT.h>
#include <PublicStruct.h>
#include <Constant.h>
#include "ServerSession.h"
#include "UserSession.h"
#include "ServerSessionManager.h"
#include "User.h"
#include "UserManager.h"
#include "World.h"
#include "UnitServer.h"
#include "WorldManager.h"
#include "AgentInfoParser.h"
#include "AgentInfo.h"
#include "AgentServerSession.h"
Handler_SA::Handler_SA(void)
{
}
Handler_SA::~Handler_SA(void)
{
}
// Agent Auth
VOID Handler_SA::OnHandler_SA_SERVER_AUTH_SYN( ServerSession *pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_AUTH_SYN *pRecvMsg = (MSG_SA_SERVER_AUTH_SYN*)pMsg;
// 해당 IP의 Agent 정보가 존재하는지 체크
AgentInfo *pAgentInfo = AgentInfoParser::Instance()->GetAgentInfo( pSession->GetIP() );
MSG_SA_SERVER_AUTH_ACK AckMsg;
if( pAgentInfo )
{
AckMsg.m_byResult = RC_AGENT_AUTH_SUCCESS;
AckMsg.m_dwAgentKey = pAgentInfo->GetKey();
pSession->SetServerKey( pAgentInfo->GetKey() );
ServerSessionManager::Instance()->AddSession( pSession );
MSGOUT( "[Handler_SA::OnHandler_SA_SERVER_AUTH_SYN] AgentServer Auth Success, Key = %u", pAgentInfo->GetKey() );
}
else
{
AckMsg.m_byResult = RC_AGENT_AUTH_FAIL;
AckMsg.m_dwAgentKey = 0;
MSGOUT( "[Handler_SA::OnHandler_SA_SERVER_AUTH_SYN] AgentServer Auth Fail, Key = %d, 0" );
}
pSession->SendPacket( (BYTE*)&AckMsg, sizeof(AckMsg) );
}
// 서버 시작 결과
VOID Handler_SA::OnHandler_SA_SERVER_EXECUTE_ACK( ServerSession *pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_EXECUTE_ACK *pRecvMsg = (MSG_SA_SERVER_EXECUTE_ACK*)pMsg;
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[SERVER_EXECUTE_ACK] Can't find ServerStart-User!" );
return;
}
// 서버시작 결과를 알린다.
MSG_SM_SERVER_EXECUTE_ACK AckMsg;
AckMsg.m_byResult = pRecvMsg->m_byResult;
memcpy( &AckMsg.m_ServerInfo, &pRecvMsg->m_ServerInfo, sizeof(SERVER_INFO) );
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
//패치 시작을 전 유저에게 알려서 패치 시작시 다른 작업을 못하게 한다.
MSGOUT( "[SERVER_EXECUTE_ACK] Result : %d, World : %d, Channel : %d, ServerType : %d, ServerNum %d "
, AckMsg.m_byResult, pRecvMsg->m_ServerInfo.m_byWorld, pRecvMsg->m_ServerInfo.m_byChannel
, pRecvMsg->m_ServerInfo.m_byServerType, pRecvMsg->m_ServerInfo.m_byServerNum );
}
VOID Handler_SA::OnHandler_SA_SERVER_FORCE_DISCONNECT_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_FORCE_DISCONNECT_ACK *pRecvMsg = (MSG_SA_SERVER_FORCE_DISCONNECT_ACK*)pMsg;
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[Handler_SA::OnHandler_SA_SERVER_FORCE_DISCONNECT_ACK] Can't find ServerStart-User!" );
return;
}
// 서버 강제종료 결과를 알린다.
MSG_SM_SERVER_FORCE_DISCONNECT_ACK Ack;
Ack.m_byResult = pRecvMsg->m_byResult;
Ack.m_ServerInfo = pRecvMsg->m_ServerInfo;
pUser->SendPacket( &Ack, sizeof(Ack) );
}
// 패치 시작 결과
VOID Handler_SA::OnHandler_SA_PATCH_EXECUTE_ACK( ServerSession *pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_PATCH_EXECUTE_ACK *pRecvMsg = (MSG_SA_PATCH_EXECUTE_ACK*)pMsg;
UnitServer* pSunServer = WorldManager::Instance()->FindSunServer( pRecvMsg->m_ServerInfo.m_byWorld );
if( !pSession )
{
MSGOUT( "[패치시작결과] %d월드의 SunServer 정보를 찾을수 없습니다.", pRecvMsg->m_ServerInfo.m_byWorld );
return;
}
if( pSunServer->GetServerStatus() != SERVER_STATUS_PATCHING )
{
MSGOUT( "[패치시작결과] %d월드가 패치중이 아닌데, 패치결과가 왔다.", pRecvMsg->m_ServerInfo.m_byWorld );
return;
}
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[패치시작결과] 패치를 실행한 유저를 찾을 수 없습니다." );
return;
}
//해당월드의 모든 서버의 상태를 패치중으로 고친다.
// UnitServer* pSunServer = WorldManager::Instance()->FindSunServer( pRecvMsg->m_ServerInfo.m_byWorld );
pSunServer->SetServerStatus( SERVER_STATUS_PATCHING );
MSG_SM_PATCH_EXECUTE_ACK AckMsg;
AckMsg.m_byResult = pRecvMsg->m_byResult;
memcpy( &AckMsg.m_ServerInfo, &pRecvMsg->m_ServerInfo, sizeof(SERVER_INFO) );
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
MSGOUT( "[PATCH_EXECUTE_ACK] Result : %d, World : %d, Channel : %d, ServerType : %d, ServerNum %d "
, pRecvMsg->m_byResult, pRecvMsg->m_ServerInfo.m_byWorld, pRecvMsg->m_ServerInfo.m_byChannel
, pRecvMsg->m_ServerInfo.m_byServerType, pRecvMsg->m_ServerInfo.m_byServerNum );
}
// 패치 완료 결과
// 이 패킷이 오면, 무조건 서버상태를 오프라인으로 바꾼다.
VOID Handler_SA::OnHandler_SA_PATCH_RESULT_NTF( ServerSession *pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_PATCH_RESULT_NTF *pRecvMsg = (MSG_SA_PATCH_RESULT_NTF*)pMsg;
// Manager로 현재 결과를 보낸다.
MSG_SM_PATCH_RESULT_NTF msg;
msg.patch_result_.patch_result_type_ = pRecvMsg->m_dwResult;
msg.patch_result_.solar_server_type_ = pRecvMsg->m_byNum;
ZeroMemory( &msg.m_ServerPatchInfo, sizeof(SERVER_PATCH_INFO) );
memcpy( &msg.m_ServerPatchInfo.m_PatchVer, &pRecvMsg->m_PatchVer, sizeof(PATCH_VERSION) );
// AgentKey와 ServerType으로 해당서버를 찾는다.
UnitServer *pSunServer = WorldManager::Instance()->FindUnitServer( pSession->GetServerKey(), pRecvMsg->m_byServerType );
if( pSunServer )
{
if( pSunServer->GetServerType() != SUN_SERVER && pSunServer->GetServerType() != SOLARAUTH_SERVER )
{
MSGOUT("패치결과가 SUN_SERVER가 아닌 이상한 값이 넘어왔다. SERVER_TYPE = %d", pSunServer->GetServerType() );
}
// 해당 SunServer가 속한 월드의 모든 서버상태를 Offline으로 바꾼다. ==> Offline이 아니라 당연히 Offline 상태이어야 한다.
World* pWorld = WorldManager::Instance()->FindWorld( pSunServer->GetWorld() );
pWorld->SetServerStatus( SERVER_STATUS_OFFLINE );
//현재 패치결과가 날라온 서버가 존재한다면... 해당 서버의 정보를 보낼 메세지에 저장한다.
pSunServer->GetServerInfo().GetServerInfo( &msg.m_ServerPatchInfo );
}
else //현재 패치결과에 해당하는 서버가 존재하지 않는다면..
{
MSGOUT("AgentKey[%d] ServerType[%d] Can't Find ServerInfo! \n", pSession->GetServerKey(), pRecvMsg->m_byServerType );
msg.m_ServerPatchInfo.m_byServerType = pRecvMsg->m_byServerType;
}
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[PATCH_RESULT_NTF] Can't find Patch-User! \n" );
return;
}
int nRet = pUser->SendPacket( &msg, sizeof(msg) );
}
// 공지사항
VOID Handler_SA::OnHandler_SA_SERVER_NOTICE_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_NOTICE_ACK *pRecvMsg = (MSG_SA_SERVER_NOTICE_ACK*)pMsg;
// 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "공지를 정보를 요청한 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_SERVER_NOTICE_ACK AckMsg;
AckMsg.m_ServerInfo = pRecvMsg->m_ServerInfo;
AckMsg.m_dwUserKey = pRecvMsg->m_dwUserKey;
strcpy( AckMsg.m_szNotice, pRecvMsg->m_szNotice );
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
}
VOID Handler_SA::OnHandler_SA_SERVER_SEND_NOTICE_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_SEND_NOTICE_ACK *pRecvMsg = (MSG_SA_SERVER_SEND_NOTICE_ACK*)pMsg;
// 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "공지를 보낸 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_SERVER_SEND_NOTICE_ACK AckMsg;
AckMsg.m_ServerInfo = pRecvMsg->m_ServerInfo;
AckMsg.m_bFlag = pRecvMsg->m_bFlag;
AckMsg.m_bConnectAgentServer = TRUE;
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
}
VOID Handler_SA::OnHandler_SA_CHECK_LOGFILE_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_CHECK_LOGFILE_ACK *pRecvMsg = (MSG_SA_CHECK_LOGFILE_ACK*)pMsg;
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[로그보기결과] 로그보기를 실행한 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_CHECK_LOGFILE_ACK AckMsg;
AckMsg.m_byResult = pRecvMsg->m_byResult;
AckMsg.m_ServerInfo = pRecvMsg->m_ServerInfo;
memcpy( &AckMsg.m_szLogFile, &pRecvMsg->m_szLogFile, MAX_FILE_BUFFER_SIZE );
AckMsg.m_wFileSize = pRecvMsg->m_wFileSize;
AckMsg.m_NumAllLogPage = pRecvMsg->m_NumAllLogPage;
pUser->SendPacket( &AckMsg, AckMsg.GetSize() );
}
VOID Handler_SA::OnHandler_SA_CHECK_GAMEPROCESS_NTF( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_CHECK_GAMEPROCESS_NTF* pRecvMsg = (MSG_SA_CHECK_GAMEPROCESS_NTF*)pMsg;
AgentServerSession* pAgentSession = (AgentServerSession*)pSession;
//에이전트 키와 서버타입으로, 현재 서버의 정보를 얻는다.
UnitServer* pUnitServer = WorldManager::Instance()->FindUnitServer( pAgentSession->GetServerKey(), pRecvMsg->m_GameStatus.m_ServerType );
if( !pUnitServer )
{
//그런 서버 존재하지 않음.
return;
}
//현재 서버의 상태와 같은 상태이면 보내지 않는다.
if( pUnitServer->GetServerStatus() == pRecvMsg->m_GameStatus.m_Status ) //같은 서버
return;
//현재 서버가 패치중이면 보내지 않는다.
if( pUnitServer->GetServerStatus() == SERVER_STATUS_PATCHING )
return;
//여기로 오는 메세지는 서버가 켜져 있다, 아니면 꺼져있다.. 2가지 상태이다.
if( SERVER_STATUS_LIVE_PROCESS == pRecvMsg->m_GameStatus.m_Status ) //켜져있으면
{
//1. 현재 서버의 상태가 Online인데, 라이브 명령이면 무시한다.
if( SERVER_STATUS_ONLINE == pUnitServer->GetServerStatus() )
return;
}
pUnitServer->SetServerStatus( pRecvMsg->m_GameStatus.m_Status );
// MSG_SM_CHECK_GAMEPROCESS_NTF msg;
// ServerInfo& rServerInfo = pUnitServer->GetServerInfo();
// rServerInfo.GetServerInfo( &msg.m_ServerInfo );
// UserManager::Instance()->SendPacketAll( &msg, sizeof(msg) );
}
VOID Handler_SA::OnHandler_SA_SERVER_BACKUP_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_BACKUP_ACK* pRecvMsg = (MSG_SA_SERVER_BACKUP_ACK*)pMsg;
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[백업결과] 백업을 실행한 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_SERVER_BACKUP_ACK ack;
ack.m_byResult = pRecvMsg->m_byResult;
ack.m_dwUserKey = pRecvMsg->m_dwUserKey;
ack.m_ServerInfo = pRecvMsg->m_ServerInfo;
pUser->SendPacket( &ack, sizeof(ack) );
}
VOID Handler_SA::OnHandler_SA_SERVER_RESTORE_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SERVER_RESTORE_ACK* pRecvMsg = (MSG_SA_SERVER_RESTORE_ACK*)pMsg;
// 패치를 실행시킨 유저를 찾는다.
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey );
if( !pUser )
{
MSGOUT( "[백업결과] 백업을 실행한 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_SERVER_RESTORE_ACK ack;
ack.m_byResult = pRecvMsg->m_byResult;
ack.m_dwUserKey = pRecvMsg->m_dwUserKey;
ack.m_ServerInfo = pRecvMsg->m_ServerInfo;
pUser->SendPacket( &ack, sizeof(ack) );
}
#ifdef __20080312__SOLARAUTH_SERVER_PATCH
VOID Handler_SA::OnHandler_SA_SOLARSCRIPT_BACKUP_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SOLARSCRIPT_BACKUP_ACK* pRecvMsg = (MSG_SA_SOLARSCRIPT_BACKUP_ACK *)pMsg;
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey);
if( !pUser )
{
MSGOUT( "스크립트 백업을 실행한 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_SERVER_SOLARSCRIPT_BACKUP_ACK ack;
ack.m_byResult = pRecvMsg->m_byResult;
ack.m_FolderInfo = pRecvMsg->m_ScriptFolder;
pUser->SendPacket( &ack, sizeof(ack) );
}
VOID Handler_SA::OnHandler_SA_SOLARSCRIPT_RESTORE_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SOLARSCRIPT_RESTORE_ACK* pRecvMsg = (MSG_SA_SOLARSCRIPT_RESTORE_ACK *)pMsg;
MSG_SM_SERVER_SOLARSCRIPT_RESTORE_ACK ack;
ack.m_byResult = pRecvMsg->m_byResult;
ack.m_FolderInfo = pRecvMsg->m_ScriptFolder;
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey);
if( !pUser )
{
MSGOUT( "스크립트 복원을 실행한 유저를 찾을 수 없습니다." );
ack.m_byResult = RC_SERVER_PATCH_EXECUTE_FAIL;
}
pUser->SendPacket( &ack, sizeof( ack));
}
VOID Handler_SA::OnHandler_SA_SOLARSCRIPT_EXECUTE_ACK( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
MSG_SA_SOLARSCRIPT_EXECUTE_ACK* pRecvMsg = (MSG_SA_SOLARSCRIPT_EXECUTE_ACK *)pMsg;
User *pUser = (User*)UserManager::Instance()->GetUser( pRecvMsg->m_dwUserKey);
if( !pUser )
{
MSGOUT( "스크립트 패치를 실행한 유저를 찾을 수 없습니다." );
return;
}
MSG_SM_PATCH_SOLARSCRIPT_EXECUTE_ACK ack;
ack.m_byResult = pRecvMsg->m_byResult;
ack.m_FolderInfo = pRecvMsg->m_ScriptFolder;
pUser->SendPacket( &ack, sizeof( ack));
}
#endif
#ifdef _NA_006543_20130318_HEARTBEAT
VOID Handler_SA::OnHandler_SA_CHECK_HEARTBEAT_NTF( ServerSession* pSession, MSG_BASE* pMsg, int nSize )
{
//UpdateServer에서 사용
//DISPMSG("Recv Heartbeat\n");
static_cast<AgentServerSession*>(pSession)->CheckHeatbeatRecv();
}
#endif