Restructure repository to include all source folders
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>
This commit is contained in:
400
Server/ManageTool/ManageClient/ManageClient.cpp
Normal file
400
Server/ManageTool/ManageClient/ManageClient.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
// ManageClient.cpp : Defines the entry point for the application.
|
||||
//
|
||||
#include "stdafx.h"
|
||||
#include "resource.h"
|
||||
#include "ManageClient.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <Thread/Lock.h> // CNamedMutex
|
||||
#include <Log/ServerLog.h>
|
||||
#include <Utility/Debug/ExceptionReport.h> // g_CExceptionReport
|
||||
#include <Utility/Time/Pulse/Pulse.h>
|
||||
#include <Utility/Setup/ServerSetup.h>
|
||||
|
||||
#include <Network/Session/CreatePolicy.h>
|
||||
#include <Network/Session/Session.h>
|
||||
#include <Network/IOCP/IOCPNet.h>
|
||||
|
||||
#include <Network/Dispatch/ManageClient/ManageClientDispatch.h>
|
||||
|
||||
#include <Network/Packet/ManagePacketCmd.h>
|
||||
#include <Network/Dispatch/SendManagePacket.h>
|
||||
|
||||
#include <Setup/SetupClient.h>
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
CNamedMutex Mutex("ManageClient", TRUE);
|
||||
|
||||
if(GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
ERRLOG0(g_Log, "ManageClient already server operating now. please shutdown and restart");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long dwExceptionFeatures = CExceptionReport::CATCH_EXCEPTION |
|
||||
CExceptionReport::USE_MINIDUMP | CExceptionReport::USE_REPORT;
|
||||
|
||||
CExceptionReport::GetInstance().Enable(dwExceptionFeatures);
|
||||
|
||||
CManageClient& ManageClient = CManageClient::GetInstance();
|
||||
|
||||
if(ManageClient.Initialize(hInstance,
|
||||
CServerSetup::GetInstance().GetManageClientWindowName(),
|
||||
lpCmdLine, IDI_MANAGECLIENT, IDC_MANAGECLIENT))
|
||||
{
|
||||
ManageClient.ProcessMessage();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
class CManageClientProcessThread : public CProcessThread
|
||||
{
|
||||
public:
|
||||
|
||||
enum Const
|
||||
{
|
||||
PROCESS_TPP = 200, // 200ms(0.2초) 에 1틱.
|
||||
CONNECT_CHECK = 10 * (1000 / PROCESS_TPP), // 10초마다 연결 체크
|
||||
PRINT_CHECK = 2 * (1000 / PROCESS_TPP), // 2초마다 콘솔 출력
|
||||
PROCESS_CHECK = 3 * (1000 / PROCESS_TPP) // 5초마다 처리 갱신
|
||||
};
|
||||
|
||||
CManageClientProcessThread(CManageClient& ManageClient)
|
||||
: CProcessThread(ManageClient, PROCESS_TPP),
|
||||
m_ManageClient(ManageClient)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual void Cleanup(CPulse& Pulse)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void InternalRun(CPulse& Pulse)
|
||||
{
|
||||
unsigned long dwCurrentPulse = Pulse.GetCurrentPulse();
|
||||
|
||||
if(0 == (dwCurrentPulse % CONNECT_CHECK))
|
||||
{
|
||||
m_ManageClient.CheckConnectionAndReconnect();
|
||||
}
|
||||
|
||||
if(0 == (dwCurrentPulse % PRINT_CHECK))
|
||||
{
|
||||
m_ManageClient.PrintConnectionStatus();
|
||||
}
|
||||
|
||||
if(0 == (dwCurrentPulse % PROCESS_CHECK))
|
||||
{
|
||||
GET_SINGLE_DISPATCH(lpManageClientDispatch,
|
||||
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
|
||||
|
||||
if(0 != lpManageClientDispatch)
|
||||
{
|
||||
lpManageClientDispatch->CheckProcessStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CManageClient& m_ManageClient;
|
||||
};
|
||||
|
||||
|
||||
CManageClient& CManageClient::GetInstance()
|
||||
{
|
||||
static CManageClient manageClient;
|
||||
return manageClient;
|
||||
}
|
||||
|
||||
|
||||
CManageClient::CManageClient()
|
||||
: m_lpClientSessionPolicy(SessionPolicy::CreateTCPPolicy<CManageClientDispatch>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CManageClient::~CManageClient()
|
||||
{
|
||||
if(0 != m_lpClientSessionPolicy)
|
||||
{
|
||||
m_lpClientSessionPolicy->Release();
|
||||
m_lpClientSessionPolicy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CManageClient::CheckConnectionAndReconnect()
|
||||
{
|
||||
bool bReconnect = false;
|
||||
|
||||
GET_SINGLE_DISPATCH(lpManageClientDispatch,
|
||||
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
|
||||
|
||||
if(0 == lpManageClientDispatch)
|
||||
{
|
||||
// 연결이 안 되어 있으면 연결을 테스트함.
|
||||
|
||||
CIOCPNet* lpIOCP = GetIOCPNet();
|
||||
|
||||
if(0 != lpIOCP)
|
||||
{
|
||||
ConnectToManageServer();
|
||||
}
|
||||
}
|
||||
else if(lpManageClientDispatch->DoPatchNow())
|
||||
{
|
||||
// 패치를 전부 받고, 패치하기 직전이다. 패치 프로세스를 시작한다.
|
||||
DoSelfPatchProcess(*lpManageClientDispatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CManageClient::ConnectToManageServer()
|
||||
{
|
||||
CIOCPNet* lpIOCP = GetIOCPNet();
|
||||
|
||||
if(0 != lpIOCP && 0 != m_lpClientSessionPolicy)
|
||||
{
|
||||
INET_Addr& manageServerAddr = ManageSetup::ClientSetup::GetInstance().GetManageServerAddr();
|
||||
|
||||
if(!lpIOCP->Connect(m_lpClientSessionPolicy, manageServerAddr.get_addr_string(),
|
||||
manageServerAddr.get_port_in()))
|
||||
{
|
||||
DETLOG3(g_Log, "this:0x%p/IP:%15s/Port/%02d/ManageServer connect failed.",
|
||||
this, manageServerAddr.get_addr_string(), manageServerAddr.get_port_in());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CManageClient::DoSelfPatchProcess(CManageClientDispatch& ClientDispatch)
|
||||
{
|
||||
/*
|
||||
// temporary .bat file
|
||||
static const TCHAR szTempBatContent[] =
|
||||
_T(":Repeat\r\n")
|
||||
_T("del \"%s\"\r\n") // execute file name(full path)
|
||||
_T("if exist \"%s\" goto Repeat\r\n") // execute file name(full path)
|
||||
_T(":Repeat2\r\n")
|
||||
_T("rename %s %s\r\n") // first - temp file name(full path), second - execute file name only
|
||||
_T("if not exist \"%s\" goto Repeat\r\n") // execute file name(full path)
|
||||
_T("cd %s\r\n") // execute file path(full path)
|
||||
_T("%s\r\n"); // execute file name(full path)
|
||||
|
||||
static const TCHAR szTempBatName[] = "_manageclient_selfpatch.bat" ;
|
||||
|
||||
TCHAR szFullPathModuleName[MAX_PATH]; // absolute path of calling .exe file
|
||||
TCHAR szModulePath[MAX_PATH]; // Module path
|
||||
TCHAR szModuleFileName[MAX_PATH]; // fileName
|
||||
TCHAR szModuleExtension[NAX_PATH]; // extension
|
||||
TCHAR szTempBatPathName[MAX_PATH]; // absolute path of temporary .bat file
|
||||
|
||||
memset(szFullPathModuleName, 0, sizeof(TCHAR) * MAX_PATH);
|
||||
memset(szModulePath, 0, sizeof(TCHAR) * MAX_PATH);
|
||||
memset(szTempBatPathName, 0, sizeof(TCHAR) * MAX_PATH);
|
||||
|
||||
bool bFailedGetName = true;
|
||||
|
||||
unsigned long dwPathLength = GetTempPath(MAX_PATH, szTempBatPathName);
|
||||
if(0 < dwPathLength)
|
||||
{
|
||||
if(0 < _sntprintf(szTempBatPathName + dwPathLength, MAX_PATH - dwPathLength - 1,
|
||||
"%s", szTempBatName))
|
||||
{
|
||||
szTempBatPathName[MAX_PATH - 1] = 0;
|
||||
bFailedGetName = false;
|
||||
}
|
||||
}
|
||||
|
||||
const TCHAR* szErrorMessage = 0;
|
||||
|
||||
if(bFailedGetName)
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/Failed get tempbat file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
dwPathLength = GetModuleFileName(NULL, szFullPathModuleName, MAX_PATH - 1);
|
||||
szFullPathModuleName[MAX_PATH - 1] = 0;
|
||||
|
||||
_tsplitpath(szFullPathModuleName, 0, 0, szModuleFileName, szModuleExtension);
|
||||
|
||||
_sntprintf(szModuleFileName, szModuleExtension
|
||||
|
||||
szModuleFileName = _tcsrchr(szFullPathModuleName, _T('\\'));
|
||||
if(0 == szModuleFileName)
|
||||
{
|
||||
szModuleFileName = _tcsrchr(szFullPathModuleName, _T('/'));
|
||||
}
|
||||
|
||||
if(0 == szModuleFileName || 0 == dwPathLength)
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/Failed get module name.");
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(szModulePath, szFullPathModuleName,
|
||||
szModuleFileName - szFullPathModuleName);
|
||||
|
||||
szModulePath[szModuleFileName - szFullPathModuleName] = _T('\0');
|
||||
++szModuleFileName;
|
||||
|
||||
HANDLE hBatFile = CreateFile(szTempBatPathName, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
|
||||
|
||||
if (INVALID_HANDLE_VALUE == hBatFile)
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/Temp bat file create failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwLength = 0;
|
||||
|
||||
unsigned long dwTempBatContentLen = _tcslen(szTempBatContent);
|
||||
unsigned long dwFullPathModuleNameLen = _tcslen(szFullPathModuleName);
|
||||
unsigned long dwTempPathFileLen = _tcslen(ClientDispatch.GetTempPatchFileName());
|
||||
unsigned long dwModuleFileNameLen = _tcslen(szModuleFileName);
|
||||
unsigned long dwModulePathLen = _tcslen(szModulePath);
|
||||
|
||||
TCHAR* szBatBuffer = new TCHAR[dwTempBatContentLen +
|
||||
dwFullPathModuleNameLen * 4 +
|
||||
dwTempPathFileLen +
|
||||
dwModuleFileNameLen +
|
||||
dwModulePathLen +
|
||||
MAX_PATH];
|
||||
|
||||
int nLength = _sntprintf(szBatBuffer, MAX_PATH * 10 - 1, szTempBatContent,
|
||||
szFullPathModuleName, // 지울 파일 이름
|
||||
szFullPathModuleName, // 파일 존재 여부 체크
|
||||
ClientDispatch.GetTempPatchFileName(), // 임시 파일 이름
|
||||
szModuleFileName, // 바뀔 이름
|
||||
szFullPathModuleName, // 바뀐 이름
|
||||
szModulePath, // 경로 이동
|
||||
szFullPathModuleName); // 실행
|
||||
|
||||
if(0 < nLength)
|
||||
{
|
||||
if(!WriteFile(hBatFile, szBatBuffer, _tcslen(szBatBuffer), &dwLength, NULL))
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/Temp bat file write content failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/Temp bat file make content failed.");
|
||||
}
|
||||
|
||||
CloseHandle(hBatFile);
|
||||
|
||||
delete [] szBatBuffer;
|
||||
ShellExecute(NULL, _T("open"), szTempBatContent, NULL, NULL, SW_HIDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(0 != szErrorMessage)
|
||||
{
|
||||
ERRLOG1(g_Log, szErrorMessage, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 패치 성공. 종료.
|
||||
DETLOG1(g_Log, "this:0x%p/Patch success. restart now.", this);
|
||||
PostMessage(GetWnd(), WM_DESTROY, 0, 0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
bool CManageClient::ApplicationSpecificInit(const TCHAR* szCmdLine)
|
||||
{
|
||||
const TCHAR* szErrorMessage = 0;
|
||||
|
||||
if(!InitializeMsgProc())
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/InitializeMsgProc failed");
|
||||
}
|
||||
else if(!InitializeCommand())
|
||||
{
|
||||
szErrorMessage = _T("this:0x%p/InitializeCommand failed");
|
||||
}
|
||||
else if(!AddProcessThread(new CManageClientProcessThread(*this)))
|
||||
{
|
||||
szErrorMessage = "this:0x%p/AddProcessThread failed";
|
||||
}
|
||||
|
||||
if(0 != szErrorMessage)
|
||||
{
|
||||
ERRLOG1(g_Log, szErrorMessage, this);
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckConnectionAndReconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CManageClient::PrintConnectionStatus()
|
||||
{
|
||||
const int MAX_BUFFER = 4096;
|
||||
char szBuffer[MAX_BUFFER];
|
||||
|
||||
char szFileName[MAX_PATH];
|
||||
char szExtension[MAX_PATH];
|
||||
|
||||
INET_Addr& manageServerAddr = ManageSetup::ClientSetup::GetInstance().GetManageServerAddr();
|
||||
|
||||
GET_SINGLE_DISPATCH(lpManageClientDispatch,
|
||||
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
|
||||
|
||||
int nLength = _snprintf(szBuffer, MAX_BUFFER - 1,
|
||||
"ManageClient Console\r\n\r\nManageServer IP:%s, Port:%d %s\r\n\r\n",
|
||||
manageServerAddr.get_addr_string(),
|
||||
manageServerAddr.get_port_in(),
|
||||
(0 != lpManageClientDispatch) ? "Connected" : "Disconnected");
|
||||
|
||||
int nTotalLength = 0;
|
||||
|
||||
if(0 < nLength)
|
||||
{
|
||||
if(0 != lpManageClientDispatch)
|
||||
{
|
||||
nTotalLength += nLength;
|
||||
|
||||
CManageClientDispatch::RunTable& runTable = lpManageClientDispatch->GetRunTable();
|
||||
|
||||
CManageClientDispatch::RunTable::iterator pos = runTable.begin();
|
||||
CManageClientDispatch::RunTable::iterator end = runTable.end();
|
||||
|
||||
for(; pos != end; ++pos)
|
||||
{
|
||||
const ServerManage::RunInfo& runInfo = pos->second.m_RunInfo;
|
||||
|
||||
_splitpath(runInfo.m_szPath, 0, 0, szFileName, szExtension);
|
||||
|
||||
nLength = _snprintf(szBuffer + nTotalLength, MAX_BUFFER - nTotalLength,
|
||||
"RunID:%5d / %s%s %s\r\n",
|
||||
runInfo.m_dwRunID, szFileName, szExtension, runInfo.m_szOption);
|
||||
|
||||
if(0 < nLength)
|
||||
{
|
||||
nTotalLength += nLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(0 < nTotalLength && nTotalLength < MAX_BUFFER)
|
||||
{
|
||||
szBuffer[nTotalLength] = 0;
|
||||
PrintInfo(szBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user