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

366 lines
11 KiB
C++

#include "StdAfx.h"
#include "UnitServer.h"
#include "PacketStruct_SA.h"
#include "ServerSessionManager.h"
#include "ServerSession.h"
#include "PacketStruct_SMA.h"
#include "PacketStruct_SM.h"
#include "User.h"
#include "UserManager.h"
#include "AccessInfo.h"
#include "AccessInfoParser.h"
#include "FtpInfo.h"
#include "FtpInfoParser.h"
UnitServer::UnitServer()
{
}
UnitServer::~UnitServer()
{
}
VOID UnitServer::Release()
{
}
VOID UnitServer::ExecuteStart( DWORD dwUserKey )
{
User* pUser = (User*)UserManager::Instance()->GetUser( dwUserKey );
if( !pUser ) return;
//먼저 해당 서버의 현재 상태가 켜져 있으면...
if( !IsEnableStart() )
{
MSG_SM_SERVER_EXECUTE_ACK ack;
ack.m_byResult = GetResultServerStatus( m_ServerInfo.GetServerStatus() );
m_ServerInfo.GetServerInfo( &ack.m_ServerInfo );
pUser->SendPacket( &ack, sizeof( ack ) );
return;
}
ServerSession *pAgentSession = ServerSessionManager::Instance()->FindAgentSession( m_ServerInfo.GetAgentKey() );
if( !pAgentSession )
{
MSG_SM_SERVER_EXECUTE_ACK AckMsg;
AckMsg.m_byResult = RC_SERVER_EXECUTE_FAIL_UPDATEAGENT_NOT_CONNECT;
memcpy( &AckMsg.m_ServerInfo, &m_ServerInfo, sizeof(SERVER_INFO) );
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
return;
}
else
{
MSG_SA_SERVER_EXECUTE_SYN SynMsg;
SynMsg.m_dwUserKey = dwUserKey;
#ifdef __20080312__SOLARAUTH_SERVER_PATCH
m_ServerInfo.GetServerInfo( &SynMsg.m_ServerInfo);
#else
memcpy( &SynMsg.m_ServerInfo, &m_ServerInfo, sizeof(SERVER_INFO) );
#endif
pAgentSession->SendPacket( (BYTE*)&SynMsg, sizeof(SynMsg) );
}
}
//마스터에 의한 서버종료
VOID UnitServer::ExecuteEnd( DWORD dwUserKey )
{
User* pUser = (User*)UserManager::Instance()->GetUser( dwUserKey );
if( !pUser ) return;
if( !IsEnableEnd() )
{
MSG_SM_SERVER_SHUTDOWN_ACK ack;
ack.m_byResult = GetResultServerStatus( m_ServerInfo.GetServerStatus() );
m_ServerInfo.GetServerInfo( &ack.m_ServerInfo );
pUser->SendPacket( &ack, sizeof( ack ) );
return;
}
ServerSession *pMasterSession = ServerSessionManager::Instance()->FindMasterSession();
if( !pMasterSession )
{
MSG_SM_SERVER_SHUTDOWN_ACK ack;
m_ServerInfo.GetServerInfo( &ack.m_ServerInfo );
ack.m_byResult = RC_SERVER_SHUTDOWN_START_FAIL_MASTER_SERVER_NOT_CONNECT;
MSGOUT( "[서버종료실행실패] pMasterSession is disconnected!" );
pUser->SendPacket( &ack, sizeof(ack) );
return;
}
else
{
MSG_MO_RTTG_SERVERSHUTDOWN_REQ ReqMsg;
ReqMsg.dwKey = dwUserKey;
ReqMsg.m_byWorldID = m_ServerInfo.GetServerInfoEx().m_byWorld;
ReqMsg.m_byChannelID = m_ServerInfo.GetServerInfoEx().m_byChannel;
ReqMsg.m_byServerType = m_ServerInfo.GetServerInfoEx().m_byServerType;
ReqMsg.m_byServerID = m_ServerInfo.GetServerInfoEx().m_byServerNum;
pMasterSession->SendPacket( (BYTE*)&ReqMsg, sizeof(ReqMsg) );
MSG_SM_SERVER_SHUTDOWN_ACK ack;
m_ServerInfo.GetServerInfo( &ack.m_ServerInfo );
ack.m_byResult = RC_SERVER_SHUTDOWN_START_SUCCESS; //서버종료 시작 성공
pUser->SendPacket( &ack, sizeof(ack) );
//서버 종료 로그
MSGOUT( "[서버종료시작] ID = %s, IP = %s, World = %d, Channel = %d, ServerType = %d "
, pUser->GetID(), pUser->GetIP(), ReqMsg.m_byWorldID, ReqMsg.m_byChannelID, ReqMsg.m_byServerType
, ReqMsg.m_byServerID );
}
}
BOOL UnitServer::ExecutePatch( DWORD dwUserKey )
{
//실행시킨 유저를 검사한다.
User* pUser = (User*)UserManager::Instance()->GetUser( dwUserKey );
if( !pUser ) return FALSE;
if( !IsEnablePatch() )
{
MSG_SM_PATCH_EXECUTE_ACK ack;
ack.m_byResult = GetResultServerStatus( m_ServerInfo.GetServerStatus() );
m_ServerInfo.GetServerInfo( &ack.m_ServerInfo );
pUser->SendPacket( &ack, sizeof( ack ) );
return FALSE;
}
// SUN_SERVER면 패치 실행 명령을 내리고, SUN_SERVER가 아니면, 현재 서버상태가 변경되었다고 접속된 유저들에게 알려준다.
if( GetServerType() == SUN_SERVER )
{
ServerSession *pAgentSession = ServerSessionManager::Instance()->FindAgentSession( m_ServerInfo.GetAgentKey() );
if( !pAgentSession )
{
//유저에게 해당 Agent가 켜져 있지 않아서, 패치실행 실패 했다고 전한다.
MSG_SM_PATCH_EXECUTE_ACK AckMsg;
AckMsg.m_byResult = RC_SERVER_PATCH_EXECUTE_FAIL_UPDATEAGENT_NOT_CONNECT;
#ifdef __20080312__SOLARAUTH_SERVER_PATCH
m_ServerInfo.GetServerInfo( &AckMsg.m_ServerInfo);
#else
memcpy( &SynMsg.m_ServerInfo, &m_ServerInfo, sizeof(SERVER_INFO) );
#endif
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
return FALSE;
}
else
{
SetServerStatus( SERVER_STATUS_PATCHING );
MSG_SA_PATCH_EXECUTE_SYN SynMsg;
SynMsg.m_dwUserKey = dwUserKey;
#ifdef __20080312__SOLARAUTH_SERVER_PATCH
m_ServerInfo.GetServerInfo( &SynMsg.m_ServerInfo);
#else
memcpy( &SynMsg.m_ServerInfo, &m_ServerInfo, sizeof(SERVER_INFO) );
#endif
pAgentSession->SendPacket( (BYTE*)&SynMsg, sizeof(SynMsg) );
MSGOUT( "[패치실행] ID = %s, IP = %s, World = %d, Channel = %d, ServerType = %d "
, pUser->GetID(), pUser->GetIP(), m_ServerInfo.GetServerInfoEx().m_byWorld, m_ServerInfo.GetServerInfoEx().m_byChannel,
m_ServerInfo.GetServerInfoEx().m_byServerType, m_ServerInfo.GetServerInfoEx().m_byServerNum );
}
}
return TRUE;
}
VOID UnitServer::SerializeServerInfoStream( SERVER_TOTAL_INFO & OUT rServerTotInfo )
{
m_ServerInfo.SerializeStream( rServerTotInfo.m_Data[rServerTotInfo.m_Count], FALSE );
rServerTotInfo.m_Count++;
}
VOID UnitServer::SerializeServerInfoStreamForUser( SERVER_TOTAL_INFO & OUT rServerTotInfo, DWORD dwUserGUID )
{
//현재 서버가 유저에게 접근권한이 있는 서버인지 체크.
AccessInfo* pAccessInfo = AccessInfoParser::Instance()->GetAccessInfo( dwUserGUID );
if( !pAccessInfo ) return;
ACCESS_SERVER* pAccessServer = pAccessInfo->GetAccessServer( m_ServerInfo.GetServerInfoEx().m_dwServerKey );
if( !pAccessServer ) return;
// int nOnlineServer = 0;
if( pAccessServer->m_bAccess )
{
m_ServerInfo.SerializeStream( rServerTotInfo.m_Data[rServerTotInfo.m_Count], FALSE );
rServerTotInfo.m_Count++;
}
}
#ifdef __20080312__SOLARAUTH_SERVER_PATCH
VOID UnitServer::SerializeScriptFolderInfoStream( SCRIPTFOLDER_TOTAL_INFO& OUT rSCFolderInfo, DWORD dwUserGUID )
{
//현재 서버가 유저에게 접근권한이 있는 서버인지 체크.
AccessInfo* pAccessInfo = AccessInfoParser::Instance()->GetAccessInfo( dwUserGUID );
if( !pAccessInfo ) return;
ACCESS_SERVER* pAccessServer = pAccessInfo->GetAccessServer( m_ServerInfo.GetServerInfoEx().m_dwServerKey );
if( !pAccessServer ) return;
// int nOnlineServer = 0;
if( pAccessServer->m_bAccess )
m_ServerInfo.SerializeScriptFolderStream( rSCFolderInfo);
}
#endif
VOID UnitServer::SetServerStatus( eSERVER_STATUS status )
{
m_ServerInfo.SetServerStatus( status );
//SUN_SERVER는 타입만 바꾸고, Client에는 알려주지 않는다.
if( GetServerType() == SUN_SERVER )
return;
//SUN_SERVER가 이나고, 현재
MSG_SM_CHECK_GAMEPROCESS_NTF msg;
m_ServerInfo.GetServerInfo( &msg.m_ServerInfo );
UserManager::Instance()->SendPacketAll( &msg, sizeof(msg) );
}
VOID UnitServer::SerializeFtpInfoStreamForUser( FTP_TOTAL_INFO & OUT rFtpTotInfo, DWORD dwUserGUID )
{
//현재 서버가 유저에게 접근권한이 있는 서버인지 체크.
AccessInfo* pAccessInfo = AccessInfoParser::Instance()->GetAccessInfo( dwUserGUID );
if( !pAccessInfo ) return;
ACCESS_SERVER* pAccessServer = pAccessInfo->GetAccessServer( m_ServerInfo.GetServerInfoEx().m_dwServerKey );
if( !pAccessServer || !pAccessServer->m_bAccess ) return;
// 현재 서버가 가지고 있는 FTP 연결정보를 가지고 온다.
FtpInfo* pFtpInfo = FtpInfoParser::Instance()->GetFtpInfo( m_ServerInfo.GetServerInfoEx().m_byWorld );
if( !pFtpInfo ) return;
// 현재 Serialize하려는 FTP정보가 기존에 있었는지 체크한다.
for( int i = 0; i < rFtpTotInfo.m_Count; i++ )
{
FTP_CONNECT_INFO& rFtpConnectInfo = rFtpTotInfo.m_Data[i];
//기존의 FTP World 와 현재 FTP World가 같으면 리턴한다.
if( rFtpConnectInfo.m_byWorld == pFtpInfo->GetWorld() )
return;
}
pFtpInfo->SerializeStream( rFtpTotInfo.m_Data[rFtpTotInfo.m_Count], FALSE );
rFtpTotInfo.m_Count++;
}
VOID UnitServer::ExecuteForceDisconnect( DWORD dwUserKey )
{
User* pUser = (User*)UserManager::Instance()->GetUser( dwUserKey );
if( !pUser ) return;
if( !IsEnableForceDisconnect() )
{
MSG_SM_SERVER_FORCE_DISCONNECT_ACK ack;
ack.m_byResult = GetResultServerStatus( m_ServerInfo.GetServerStatus() );
m_ServerInfo.GetServerInfo( &ack.m_ServerInfo );
pUser->SendPacket( &ack, sizeof( ack ) );
return;
}
ServerSession *pAgentSession = ServerSessionManager::Instance()->FindAgentSession( m_ServerInfo.GetAgentKey() );
if( !pAgentSession )
{
//유저에게 해당 Agent가 켜져 있지 않아서, 패치실행 실패 했다고 전한다.
MSG_SM_SERVER_FORCE_DISCONNECT_ACK AckMsg;
AckMsg.m_byResult = RC_SERVER_FORCE_DISCONNECT_FAIL_UPDATEAGENT_NOT_CONNECT;
m_ServerInfo.GetServerInfo( &AckMsg.m_ServerInfo );
pUser->SendPacket( &AckMsg, sizeof(AckMsg) );
return;
}
else
{
MSG_SA_SERVER_FORCE_DISCONNECT_SYN SynMsg;
SynMsg.m_dwUserKey = dwUserKey;
m_ServerInfo.GetServerInfo( &SynMsg.m_ServerInfo );
pAgentSession->SendPacket( (BYTE*)&SynMsg, sizeof(SynMsg) );
}
//강제종료 로그
MSGOUT( "[서버강제종료] ID = %s, IP = %s, World = %d, Channel = %d, ServerType = %d "
, pUser->GetID(), pUser->GetIP(), m_ServerInfo.GetServerInfoEx().m_byWorld, m_ServerInfo.GetServerInfoEx().m_byChannel,
m_ServerInfo.GetServerInfoEx().m_byServerType, m_ServerInfo.GetServerInfoEx().m_byServerNum );
}
BOOL UnitServer::IsEnablePatch()
{
#ifdef _NA_006543_20130318_HEARTBEAT
//SunServer가 Unknown인 상황은 예외
if(m_ServerInfo.GetServerInfoEx().m_byServerType == SUN_SERVER && m_ServerInfo.GetServerStatus() == SERVER_STATUS_UNKNOWN)
return TRUE;
#endif
if( m_ServerInfo.GetServerStatus() != SERVER_STATUS_OFFLINE )
return FALSE;
return TRUE;
}
BOOL UnitServer::IsEnableEnd()
{
eSERVER_STATUS status = m_ServerInfo.GetServerStatus();
if( status == SERVER_STATUS_ONLINE || status == SERVER_STATUS_LIVE_PROCESS )
return TRUE;
return FALSE;
}
BOOL UnitServer::IsEnableStart()
{
eSERVER_STATUS status = m_ServerInfo.GetServerStatus();
if( status != SERVER_STATUS_OFFLINE )
return FALSE;
return TRUE;
}
BOOL UnitServer::IsEnableForceDisconnect()
{
eSERVER_STATUS status = m_ServerInfo.GetServerStatus();
if( status == SERVER_STATUS_ONLINE || status == SERVER_STATUS_LIVE_PROCESS )
return TRUE;
return FALSE;
}
eRC_SERVER_CONSTANT UnitServer::GetResultServerStatus( eSERVER_STATUS status )
{
eRC_SERVER_CONSTANT result = (eRC_SERVER_CONSTANT)0;
switch( status )
{
case SERVER_STATUS_OFFLINE:
result = RC_SERVER_STATUS_OFFLINE;
break;
case SERVER_STATUS_ONLINE:
result = RC_SERVER_STATUS_ONLINE;
break;
case SERVER_STATUS_LIVE_PROCESS:
result = RC_SERVER_STATUS_LIVE_PROCESS;
break;
case SERVER_STATUS_PATCHING:
result = RC_SERVER_STATUS_PATCHING;
break;
#ifdef _NA_006543_20130318_HEARTBEAT
case SERVER_STATUS_UNKNOWN:
result = RC_SERVER_STATUS_UNKNOWN;
break;
#endif
}
return result;
}