Files
2026-06-01 12:46:52 +02:00

385 lines
13 KiB
C++

#include "LogClient.h"
#include "LogStruct.h"
#include <vector>
#include <network/XSyncStreamConnection.h>
#include <toolkit/ILock.h>
#include <logging/FileLog.h>
#include <toolkit/XThread.h>
#include <toolkit/XEnv.h>
#include <toolkit/XStringUtil.h>
#include <toolkit/XConsole.h>
XCriticalSection g_csLock;
std::vector< XSyncStreamConnection* > g_vConnectionVector;
__declspec( thread ) XSyncStreamConnection* g_pLogServerConnection = NULL;
__declspec( thread ) DWORD g_nLogThreadId = 0;
__declspec( thread ) XSyncStreamConnection* g_pChatLogServerConnection = NULL;
__declspec( thread ) DWORD g_nChatLogThreadId = 0;
volatile bool g_bWriteLog = true;
volatile bool g_bWriteChatLog = false;
static void chat_log_error( XSyncStreamConnection* pConn, const char *szLogError );
XSyncStreamConnection * GetLogServerConnection()
{
char szLogTag[256];
s_sprintf( szLogTag, _countof( szLogTag ), "log.connect_%s", XGetThreadName() );
if( !g_pLogServerConnection )
{
ENV().Set( szLogTag, 0 );
g_csLock.Lock();
g_pLogServerConnection = new XSyncStreamConnection;
g_vConnectionVector.push_back( g_pLogServerConnection );
g_csLock.UnLock();
}
if( !g_pLogServerConnection->IsConnected() )
{
XAddr addr( ENV().GetString( "log.ip", "127.0.0.1" ).c_str(), ENV().GetInt( "log.port", 4516 ) );
if( !g_pLogServerConnection->Connect( addr ) )
{
//_cprint( "cannot connect log server: ip: %s, port: %d\n", addr.GetAddr(), addr.GetPort() );
//FILELOG( "cannot connect log server: ip: %s, port: %d", addr.GetAddr(), addr.GetPort() );
return NULL;
}
ENV().Set( szLogTag, 1 );
g_nLogThreadId = GetCurrentThreadId();
LOG::Log11N4S( LM_SERVER_LOGIN, 0, 0, 0, g_nLogThreadId, 0, 0, 0, 0, 0, 0, 0, "", 0, "", 0, XGetThreadName(), LOG::STR_NTS, ENV().GetString( "log.server_name" ).c_str(), LOG::STR_NTS );
}
return g_pLogServerConnection;
}
XSyncStreamConnection * GetChatLogServerConnection()
{
char szLogTag[256];
s_sprintf( szLogTag, _countof( szLogTag ), "log.chat.connect_%s", XGetThreadName() );
if( !g_pChatLogServerConnection )
{
ENV().Set( szLogTag, 0 );
g_csLock.Lock();
g_pChatLogServerConnection = new XSyncStreamConnection;
g_vConnectionVector.push_back( g_pChatLogServerConnection );
g_csLock.UnLock();
}
if( !g_pChatLogServerConnection->IsConnected() )
{
if( !g_pChatLogServerConnection->Connect( XAddr( ENV().GetString( "log.chat.ip", "127.0.0.1" ).c_str(), ENV().GetInt( "log.chat.port", 4520 ) ) ) )
{
return NULL;
}
ENV().Set( szLogTag, 1 );
g_nChatLogThreadId = GetCurrentThreadId();
char szBuffer[ 1024 ];
memset( szBuffer, 0, sizeof( szBuffer ) );
LS_CHAT * pMsg = new ( szBuffer ) LS_CHAT();
pMsg->id = LM_SERVER_LOGIN;
pMsg->nReceiverAccountID = g_nChatLogThreadId;
pMsg->nReceiverAccountLength = static_cast< unsigned char >( strlen( XGetThreadName() ) );
pMsg->nChatLength = static_cast< unsigned short >( strlen( ENV().GetString( "log.server_name" ).c_str() ) );
pMsg->size += pMsg->nReceiverAccountLength + pMsg->nChatLength;
s_memcpy( pMsg + 1, sizeof( szBuffer ) - sizeof( LS_CHAT ), XGetThreadName(), pMsg->nReceiverAccountLength );
s_memcpy( reinterpret_cast< char * >( pMsg + 1 ) + pMsg->nReceiverAccountLength, sizeof( szBuffer ) - sizeof( LS_CHAT ) - pMsg->nReceiverAccountLength, ENV().GetString( "log.server_name" ).c_str(), pMsg->nChatLength );
if( g_pChatLogServerConnection->Write( pMsg, pMsg->size ) != pMsg->size )
{
chat_log_error( g_pChatLogServerConnection, "DISCONNECTED" );
}
}
return g_pChatLogServerConnection;
}
static void log_error( XSyncStreamConnection* pConn, const char *szLogError )
{
pConn->Close();
//g_bWriteLog = false;
char szLogTag[256];
s_sprintf( szLogTag, _countof( szLogTag ), "log.connect_%s", XGetThreadName() );
std::vector< XSyncStreamConnection* >::iterator it = std::find( g_vConnectionVector.begin(), g_vConnectionVector.end(), pConn );
if( it != g_vConnectionVector.end() )
{
g_vConnectionVector.erase( it );
if( pConn == g_pLogServerConnection )
{
g_pLogServerConnection = NULL;
}
delete pConn;
}
ENV().Set( szLogTag, 0 );
}
static void chat_log_error( XSyncStreamConnection* pConn, const char *szLogError )
{
pConn->Close();
//g_bWriteChatLog = false;
char szLogTag[256];
s_sprintf( szLogTag, _countof( szLogTag ), "log.chat.connect_%s", XGetThreadName() );
std::vector< XSyncStreamConnection* >::iterator it = std::find( g_vConnectionVector.begin(), g_vConnectionVector.end(), pConn );
if( it != g_vConnectionVector.end() )
{
g_vConnectionVector.erase( it );
if( pConn == g_pChatLogServerConnection )
{
g_pChatLogServerConnection = NULL;
}
delete pConn;
}
ENV().Set( szLogTag, 0 );
}
void LOG::Init( const char *szServerName )
{
// ENV().LoadFromFile 함수가 호출된 이후에 호출되는 경우 이와 같이 변수에 값을 초기화해야 파일의 설정이 유지 됨
g_bWriteLog = (ENV().GetInt( "log.working", 1 ) != 0);
g_bWriteChatLog = (ENV().GetInt( "log.chat.working", 0 ) != 0);
ENV().Bind( "log.working", (bool*)&g_bWriteLog );
ENV().Bind( "log.chat.working", (bool*)&g_bWriteChatLog );
ENV().Set( "log.server_name", szServerName );
if( ENV().IsExist( "log.disable" ) ) g_bWriteLog = false;
}
void LOG::DeInit()
{
g_bWriteLog = false;
g_bWriteChatLog = false;
for( std::vector< XSyncStreamConnection* >::iterator it = g_vConnectionVector.begin() ; it != g_vConnectionVector.end() ; ++it )
{
if( (*it)->IsConnected() )
(*it)->Close();
delete (*it);
}
g_vConnectionVector.clear();
}
void LOG::Log11N4S( unsigned short id, const __int64 & n1, const __int64 & n2, const __int64 & n3, const __int64 & n4, const __int64 & n5, const __int64 & n6, const __int64 & n7, const __int64 & n8, const __int64 & n9, const __int64 & n10, const __int64 & n11, const char * szStr1, int len1, const char * szStr2, int len2, const char * szStr3, int len3, const char * szStr4, int len4 )
{
if( !g_bWriteLog ) return;
XSyncStreamConnection* pConn = GetLogServerConnection();
if( !pConn ) return;
LS_11N4S header;
header.thread_id = g_nLogThreadId;
header.id = id;
header.n1 = n1;
header.n2 = n2;
header.n3 = n3;
header.n4 = n4;
header.n5 = n5;
header.n6 = n6;
header.n7 = n7;
header.n8 = n8;
header.n9 = n9;
header.n10 = n10;
header.n11 = n11;
if( szStr1 )
{
if( len1 == LOG::STR_NTS )
{
len1 = (int) strlen( szStr1 );
}
}
else
{
len1 = 0;
}
if( szStr2 )
{
if( len2 == LOG::STR_NTS )
{
len2 = (int) strlen( szStr2 );
}
}
else
{
len2 = 0;
}
if( szStr3 )
{
if( len3 == LOG::STR_NTS )
{
len3 = (int) strlen( szStr3 );
}
}
else
{
len3 = 0;
}
if( szStr4 )
{
if( len4 == LOG::STR_NTS )
{
len4 = (int) strlen( szStr4 );
}
}
else
{
len4 = 0;
}
header.size += (unsigned short)(len1 + len2 + len3 + len4);
header.string_length_1 = (unsigned short)len1;
header.string_length_2 = (unsigned short)len2;
header.string_length_3 = (unsigned short)len3;
header.string_length_4 = (unsigned short)len4;
if( pConn->Write( &header, sizeof(header) ) != sizeof(header) ||
pConn->Write( szStr1, (unsigned short)len1 ) != len1 ||
pConn->Write( szStr2, (unsigned short)len2 ) != len2 ||
pConn->Write( szStr3, (unsigned short)len3 ) != len3 ||
pConn->Write( szStr4, (unsigned short)len4 ) != len4 )
{
log_error( pConn, "DISCONNECTED" );
std::string strLog;
XStringUtil::Format( strLog, "%lu\t%hu\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d\t%I64d",
header.thread_id, header.id, header.n1, header.n2, header.n3, header.n4, header.n5, header.n6, header.n7, header.n8, header.n9, header.n10, header.n11 );
strLog += "\t";
if( header.string_length_1 )
strLog.append( szStr1, header.string_length_1 );
strLog += "\t";
if( header.string_length_2 )
strLog.append( szStr2, header.string_length_2 );
strLog += "\t";
if( header.string_length_3 )
strLog.append( szStr3, header.string_length_3 );
strLog += "\t";
if( header.string_length_4 )
strLog.append( szStr4, header.string_length_4 );
FileLogHandler::GetFileLogHandler()->LogStringEx( NULL, "LostLogs", strLog.c_str() );
}
}
void LOG::LogChat( const int nSenderAccountID, const int nSenderCharacterID, const unsigned char nChatType, const int nSenderPosX, const int nSenderPosY,
const int nReceiverAccountID, const int nReceiverCharacterID,
const char * pszSenderAccount, const int nSenderAccountLength, const char * pszSenderCharacter, const int nSenderCharacterLength,
const char * pszReceiverAccount, const int nReceiverAccountLength, const char * pszReceiverCharacter, const int nReceiverCharacterLength,
const char * pszChat, const unsigned short nChatLength )
{
if( !g_bWriteChatLog ) return;
XSyncStreamConnection* pConn = GetChatLogServerConnection();
if( !pConn ) return;
char szBuffer[ 16384 ];
memset( szBuffer, 0, sizeof( szBuffer ) );
LS_CHAT * pMsg = new ( szBuffer ) LS_CHAT();
pMsg->thread_id = g_nChatLogThreadId;
pMsg->id = 0; // 채팅 로그만을 나타내므로 이 함수에서는 사용되지 않음(서버 로그인 메시지만 별도로 사용 됨)
pMsg->nSenderAccountID = nSenderAccountID;
pMsg->nSenderCharacterID = nSenderCharacterID;
pMsg->nChatType = nChatType;
pMsg->nSenderPosX = nSenderPosX;
pMsg->nSenderPosY = nSenderPosY;
pMsg->nReceiverAccountID = nReceiverAccountID;
pMsg->nReceiverCharacterID = nReceiverCharacterID;
if( nSenderAccountLength == STR_NTS )
pMsg->nSenderAccountLength = static_cast< unsigned char >( strlen( pszSenderAccount ) );
else
pMsg->nSenderAccountLength = static_cast< unsigned char >( nSenderAccountLength );
if( nSenderCharacterLength == STR_NTS )
pMsg->nSenderCharacterLength = static_cast< unsigned char >( strlen( pszSenderCharacter ) );
else
pMsg->nSenderCharacterLength = static_cast< unsigned char >( nSenderCharacterLength );
if( nReceiverAccountLength == STR_NTS )
pMsg->nReceiverAccountLength = static_cast< unsigned char >( strlen( pszReceiverAccount ) );
else
pMsg->nReceiverAccountLength = static_cast< unsigned char >( nReceiverAccountLength );
if( nReceiverCharacterLength == STR_NTS )
pMsg->nReceiverCharacterLength = static_cast< unsigned char >( strlen( pszReceiverCharacter ) );
else
pMsg->nReceiverCharacterLength = static_cast< unsigned char >( nReceiverCharacterLength );
if( nChatLength == STR_NTS )
pMsg->nChatLength = static_cast< unsigned short >( strlen( pszChat ) );
else
pMsg->nChatLength = nChatLength;
pMsg->size += pMsg->nSenderAccountLength + pMsg->nSenderCharacterLength + pMsg->nReceiverAccountLength + pMsg->nReceiverCharacterLength + pMsg->nChatLength;
char * pszStringBuffer = reinterpret_cast< char * >( pMsg + 1 );
s_memcpy( pszStringBuffer, sizeof( szBuffer ) - sizeof( LS_CHAT ), pszSenderAccount, pMsg->nSenderAccountLength );
pszStringBuffer += pMsg->nSenderAccountLength;
s_memcpy( pszStringBuffer, sizeof( szBuffer ) - sizeof( LS_CHAT ) - pMsg->nSenderAccountLength, pszSenderCharacter, pMsg->nSenderCharacterLength );
pszStringBuffer += pMsg->nSenderCharacterLength;
s_memcpy( pszStringBuffer, sizeof( szBuffer ) - sizeof( LS_CHAT ) - pMsg->nSenderAccountLength - pMsg->nSenderCharacterLength, pszReceiverAccount, pMsg->nReceiverAccountLength );
pszStringBuffer += pMsg->nReceiverAccountLength;
s_memcpy( pszStringBuffer, sizeof( szBuffer ) - sizeof( LS_CHAT ) - pMsg->nSenderAccountLength - pMsg->nSenderCharacterLength - pMsg->nReceiverAccountLength, pszReceiverCharacter, pMsg->nReceiverCharacterLength );
pszStringBuffer += pMsg->nReceiverCharacterLength;
s_memcpy( pszStringBuffer, sizeof( szBuffer ) - sizeof( LS_CHAT ) - pMsg->nSenderAccountLength - pMsg->nSenderCharacterLength - pMsg->nReceiverAccountLength - pMsg->nReceiverCharacterLength, pszChat, pMsg->nChatLength );
if( pConn->Write( pMsg, pMsg->size ) != pMsg->size )
{
chat_log_error( pConn, "DISCONNECTED" );
std::string strLog;
XStringUtil::Format( strLog, "%lu\t%d\t%d\t%u\t%d\t%d\t%d\t%d",
pMsg->thread_id, pMsg->nSenderAccountID, pMsg->nSenderCharacterID, (unsigned int)pMsg->nChatType, pMsg->nSenderPosX, pMsg->nSenderPosY, pMsg->nReceiverAccountID, pMsg->nReceiverCharacterID );
strLog += "\t";
if( pMsg->nSenderAccountLength )
strLog.append( pszSenderAccount, pMsg->nSenderAccountLength );
strLog += "\t";
if( pMsg->nSenderCharacterLength )
strLog.append( pszSenderCharacter, pMsg->nSenderCharacterLength );
strLog += "\t";
if( pMsg->nReceiverAccountLength )
strLog.append( pszReceiverAccount, pMsg->nReceiverAccountLength );
strLog += "\t";
if( pMsg->nReceiverCharacterLength )
strLog.append( pszReceiverCharacter, pMsg->nReceiverCharacterLength );
strLog += "\t";
if( pMsg->nChatLength )
strLog.append( pszChat, pMsg->nChatLength );
FileLogHandler::GetFileLogHandler()->LogStringEx( NULL, "LostChatLogs", strLog.c_str() );
}
}