366 lines
11 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|