Files
Sun1602/Server/AgentServer/TimeCheck/HeartbeatManager.cpp
T
2022-10-26 12:25:11 +08:00

165 lines
5.2 KiB
C++

#include "stdafx.h"
#include "HeartbeatManager.h"
#include <UserSessions/UserManager.h>
//
sHEARTBEAT_VALUATION_INFO PROCESS_HEARTBEAT_VALUATION::ms_VALUATION_INFO = { 0, };
PROCESS_HEARTBEAT_VALUATION::sRECORD_INFO PROCESS_HEARTBEAT_VALUATION::ms_RECORD_INFO = { 0, };
//
BOOL PROCESS_HEARTBEAT_VALUATION::SetInformation( const sHEARTBEAT_VALUATION_INFO* pVALUATION_INFO )
{
sHEARTBEAT_VALUATION_INFO* pINFO = (sHEARTBEAT_VALUATION_INFO*)pVALUATION_INFO;
ASSERT( pINFO && pINFO->m_dwValuationPeriod && pINFO->m_dwHeartbeatTick );
if( !(pINFO && pINFO->m_dwValuationPeriod && pINFO->m_dwHeartbeatTick ) )
return FALSE;
//
m_dwCountPerPeriod = 1;
// 모든 유저들을 대상으로 한 Heartbeat 무결성 검사주기... 말은 좋지만 실상 Heartbeat 오는지 등의 여부검사
DWORD dwCheckPeriod = pINFO->m_dwCheckUserValuationPeriod;
ms_VALUATION_INFO.m_dwCheckUserValuationPeriod = dwCheckPeriod < 1000 ? 1000 : dwCheckPeriod;
// 각 유저별 Heartbeat 패킷 수신시 수행되는 평가로직에 사용되는 인자설정
ms_VALUATION_INFO.m_dwValuationPeriod = pINFO->m_dwValuationPeriod;
ms_VALUATION_INFO.m_dwHeartbeatTick = pINFO->m_dwHeartbeatTick;
ms_VALUATION_INFO.m_bUseArmorKitHeartbeat = pINFO->m_bUseArmorKitHeartbeat;
//
return TRUE;
}
//sSTRICT_HEARTBEAT_UPPERBOUND_RECORD s_pRECORDs[50];
BOOL PROCESS_HEARTBEAT_VALUATION::DoInit()
{
m_dwStatus = this->FIRST;
m_dwAssuranceTime[this->CHECK_FIXER] = 0;
m_dwAssuranceTime[this->ADD_FIXER] = 0;
DWORD& dwMaxRound = ms_RECORD_INFO.dwMaxRound;
dwMaxRound = (DWORD)(ms_VALUATION_INFO.m_dwValuationPeriod / ms_VALUATION_INFO.m_dwHeartbeatTick);
dwMaxRound += (DWORD)((ms_VALUATION_INFO.m_dwValuationPeriod % ms_VALUATION_INFO.m_dwHeartbeatTick) ? 1 : 0);
ms_RECORD_INFO.dwMaxRound = dwMaxRound;
ms_RECORD_INFO.pRECORD = new sSTRICT_HEARTBEAT_UPPERBOUND_RECORD[ dwMaxRound ];
memset( ms_RECORD_INFO.pRECORD, 0, sizeof(sSTRICT_HEARTBEAT_UPPERBOUND_RECORD)*dwMaxRound );
//ms_RECORD_INFO.pRECORD = s_pRECORDs;
//memset( ms_RECORD_INFO.pRECORD, 0, sizeof(s_pRECORDs) );
sSTRICT_HEARTBEAT_UPPERBOUND_RECORD* pRECORD = ms_RECORD_INFO.pRECORD;
//DWORD dwSumTick = ms_VALUATION_INFO.m_dwHeartbeatTick;
for( DWORD i=0 ; i<dwMaxRound ; ++i, ++pRECORD )
{
//pRECORD->m_dwFlagTick = dwSumTick;
//pRECORD->m_dwTotalCounts = i+1;
//dwSumTick += ms_VALUATION_INFO.m_dwHeartbeatTick;
pRECORD->m_dwFlagTick = ms_VALUATION_INFO.m_dwHeartbeatTick;
pRECORD->m_dwTotalCounts = i+1;
}
DWORD dwPeriod = ms_VALUATION_INFO.m_dwCheckUserValuationPeriod;
DWORD dwStartTick = GetTickCount();
m_dwTimeout = dwStartTick + dwPeriod;
return TRUE;
}
class CheckValuationHeartbeat
{
DWORD m_dwCurTick;
DWORD m_dwValuationPeriod;
public:
CheckValuationHeartbeat( DWORD dwCurTick, DWORD dwValuationPeriod )
: m_dwCurTick(dwCurTick), m_dwValuationPeriod(dwValuationPeriod) {}
~CheckValuationHeartbeat(){}
void operator() ( UserSession* pUser )
{
User* pCheckUser = (User*)pUser;
HeartbeatChecker& rChecker = pCheckUser->GetHeartbeatChecker();
DWORD& dwLifeTimeout = rChecker.LifeTimeOut();
if( m_dwCurTick < dwLifeTimeout )
return;
DWORD& dwSignaledCount = rChecker.SignaledCount();
if( dwSignaledCount )
{
// 최소한 하나라도 Heartbeat 패킷을 수신받았다.
// 수신 받은 패킷 수는 여기서는 평가대상이 아니다.
dwLifeTimeout += m_dwValuationPeriod;
dwSignaledCount = 0;
}
else
{
// 다음 두 줄은 임시 루틴이다.
dwLifeTimeout += m_dwValuationPeriod;
dwSignaledCount = 0;
//한번도 수신받지 않는 경우다. 이 경우라면 끊어도 무방
// 이 루틴은 클라이언트 정지 상태가 해결되면 제공하기로 한다.
pCheckUser->SetDisconnectCode( RC::RC_DISCONNECT_IRREGULAR_CLIENT_CYCLE_TICK );
pCheckUser->DisconnectUser( TRUE );
SECURELOG( SECURELOG_USERINFO(pCheckUser, eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_HEARTBEAT_DISCONNECT),
_T("[VALUATION ROUTINE] Disconnect by Heartbeat") );
return;
}
// ArmorKit Heartbeat가 구현되었을 경우에는 여기에 구현하기로 한다.
}
};
BOOL PROCESS_HEARTBEAT_VALUATION::DoProcess()
{
// CHANGES: f101229.2L, skip time statistics checker because LMP issues.
return true;
//
#if SUN_CODE_BACKUP
DWORD dwCurTick = GetTickCount();
if( m_dwTimeout > dwCurTick )
return TRUE;
// 가장 마지막에 업데이트 하도록 하자. 처리과정에서 시간이 바뀌는 경우... -_-;;;
// 이 루틴은 그렇게까지 할 필요 없나?
DWORD dwPeriod = ms_VALUATION_INFO.m_dwCheckUserValuationPeriod;
m_dwTimeout = dwCurTick + dwPeriod;
// 처음을 제외한 주기마다 모든 플레이중인 유저들을 대상으로 검사하는 루틴이 요구된다.
// 측정 시점:
// 해당 유저의 클라이언트에 ArmorKit이 동작중인가?
// 해당 유저의 Heartbeat는 수신되고 있는가?
// 기타 등등
DWORD dwHeartbeatTick = PROCESS_HEARTBEAT_VALUATION::GetHeartbeatTick();
DWORD dwValuationPeriod = dwHeartbeatTick * (PROCESS_HEARTBEAT_VALUATION::GetRecordInfo()->dwMaxRound);
CheckValuationHeartbeat checker(dwCurTick, dwValuationPeriod);
UserManager::Instance()->Foreach( checker );
return TRUE;
#endif //SUN_CODE_BACKUP
}
BOOL PROCESS_HEARTBEAT_VALUATION::IsComplete()
{
return (BOOL)(this->LAST == m_dwStatus);
}
BOOL PROCESS_HEARTBEAT_VALUATION::DoRelease()
{
SAFE_DELETE(ms_RECORD_INFO.pRECORD);
return TRUE;
}
VOID PROCESS_HEARTBEAT_VALUATION::OnMsg( sSIG_MSG* pSIG_MSG )
{
__UNUSED(pSIG_MSG);
}