Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
486 lines
14 KiB
C++
486 lines
14 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "MonitoringTool.h"
|
|
#include "MonitoringToolDlg.h"
|
|
#include "ChatServerEventHandler.h"
|
|
#include "MonitoringToolSetup.h"
|
|
#include "MonitoringToolLog.h"
|
|
#include "WhisperDlg.h"
|
|
#include "ChattingPage.h"
|
|
#include "LoginDlg.h"
|
|
#include "GlobalFunc.h"
|
|
|
|
#include <Log/ServerLog.h>
|
|
#include <Stream/Buffer/Buffer.h>
|
|
#include <Utility/Setup/ServerSetup.h>
|
|
#include <Network/Packet/WrapPacket.h>
|
|
#include <Network/Packet/ChatToolPacketCmd.h>
|
|
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
|
|
#include <mmsystem.h>
|
|
|
|
const char* szChatSection = _T("CHAT_SERVER_CONNECTION");
|
|
const unsigned int MAX_CHAT = CMonitoringToolSetup::GetInstance().GetInt(szChatSection, _T("CHAT_SERVER_NUM"));
|
|
|
|
|
|
ClientNet::CChatServerEventHandler::CChatServerEventHandler(unsigned int nServerGroup)
|
|
: m_nServerGroup(nServerGroup), m_dwLastPingRecvTime(0)
|
|
{
|
|
}
|
|
|
|
bool ClientNet::CChatServerEventHandler::Connect()
|
|
{
|
|
char szKey[MAX_PATH];
|
|
unsigned int nServerGroup;
|
|
const char* szIP;
|
|
|
|
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
|
|
|
|
for(unsigned int nIndex = 0; nIndex < MAX_CHAT; ++nIndex)
|
|
{
|
|
_snprintf(szKey, MAX_PATH, "CHAT_SERVER_IP_%02d", nIndex);
|
|
szIP = Setup.GetString(szChatSection, szKey);
|
|
|
|
_snprintf(szKey, MAX_PATH, "CHAT_SERVER_INDEX_%02d", nIndex);
|
|
nServerGroup = Setup.GetInt(szChatSection, szKey);
|
|
|
|
ClientNet::CClientEventHandlerMgr& eventHandlerMgr = theApp.GetEventHandlerMgr();
|
|
ClientNet::CChatServerEventHandler* lpEventHandler = new ClientNet::CChatServerEventHandler(nServerGroup);
|
|
|
|
if (!eventHandlerMgr.Connect(
|
|
INET_Addr(szIP, CServerSetup::ChatServerMonitoringToolListen), lpEventHandler))
|
|
{
|
|
delete lpEventHandler;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int ClientNet::CChatServerEventHandler::OnOpen(int iErrorCode)
|
|
{
|
|
if(0 == iErrorCode)
|
|
{
|
|
theApp.RegisterChatHandler(m_nServerGroup, this);
|
|
|
|
INET_Addr& addr = GetPeerAddress();
|
|
|
|
INFLOG3(g_Log, _T("Connect Session (ChatServer) : DP:0x%p, %s:%d"),
|
|
this, addr.get_addr_string(), addr.get_port_in());
|
|
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_031"));
|
|
}
|
|
else
|
|
{
|
|
ERRLOG1(g_Log, _T("Connect Session Failed (ChatServer): Err- %d"), iErrorCode);
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_032"));
|
|
}
|
|
|
|
m_dwLastPingRecvTime = timeGetTime();
|
|
return 0;
|
|
}
|
|
|
|
int ClientNet::CChatServerEventHandler::OnClose()
|
|
{
|
|
theApp.RemoveChatHandler(m_nServerGroup, this);
|
|
|
|
INFLOG1(g_Log, _T("Disconnect Session (ChatServer): DP:0x%p"), this);
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_033"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ClientNet::CChatServerEventHandler::OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr)
|
|
{
|
|
bool bResult = false;
|
|
|
|
switch(lpPktBase->GetCmd())
|
|
{
|
|
case ChatToolCMD::Authorize: RecvAuthAck(lpPktBase, peerAddr); break;
|
|
case ChatToolCMD::ChatSend: RecvChatData(lpPktBase, peerAddr); break;
|
|
case ChatToolCMD::ChatPing: RecvChatPing(lpPktBase, peerAddr); break;
|
|
case ChatToolCMD::ChatRequest: RecvChatRequest(lpPktBase, peerAddr); break;
|
|
default: break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// \brief 채팅서버로 인증 패킷 전송
|
|
/// \param szUserID 로그인 계정명
|
|
/// \param szPass 로그인 패스워드
|
|
/// \return 패킷 전송 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::SendAuthPkt(char* szUserID, char* szPass)
|
|
{
|
|
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
|
|
char szKey[MAX_PATH];
|
|
|
|
for(unsigned int nIndex = 0; nIndex < MAX_CHAT; ++nIndex)
|
|
{
|
|
_snprintf(szKey, MAX_PATH, "CHAT_SERVER_INDEX_%02d", nIndex);
|
|
|
|
CChatServerEventHandler* lpHandler =
|
|
theApp.GetChatServerHandler(Setup.GetInt(szChatSection, szKey, 100));
|
|
|
|
if(0 != lpHandler)
|
|
{
|
|
CNetworkMsgBlock* lpMsg =
|
|
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
|
|
sizeof(ChatToolPkt::Authorize), INET_Addr());
|
|
|
|
if(0 != lpMsg)
|
|
{
|
|
ChatToolPkt::Authorize* lpAuthorize =
|
|
reinterpret_cast<ChatToolPkt::Authorize*>(lpMsg->wr_ptr());
|
|
|
|
_snprintf(lpAuthorize->m_szUserID, ChatToolPkt::MAX_USER_ID, szUserID);
|
|
lpAuthorize->m_szUserID[ChatToolPkt::MAX_USER_ID - 1] = 0;
|
|
|
|
_snprintf(lpAuthorize->m_szPassword, ChatToolPkt::MAX_PASSWORD, szPass);
|
|
lpAuthorize->m_szPassword[ChatToolPkt::MAX_PASSWORD - 1] = 0;
|
|
|
|
if(lpMsg->WrapCrypt(sizeof(ChatToolPkt::Authorize), ChatToolCMD::Authorize, 0))
|
|
{
|
|
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
|
|
}
|
|
else
|
|
{
|
|
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
|
|
}
|
|
}
|
|
Sleep(1000);
|
|
}
|
|
else
|
|
{
|
|
ERRLOG1(g_Log, "Failed get session(ChatServer): Group- %d", Setup.GetInt(szChatSection, szKey, 100));
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_030"));
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// \brief 인증 패킷 Ack 처리
|
|
/// \return 패킷 전송 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::RecvAuthAck(PktBase* lpPktBase, INET_Addr& peerAddr)
|
|
{
|
|
CLoginDlg* lpLoginDlg = static_cast<CLoginDlg*>(theApp.GetRegisteredWindow(IDD_LOGINDLG));
|
|
if(NULL != lpLoginDlg)
|
|
{
|
|
ChatToolPkt::Authorize* lpAuthorize = static_cast<ChatToolPkt::Authorize*>(lpPktBase);
|
|
|
|
if(1 == lpAuthorize->m_cResult)
|
|
{
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_034"));
|
|
theApp.SetAuthorized(true);
|
|
|
|
CString strLoginedName;
|
|
strLoginedName.Format("%s", lpAuthorize->m_szUserID);
|
|
theApp.SetLoginedName(strLoginedName);
|
|
|
|
lpLoginDlg->OnOK();
|
|
|
|
CChattingPage* lpChatPage =
|
|
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
|
|
|
|
if (NULL != lpChatPage)
|
|
{
|
|
lpChatPage->SetLoginedNameEdit(strLoginedName);
|
|
lpChatPage->CheckDlgButton(IDC_GMLOGINED_CHK, BST_CHECKED);
|
|
}
|
|
|
|
unsigned char szOption[ChatToolPkt::ChatOption::MAX_OPTION];
|
|
std::fill_n(szOption, int(ChatToolPkt::ChatOption::MAX_OPTION), 1);
|
|
|
|
SendChatOptPkt(m_nServerGroup, szOption, ChatToolPkt::ChatOption::MAX_OPTION);
|
|
}
|
|
else
|
|
{
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_035"));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// \brief 채팅 메세지 보내기(외치기, 귓속말등)
|
|
/// \param nServerGroup 전송할 서버군
|
|
/// \param cChatType 전송할 메세지의 타입
|
|
/// \param cTargetType 메세지를 받을 대상 타입
|
|
/// \param dwTargetUID 메세지를 받을 대상의 UID
|
|
/// \param dwMessageID 메세지의 고유 ID (Ack를 받을때 활용)
|
|
/// \param strGMName 메세지를 보내는 GM의 로그인 계정명
|
|
/// \param strTargetName 메세지를 받을 대상의 계정명 또는 캐릭터명
|
|
/// \param strMsg 메세지 내용
|
|
/// \return 패킷 전송 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::SendChatReqPkt(unsigned int nServerGroup,
|
|
unsigned char cChatType,
|
|
unsigned char cTargetType,
|
|
unsigned long dwTargetUID,
|
|
unsigned long dwMessageID,
|
|
const CString& strGMName,
|
|
const CString& strTargetName,
|
|
const CString& strMsg)
|
|
{
|
|
if (!theApp.IsAuthorized())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CClientEventHandler* lpHandler = theApp.GetChatServerHandler(nServerGroup);
|
|
if (0 == lpHandler)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
unsigned char cMsgLen = static_cast<unsigned char>(strMsg.GetLength());
|
|
|
|
CNetworkMsgBlock* lpMsg =
|
|
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
|
|
sizeof(ChatToolPkt::ChatRequest) + cMsgLen + 1, INET_Addr());
|
|
|
|
if(0 != lpMsg)
|
|
{
|
|
ChatToolPkt::ChatRequest* lpChatReq =
|
|
reinterpret_cast<ChatToolPkt::ChatRequest*>(lpMsg->wr_ptr());
|
|
|
|
memset(lpChatReq, 0, sizeof(ChatToolPkt::ChatRequest));
|
|
|
|
lpChatReq->m_dwUID = dwTargetUID; // 대상 캐릭터 UID (TargetName이 없을 경우 사용)
|
|
lpChatReq->m_cTargetType = cTargetType; // UID / CharName / AccountName 중 하나
|
|
lpChatReq->m_dwMessageID = dwMessageID;
|
|
|
|
lpChatReq->m_cChatType = cChatType;
|
|
lpChatReq->m_cChatMsgLen = cMsgLen + 1; // +1 : 널 문자 사이즈
|
|
|
|
_snprintf(lpChatReq->m_szAdminName, ChatToolPkt::MAX_CHAR_NAME - 1, "%s", strGMName);
|
|
lpChatReq->m_szAdminName[ChatToolPkt::MAX_CHAR_NAME - 1] = 0;
|
|
|
|
_snprintf(lpChatReq->m_szTargetName, ChatToolPkt::MAX_CHAR_NAME - 1, "%s", strTargetName);
|
|
lpChatReq->m_szTargetName[ChatToolPkt::MAX_CHAR_NAME - 1] = 0;
|
|
|
|
memcpy(reinterpret_cast<char*>(lpChatReq + 1), strMsg, cMsgLen);
|
|
*(reinterpret_cast<char*>(lpChatReq + 1) + cMsgLen) = 0;
|
|
|
|
if (lpMsg->WrapCrypt(sizeof(ChatToolPkt::ChatRequest) + lpChatReq->m_cChatMsgLen,
|
|
ChatToolCMD::ChatRequest, 0))
|
|
{
|
|
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
|
|
return true;
|
|
}
|
|
|
|
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// \brief 채팅 관련 데이터 처리
|
|
/// \return 패킷 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::RecvChatData(PktBase* lpPktBase, INET_Addr& peerAddr)
|
|
{
|
|
ChatToolPkt::ChatDataSend* lpChatDataSend =
|
|
reinterpret_cast<ChatToolPkt::ChatDataSend*>(lpPktBase);
|
|
|
|
CChattingPage* lpPage =
|
|
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
|
|
|
|
CFilterUserDialog* lpFilter =
|
|
static_cast<CFilterUserDialog*>(theApp.GetRegisteredWindow(IDD_FILTERDIALOG));
|
|
|
|
CGMReportDialog* lpGMReport =
|
|
static_cast<CGMReportDialog*>(theApp.GetRegisteredWindow(IDD_GMREPORTDIALOG));
|
|
|
|
if (NULL != lpPage)
|
|
{
|
|
if(PktChat::GMREPORT == lpChatDataSend->m_cChatType)
|
|
{
|
|
if(lpGMReport)
|
|
{
|
|
lpGMReport->AddMessage(lpChatDataSend);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 여기서 필터링
|
|
if(lpFilter)
|
|
{
|
|
lpFilter->CheckMessage(lpChatDataSend);
|
|
}
|
|
|
|
if (PktChat::WHISPER == lpChatDataSend->m_cChatType)
|
|
{
|
|
if ((0 == theApp.GetLoginedName().Compare(lpChatDataSend->m_szTargetName))
|
|
|| (0 == theApp.GetLoginedName().Compare(lpChatDataSend->m_szSenderName)))
|
|
{
|
|
CWhisperDlg* lpWhisperDlg = lpPage->GetWhisperDlg(lpChatDataSend->m_dwUID);
|
|
|
|
if (NULL != lpWhisperDlg)
|
|
{
|
|
lpWhisperDlg->ParseChatData(lpChatDataSend);
|
|
}
|
|
else
|
|
{
|
|
bool bGMSender = false;
|
|
// sender 유저가 GM이면
|
|
if(0 == theApp.GetLoginedName().Compare(lpChatDataSend->m_szSenderName))
|
|
bGMSender = true;
|
|
|
|
// 두번째 매개변수는 유저가 운영자에게 말을 거는 경우 true
|
|
lpPage->ParseChatData(lpChatDataSend, true, bGMSender);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpPage->ParseChatData(lpChatDataSend);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpPage->ParseChatData(lpChatDataSend);
|
|
}
|
|
}
|
|
}
|
|
|
|
CMonitoringToolLog::GetInstance().WriteChatLog(lpChatDataSend);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// \brief 모니터링 할 채팅 타입 보내기
|
|
/// \param nServerGroup 패킷을 전송할 서버군
|
|
/// \param szOption 모니터링할 옵션
|
|
/// \param cOptionNum 모니터링 하고자 선택한 타입의 개수
|
|
/// \return 패킷 전송 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::SendChatOptPkt(unsigned int nServerGroup,
|
|
unsigned char* szOption, unsigned char cOptionNum)
|
|
{
|
|
if (true != theApp.IsAuthorized())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
cOptionNum = std::min(cOptionNum, unsigned char(ChatToolPkt::ChatOption::MAX_OPTION));
|
|
|
|
CChatServerEventHandler* lpHandler = theApp.GetChatServerHandler(nServerGroup);
|
|
|
|
if(0 == lpHandler)
|
|
{
|
|
ERRLOG1(g_Log, "Failed get session(ChatServer): Group- %u", nServerGroup);
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_030"));
|
|
|
|
return false;
|
|
}
|
|
|
|
CNetworkMsgBlock* lpMsg =
|
|
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
|
|
sizeof(ChatToolPkt::ChatOption), INET_Addr());
|
|
|
|
if(0 != lpMsg)
|
|
{
|
|
ChatToolPkt::ChatOption* lpOption =
|
|
reinterpret_cast<ChatToolPkt::ChatOption*>(lpMsg->wr_ptr());
|
|
|
|
memcpy(lpOption->m_cChatOption, szOption, sizeof(unsigned char) * cOptionNum);
|
|
|
|
if(lpMsg->WrapCrypt(sizeof(ChatToolPkt::ChatOption), ChatToolCMD::ChangeOption, 0))
|
|
{
|
|
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
|
|
return true;
|
|
}
|
|
|
|
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// \brief 운영자의 접속 상태 설정
|
|
/// \param nServerGroup 상태를 다시 설정할 서버군
|
|
/// \param strAdminName 상태를 설정할 운영자의 계정명
|
|
/// \param cStatus 로그인 또는 로그아웃 상태
|
|
/// \return 패킷 전송 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::SendAdminStatus(unsigned int nServerGroup,
|
|
const CString& strAdminName, unsigned char cStatus)
|
|
{
|
|
if(!theApp.IsAuthorized())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CChatServerEventHandler* lpHandler = theApp.GetChatServerHandler(nServerGroup);
|
|
|
|
if(0 == lpHandler)
|
|
{
|
|
ERRLOG1(g_Log, "Failed get session(ChatServer): Group- %u", nServerGroup);
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_030"));
|
|
|
|
return false;
|
|
}
|
|
|
|
CNetworkMsgBlock* lpMsg =
|
|
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(sizeof(ChatToolPkt::ChatAdminStatus), INET_Addr());
|
|
|
|
if(0 != lpMsg)
|
|
{
|
|
ChatToolPkt::ChatAdminStatus* lpAdminStatus =
|
|
reinterpret_cast<ChatToolPkt::ChatAdminStatus*>(lpMsg->wr_ptr());
|
|
|
|
strncpy(lpAdminStatus->m_szChatAdminName, strAdminName, ChatToolPkt::MAX_USER_ID);
|
|
lpAdminStatus->m_cChangeStatus = cStatus;
|
|
|
|
if(lpMsg->WrapCrypt(sizeof(ChatToolPkt::ChatAdminStatus), ChatToolCMD::ChatAdminStatus, 0))
|
|
{
|
|
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
|
|
return true;
|
|
}
|
|
|
|
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// \brief 핑 패킷을 마지막으로 받은 시간 갱신
|
|
/// \return 패킷 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::RecvChatPing(PktBase* lpPktBase, INET_Addr& peerAddr)
|
|
{
|
|
m_dwLastPingRecvTime = timeGetTime();
|
|
return true;
|
|
}
|
|
|
|
/// \brief 채팅 요청에 대한 Ack처리
|
|
/// \return 패킷 처리 성공 여부
|
|
bool ClientNet::CChatServerEventHandler::RecvChatRequest(PktBase* lpPktBase, INET_Addr& peerAddr)
|
|
{
|
|
ChatToolPkt::ChatRequest* lpChatRequest =
|
|
reinterpret_cast<ChatToolPkt::ChatRequest*>(lpPktBase);
|
|
|
|
switch (lpChatRequest->GetError())
|
|
{
|
|
case 0:
|
|
{
|
|
// 메세지 ID에 매칭되는 창이 띄워져있다면 Ack로 받은 UID를 셋팅해준다.
|
|
CChattingPage* lpPage =
|
|
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
|
|
|
|
CWhisperDlg* lpDlg = lpPage->GetAccountDlg(lpChatRequest->m_dwMessageID);
|
|
|
|
if ((NULL != lpDlg) && (0 == lpDlg->GetKeyUID()))
|
|
{
|
|
lpDlg->SetKeyUID(lpChatRequest->m_dwUID, lpChatRequest->m_dwCID);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case ChatToolPkt::ChatRequest::PACKET_ERROR:
|
|
// 패킷에 에러가 있는 경우. 어쨌건 Ack는 왔음이요...
|
|
break;
|
|
|
|
case ChatToolPkt::ChatRequest::NONE_CHARACTER:
|
|
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_043"));
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
} |