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:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,835 @@
#include "stdafx.h"
#include "ManageClientDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Setup/SetupClient.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Log/ServerLog.h>
#include <tlhelp32.h>
#include <mmsystem.h>
#include <string>
#include <vector>
#pragma comment(lib, "winmm.lib")
/*
// forward decl
HANDLE GetProcessHandle(const char* szProcessFullPathName, unsigned long* lpdwPID);
*/
enum ManageClientConst
{
MANAGE_CLIENT_DEFAULT_DISPATCH_NUM = 10
};
CManageClientDispatch::RunExtraInfo::RunExtraInfo(const ServerManage::RunInfo& runInfo,
HANDLE hProcess, unsigned long dwProcessID)
: m_RunInfo(runInfo), m_hProcess(hProcess), m_dwProcessID(dwProcessID),
m_hWnd(0), m_dwCustomStatus(0), m_dwLastSetWindowHandleTime(0)
{
char szCommand[MAX_PATH];
_snprintf(szCommand, MAX_PATH - 1, "%s", m_RunInfo.m_szOption);
szCommand[MAX_PATH - 1] = 0;
char* szData = strtok(szCommand, " \t\r\n");
while(0 != szData)
{
m_CommandSet.insert(szData);
szData = strtok(0, " \t\r\n");
}
}
CSingleDispatch& CManageClientDispatch::GetDispatchTable()
{
static CSingleDispatch singleDispatch;
return singleDispatch;
}
CManageClientDispatch::CManageClientDispatch(CSession& Session)
: CRylServerDispatch(Session, MANAGE_CLIENT_DEFAULT_DISPATCH_NUM),
m_hPatchFile(INVALID_HANDLE_VALUE),
m_bDoPatchNow(false)
{
TCHAR* szTempFileName = _T("./mytmp_patch.tmp");
memset(m_szTempPatchFileName, 0, sizeof(TCHAR) * MAX_PATH);
_tcscpy(m_szTempPatchFileName, szTempFileName);
TCHAR szFullPathModuleName[MAX_PATH];
GetModuleFileName(NULL, szFullPathModuleName, MAX_PATH - 1);
szFullPathModuleName[MAX_PATH - 1] = 0;
TCHAR szDrive[MAX_PATH];
TCHAR szPath[MAX_PATH];
TCHAR szName[MAX_PATH];
TCHAR szExtension[MAX_PATH];
_tsplitpath(szFullPathModuleName, szDrive, szPath, szName, szExtension);
_sntprintf(m_szTempPatchFileName, MAX_PATH - 1,
_T("%s\\%s\\%s"), szDrive, szPath, szTempFileName);
m_szTempPatchFileName[MAX_PATH - 1] = 0;
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Created", this);
}
CManageClientDispatch::~CManageClientDispatch()
{
if(INVALID_HANDLE_VALUE != m_hPatchFile)
{
// 파일이 아직 열려 있다. 닫는다.
ERRLOG2(g_Log, "this:0x%0p/HANDLE:0x%p/PatchFile is not closed. close now", this, m_hPatchFile);
CloseHandle(m_hPatchFile);
}
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Destroyed", this);
}
void CManageClientDispatch::Connected()
{
GetDispatchTable().SetDispatch(this);
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Connected", this);
}
void CManageClientDispatch::Disconnected()
{
GetDispatchTable().RemoveDispatch(this);
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Disconnected", this);
}
bool CManageClientDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::LengthType nPacketLen = lpPktBase->GetLen();
if(nPacketLen < sizeof(ServerManage::ManageCommand))
{
ERRLOG3(g_Log, "IP:%15s/PacketLen:%d/Cmd:0x%02x/Invalid packet length or command",
GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetLen(), lpPktBase->GetCmd());
}
else
{
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(nPacketLen != sizeof(ServerManage::ManageCommand) + lpManageCommand->usDataLen)
{
ERRLOG3(g_Log, "IP:%15s/PacketLen:%d/Cmd:0x%02x/Invalid packet length",
GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetLen(), lpPktBase->GetCmd());
}
else
{
TCHAR* szWindowName = 0;
char* lpData = (0 != lpManageCommand->usDataLen) ?
reinterpret_cast<char*>(lpManageCommand + 1) : 0;
const TCHAR* szErrorMessage = 0;
switch(lpManageCommand->GetCmd())
{
case ServerManage::CMD::UpdateRunList: // 실행 목룍을 준다 (ManageServer -> ManageClient, ManageTool), Ack없음.
ProcessUpdateRunList(lpData, lpManageCommand->usDataLen, lpManageCommand->usFlags);
break;
case ServerManage::CMD::RunProcess: // 실행한다. (ManageTool -> ManageServer -> ManageClient), Ack는 반대 순서로 전송
ProcessRunServer(lpManageCommand->dwRunID);
break;
case ServerManage::CMD::QuitProcess: // 종료한다. (ManageTool -> ManageServer -> ManageClient), Ack는 반대 순성로 전송
ProcessQuitServer(lpManageCommand->dwRunID);
break;
case ServerManage::CMD::ForceTerminate: // 강제 종료한다. (ManageTool -> ManageServer -> ManageClient), Ack는 반대 순서로 전송
ProcessTerminateServer(lpManageCommand->dwRunID);
break;
case ServerManage::CMD::RelayCommand: // 패킷 커맨드를 윈도우 메시지를 써서 중계해서 넘긴다.
/*
if(!ProcessRelayCommand(lpManageCommand->nMessage,
lpManageCommand->wParam, lpManageCommand->lParam,
szWindowName, lpData, lpManageCommand->usDataLen, lpManageCommand->cFlag))
{
szErrorMessage = _T("RelayCommand : RelayCommand Failed");
}
*/
break;
case ServerManage::CMD::AutoPatch: // 자기 자신을 패치한다
if(!ProcessAutoPatch(lpData, lpManageCommand->usDataLen, lpManageCommand->usFlags))
{
szErrorMessage = _T("AutoPatch : AutoPatch packet process failed");
}
break;
case ServerManage::CMD::ChangeSetup: // 설정을 바꾸고 저장한다.
if(!ManageSetup::ClientSetup::GetInstance().SerializeIn(lpData, lpManageCommand->usDataLen))
{
szErrorMessage = _T("ChangeSetup : Change setup failed");
}
else
{
ManageSetup::ClientSetup::GetInstance().Save();
}
break;
case ServerManage::CMD::ReloadSetup: // 설정을 재로드한다.
ManageSetup::ClientSetup::GetInstance().Load();
break;
case ServerManage::CMD::ExecuteCommand:
ProcessExecuteConsoleCommand(lpManageCommand);
break;
default:
szErrorMessage = _T("Unknown message : Process failed");
break;
}
if(0 != szErrorMessage)
{
ERRLOG4(g_Log, "IP:%15s/DetailCmd:0x%02x/Error:%d/%s",
GetSession().GetRemoteAddr().get_addr_string(),
lpPktBase->GetCmd(), GetLastError(), szErrorMessage);
}
}
}
return true;
}
bool CManageClientDispatch::ProcessRelayCommand(unsigned int nMessage, WPARAM wParam, LPARAM lParam,
const char* szWindowName, const char* lpData,
unsigned short usDataLen, unsigned char cFlag)
{
if(0 != szWindowName)
{
HWND hWnd = FindWindow(0, szWindowName);
if(0 != hWnd)
{
if(0 != lpData && WM_COPYDATA == nMessage)
{
COPYDATASTRUCT copyDataStruct;
copyDataStruct.dwData = 0;
copyDataStruct.cbData = usDataLen;
copyDataStruct.lpData = (void*)lpData;
// 메시지를 보낸다.
SendMessage(hWnd, nMessage, wParam,
reinterpret_cast<LPARAM>(&copyDataStruct));
}
else
{
SendMessage(hWnd, nMessage, wParam, lParam);
}
}
}
return true;
}
bool CManageClientDispatch::ProcessAutoPatch(const char* lpData, unsigned short usDataLen, unsigned short usFlag)
{
switch(usFlag)
{
case ServerManage::ManageCommand::AUTOPATCH_OPENFILE:
if(INVALID_HANDLE_VALUE != m_hPatchFile)
{
// 패치 파일이 열려 있음. 닫는다.
ERRLOG2(g_Log, "this:0x%0p/HANDLE:0x%p/PatchFile is not closed. close now for create new one",
this, m_hPatchFile);
CloseHandle(m_hPatchFile);
}
// 파일을 생성한다.
m_hPatchFile = CreateFile(m_szTempPatchFileName, GENERIC_WRITE, 0, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == m_hPatchFile)
{
ERRLOG2(g_Log, "this:0x%p/Error:%d/Patch tempfile create failed",
this, GetLastError());
}
break;
case ServerManage::ManageCommand::AUTOPATCH_DATA:
if(INVALID_HANDLE_VALUE != m_hPatchFile)
{
unsigned long dwWritten = 0;
unsigned long dwTotalWritten = 0;
while(usDataLen != dwTotalWritten)
{
if(!WriteFile(m_hPatchFile, lpData, usDataLen, &dwWritten, 0))
{
ERRLOG3(g_Log, "this:0x%p/HANDLE:0x%p/Error:%d/Patchfile write failed.",
this, m_hPatchFile, GetLastError());
CloseHandle(m_hPatchFile);
m_hPatchFile = INVALID_HANDLE_VALUE;
DeleteFile(m_szTempPatchFileName);
break;
}
dwTotalWritten += dwWritten;
}
if(0 == usDataLen && INVALID_HANDLE_VALUE != m_hPatchFile)
{
// 파일을 전부 받았다. 이제 전송을 종료하고 패치를 적용한다.
m_bDoPatchNow = true;
}
}
else
{
ERRLOG1(g_Log, "this:0x%p/Patchfile is invalid", this);
}
break;
}
return true;
}
bool CManageClientDispatch::ProcessUpdateRunList(const char* szData, unsigned short usDataLen,
unsigned short usFlags)
{
if(ServerManage::SEND_RUNINFO_START == usFlags)
{
// 기존에 열었던 Process들에 대해서 전부 핸들을 닫는다.
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
if(0 != runExtraInfo.m_hProcess)
{
CloseHandle(runExtraInfo.m_hProcess);
}
}
m_RunTable.clear();
}
else if(ServerManage::SEND_RUNINFO_NOW == usFlags)
{
// RunTable에 세팅하고, 프로세스를 연다.
const ServerManage::RunInfo* lpRunInfo = reinterpret_cast<const ServerManage::RunInfo*>(szData);
const ServerManage::RunInfo* lpEndRunInfo = lpRunInfo + (usDataLen / sizeof(ServerManage::RunInfo));
for(; lpRunInfo != lpEndRunInfo; ++lpRunInfo)
{
m_RunTable.insert(RunTable::value_type(lpRunInfo->m_dwRunID,
RunExtraInfo(*lpRunInfo, 0, 0)));
}
}
else if(ServerManage::SEND_RUNINFO_FINISH == usFlags)
{
// 프로세스 상태 갱신 패킷을 보낸다.
CheckProcessStatus();
}
return true;
}
bool CManageClientDispatch::ProcessRunServer(unsigned long dwRunID)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
TCHAR szDrive[MAX_PATH];
TCHAR szPath[MAX_PATH];
TCHAR szDefaultPath[MAX_PATH];
_splitpath(runExInfo.m_RunInfo.m_szPath, szDrive, szPath, 0, 0);
_snprintf(szDefaultPath, MAX_PATH - 1, "%s%s", szDrive, szPath);
szDefaultPath[MAX_PATH - 1] = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
/*
if(CreateProcess(runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, 0, 0,
FALSE, 0, 0, szDefaultPath, &si, &pi))
*/
char szExecutePath[MAX_PATH * 2];
_snprintf(szExecutePath, MAX_PATH * 2 - 1, "\"%s\" %s",
runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption);
szExecutePath[MAX_PATH * 2 - 1] = 0;
if(CreateProcess(0, szExecutePath, 0, 0,
FALSE, 0, 0, szDefaultPath, &si, &pi))
{
runExInfo.m_hProcess = pi.hProcess;
runExInfo.m_dwProcessID = pi.dwProcessId;
DETLOG4(g_Log, "Execute file success, RunID(%u), Path(%s), Option(%s), DefaultPath(%s)",
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption, szDefaultPath);
}
else
{
ERRLOG5(g_Log, "Cannot execute file : CreateProcess failed(%d), RunID(%u), "
"Path(%s), Option(%s), DefaultPath(%s)",
WSAGetLastError(), runExInfo.m_RunInfo.m_dwRunID,
runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, szDefaultPath);
}
}
else
{
ERRLOG1(g_Log, "Cannot execute file : Unknown RunID(%d)", dwRunID);
}
return true;
}
bool CManageClientDispatch::ProcessQuitServer(unsigned long dwRunID)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
if(0 != runExInfo.m_hWnd)
{
TCHAR szWindowName[MAX_PATH];
GetWindowText(runExInfo.m_hWnd, szWindowName, MAX_PATH - 1);
szWindowName[MAX_PATH - 1] = 0;
SendMessage(runExInfo.m_hWnd, WM_DESTROY, 0, 0);
DETLOG6(g_Log, "Send quit message : HANDLE(0x%p), PID(0x%08x), WindowName(%s), "
"RunID(%u), Path(%s), Option(%s)",
runExInfo.m_hProcess, runExInfo.m_dwProcessID, szWindowName,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
else
{
ERRLOG5(g_Log, "Cannot send quit message (Get window failed) : "
"HANDLE(0x%p), PID(0x%08x), RunID(%u), Path(%s), Option(%s)",
runExInfo.m_hProcess, runExInfo.m_dwProcessID,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
}
return true;
}
bool CManageClientDispatch::ProcessTerminateServer(unsigned long dwRunID)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
if(0 != runExInfo.m_hProcess)
{
if(TerminateProcess(runExInfo.m_hProcess, -1))
{
DETLOG5(g_Log, "Terminate process. HANDLE(0x%p), PID(0x%08x), "
"RunID(%u), Path(%s), Option(%s)",
runExInfo.m_hProcess, runExInfo.m_dwProcessID,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
else
{
ERRLOG6(g_Log, "Cannot terminate process. Err(%d), HANDLE(0x%p), PID(0x%08x), "
"RunID(%u), Path(%s), Option(%s)",
GetLastError(), runExInfo.m_hProcess, runExInfo.m_dwProcessID,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
}
}
return true;
}
bool CManageClientDispatch::ProcessExecuteConsoleCommand(ServerManage::ManageCommand* lpManageCmd)
{
RunTable::iterator pos = m_RunTable.find(lpManageCmd->dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
if(0 != runExInfo.m_hWnd)
{
COPYDATASTRUCT copyDataStruct;
copyDataStruct.dwData = 0;
copyDataStruct.cbData = lpManageCmd->GetLen();
copyDataStruct.lpData = lpManageCmd;
SendMessage(runExInfo.m_hWnd, WM_COPYDATA, 0, (LPARAM)&copyDataStruct);
}
}
return true;
}
void CManageClientDispatch::CheckProcessStatus()
{
const int MAX_PROCESS_STATUS_SEND_ONCE =
(PktMaxLen - sizeof(ServerManage::ManageCommand)) / sizeof(ServerManage::ProcessStatus);
ServerManage::ProcessStatus procesStatus[MAX_PROCESS_STATUS_SEND_ONCE];
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
// 체크하고, PID가 있는데 프로세스가 열리지 않은 프로그램은, 프로세스를 연다.
if(0 != runExtraInfo.m_dwProcessID && 0 != runExtraInfo.m_hWnd
&& 0 == runExtraInfo.m_hProcess)
{
runExtraInfo.m_hProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE, runExtraInfo.m_dwProcessID);
}
}
unsigned long dwExitCode = 0;
unsigned long dwErrorCode = 0;
unsigned short usSendProcessStatus = 0;
pos = m_RunTable.begin();
end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
// Default - Deactivated Process.
ServerManage::ProcessStatus* lpCurrentProcessStatus = procesStatus + usSendProcessStatus;
memset(lpCurrentProcessStatus, 0, sizeof(ServerManage::ProcessStatus));
lpCurrentProcessStatus->m_dwRunID = runExtraInfo.m_RunInfo.m_dwRunID;
lpCurrentProcessStatus->m_dwStatusFlags = 0;
lpCurrentProcessStatus->m_dwCurrentTime = timeGetTime();
lpCurrentProcessStatus->m_dwCustomStatus = runExtraInfo.m_dwCustomStatus;
lpCurrentProcessStatus->m_dwLastSetWindowHandleTime = runExtraInfo.m_dwLastSetWindowHandleTime;
if(0 != runExtraInfo.m_hProcess)
{
GetProcessTimes(runExtraInfo.m_hProcess,
&lpCurrentProcessStatus->m_CreationTIme,
&lpCurrentProcessStatus->m_ExitTime,
&lpCurrentProcessStatus->m_KernelTime,
&lpCurrentProcessStatus->m_UserTime);
GetProcessMemoryInfo(runExtraInfo.m_hProcess,
&lpCurrentProcessStatus->m_ProcessMemoryCounters,
sizeof(PROCESS_MEMORY_COUNTERS));
if(!GetExitCodeProcess(runExtraInfo.m_hProcess, &dwExitCode))
{
ERRLOG3(g_Log, "GetExitCodeProcess failed(%d) : RunID(%u), Path(%s)",
dwErrorCode, runExtraInfo.m_RunInfo.m_dwRunID,
runExtraInfo.m_RunInfo.m_szPath);
}
else if(dwExitCode != STILL_ACTIVE)
{
DETLOG4(g_Log, "Close process handle : HANDLE(0x%p), PID(0x%08x), RunID(%u), Path(%s)",
runExtraInfo.m_hProcess, runExtraInfo.m_dwProcessID,
runExtraInfo.m_RunInfo.m_dwRunID, runExtraInfo.m_RunInfo.m_szPath);
CloseHandle(runExtraInfo.m_hProcess);
runExtraInfo.m_hProcess = 0;
runExtraInfo.m_dwProcessID = 0;
runExtraInfo.m_hWnd = 0;
runExtraInfo.m_dwLastSetWindowHandleTime = 0;
}
else
{
lpCurrentProcessStatus->m_dwStatusFlags =
ServerManage::PROCESS_RUNNING;
}
}
++usSendProcessStatus;
if(usSendProcessStatus == MAX_PROCESS_STATUS_SEND_ONCE)
{
ServerManage::SendManagePacket(GetSession(), ServerManage::CMD::ProcessStatus,
0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * usSendProcessStatus, 0, procesStatus, 0);
usSendProcessStatus = 0;
}
}
if(0 < usSendProcessStatus)
{
ServerManage::SendManagePacket(GetSession(), ServerManage::CMD::ProcessStatus,
0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * usSendProcessStatus, 0, procesStatus, 0);
usSendProcessStatus = 0;
}
}
bool CManageClientDispatch::SetAppData(unsigned long dwRunID, HWND hWnd,
unsigned long dwPID, unsigned long dwCustomStatus)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
RunTable::iterator end = m_RunTable.end();
if(pos != end)
{
RunExtraInfo& runExtraInfo = pos->second;
runExtraInfo.m_dwProcessID = dwPID;
runExtraInfo.m_hWnd = hWnd;
runExtraInfo.m_dwCustomStatus = dwCustomStatus;
runExtraInfo.m_dwLastSetWindowHandleTime = timeGetTime();
return true;
}
return false;
}
bool CManageClientDispatch::GetRunIDFromString(const char* szAppName, const char* szCommandLine,
unsigned long& dwRunID_Out)
{
char szProcessName[MAX_PATH];
char szProcessSnapName[MAX_PATH];
_snprintf(szProcessSnapName, MAX_PATH - 1, "%s", szAppName);
szProcessSnapName[MAX_PATH - 1] = 0;
_strupr(szProcessSnapName);
char szCommandLineData[MAX_PATH * 2];
_snprintf(szCommandLineData, MAX_PATH * 2 - 1, "%s", szCommandLine);
szCommandLineData[MAX_PATH * 2 - 1] = 0;
RunExtraInfo::CommandSet commandSet;
char* szData = 0;
if('\"' == szCommandLineData[0])
{
szData = strtok(szCommandLineData, "\"");
szData = strtok(0, "\"");
if(0 != szData)
{
// 파일명을 분리한 Argument를 받아서 처리..
char szRealCommandLine[MAX_PATH];
_snprintf(szRealCommandLine, MAX_PATH - 1, "%s", szData);
szRealCommandLine[MAX_PATH - 1] = 0;
szData = strtok(szRealCommandLine, " \t\r\n");
while(0 != szData)
{
commandSet.insert(szData);
szData = strtok(0, " \t\r\n");
}
}
}
else
{
szData = strtok(szCommandLineData, " \t\r\n");
// 첫번째 Argument는 파일명이므로 무시.
szData = strtok(0, " \t\r\n");
while(0 != szData)
{
commandSet.insert(szData);
szData = strtok(0, " \t\r\n");
}
}
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
_snprintf(szProcessName, MAX_PATH - 1, "%s", runExtraInfo.m_RunInfo.m_szPath);
szProcessName[MAX_PATH - 1] = 0;
_strupr(szProcessName);
if(0 == strncmp(szProcessName, szProcessSnapName, MAX_PATH))
{
if((runExtraInfo.m_CommandSet.size() == commandSet.size()
&& std::equal(runExtraInfo.m_CommandSet.begin(),
runExtraInfo.m_CommandSet.end(), commandSet.begin())))
{
dwRunID_Out = runExtraInfo.m_RunInfo.m_dwRunID;
return true;
}
}
}
dwRunID_Out = 0;
return false;
}
bool CManageClientDispatch::GetRunIDFromPID(unsigned long dwPID, unsigned long& dwRunID_Out)
{
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
if(runExtraInfo.m_dwProcessID == dwPID)
{
dwRunID_Out = runExtraInfo.m_RunInfo.m_dwRunID;
return true;
}
}
dwRunID_Out = 0;
return false;
}
/*
HANDLE GetProcessHandle(const char* szProcessFullPathName, unsigned long* lpdwPID)
{
HANDLE hProcess = INVALID_HANDLE_VALUE;
if(0 == lpdwPID)
{
return hProcess;
}
// Take a snapshot of all processes in the system.
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return hProcess;
}
// Fill in the size of the structure before using it.
PROCESSENTRY32 pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes, and for each process,
// display information.
char szProcessName[MAX_PATH];
char szProcessSnapName[MAX_PATH];
_snprintf(szProcessName, MAX_PATH - 1, "%s", szProcessFullPathName);
szProcessName[MAX_PATH - 1] = 0;
_strupr(szProcessName);
bool bFound = false;
if (Process32First(hProcessSnap, &pe32))
{
do
{
MODULEENTRY32 me32 = {0};
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID);
if (hModuleSnap != INVALID_HANDLE_VALUE)
{
me32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hModuleSnap, &me32))
{
do
{
_snprintf(szProcessSnapName, MAX_PATH - 1, "%s", me32.szExePath);
szProcessSnapName[MAX_PATH - 1] = 0;
_strupr(szProcessSnapName);
if(0 == strcmp(szProcessName, szProcessSnapName))
{
// Get the actual priority class.
hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if(INVALID_HANDLE_VALUE == hProcess)
{
ERRLOG2(g_Log, "Process open failed(%d) : %s",
GetLastError(), me32.szExePath);
}
*lpdwPID = pe32.th32ProcessID;
bFound = true;
break;
}
}
while (!bFound && Module32Next(hModuleSnap, &me32));
}
CloseHandle (hModuleSnap);
}
}
while (!bFound && Process32Next(hProcessSnap, &pe32));
}
CloseHandle(hProcessSnap);
return hProcess;
}
*/

View File

@@ -0,0 +1,90 @@
#ifndef _GM_MANAGE_CLIENT_DISPATCH_H_
#define _GM_MANAGE_CLIENT_DISPATCH_H_
#pragma warning(disable:4800)
#include <map>
#include <set>
#include <boost/pool/pool_alloc.hpp>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Network/Packet/ManagePacketCmd.h>
// CManageClientDispatch를 쓰는 클라이언트만 이 라이브러리를 링크함.
#pragma comment(lib, "psapi.lib")
class CManageClientDispatch : public CRylServerDispatch
{
public:
struct RunExtraInfo
{
typedef std::set<std::string> CommandSet;
ServerManage::RunInfo m_RunInfo;
HANDLE m_hProcess;
HWND m_hWnd;
unsigned long m_dwProcessID;
unsigned long m_dwCustomStatus;
unsigned long m_dwLastSetWindowHandleTime;
CommandSet m_CommandSet;
RunExtraInfo();
RunExtraInfo(const ServerManage::RunInfo& runInfo,
HANDLE hProcess, unsigned long dwProcessID);
};
// Key - RunID
typedef std::map<unsigned long, RunExtraInfo, std::less<unsigned long>,
boost::pool_allocator<std::pair<unsigned long, RunExtraInfo> > > RunTable;
static CSingleDispatch& GetDispatchTable();
CManageClientDispatch(CSession& Session);
virtual ~CManageClientDispatch();
void CheckProcessStatus();
bool DoPatchNow() const { return m_bDoPatchNow; }
const TCHAR* GetTempPatchFileName() const { return m_szTempPatchFileName; }
bool SetAppData(unsigned long dwRunID, HWND hWnd,
unsigned long dwPID, unsigned long dwCustomStatus);
bool GetRunIDFromPID(unsigned long dwPID, unsigned long& dwRunID_Out);
bool GetRunIDFromString(const char* szAppName,
const char* szCommandLine, unsigned long& dwRunID_Out);
RunTable& GetRunTable() { return m_RunTable; }
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
bool ProcessUpdateRunList(const char* szData, unsigned short usDataLen, unsigned short usFlags);
bool ProcessRunServer(unsigned long dwRunID);
bool ProcessQuitServer(unsigned long dwRunID);
bool ProcessTerminateServer(unsigned long dwRunID);
bool ProcessExecuteConsoleCommand(ServerManage::ManageCommand* lpManageCmd);
bool ProcessRelayCommand(unsigned int nMessage, WPARAM wParam, LPARAM lParam,
const char* szWindowName, const char* lpData, unsigned short usDataLen, unsigned char cFlag);
bool ProcessAutoPatch(const char* lpData, unsigned short usDataLen, unsigned short usFlag);
// Member variable;
HANDLE m_hPatchFile; // 패치 파일 핸들.
TCHAR m_szTempPatchFileName[MAX_PATH]; // 임시 패치 파일 이름.
bool m_bDoPatchNow; // 패치 준비가 되었는지 여부를 알아옴.
RunTable m_RunTable;
};
#endif

View File

@@ -0,0 +1,231 @@
#include "stdafx.h"
#include "ManageServerDispatch.h"
#include "ManageToolServerDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <UserManage/ToolUserManageTable.h>
#include <Log/ServerLog.h>
#include <Setup/SetupClient.h>
#include <ServerManage/ManageClientManager.h>
#include <UserManage/UserStatistics.h>
enum ManageServerConst
{
MANAGE_SERVER_DEFAULT_DISPATCH_NUM = 100
};
CMultiDispatch& CManageServerDispatch::GetDispatchTable()
{
static CMultiDispatch multiDispatch;
return multiDispatch;
}
CManageServerDispatch::CManageServerDispatch(CSession& Session)
: CRylServerDispatch(Session, MANAGE_SERVER_DEFAULT_DISPATCH_NUM),
m_bAuthorized(false)
{
memset(&m_UserInfo, 0, sizeof(ServerManage::UserInfo));
DETLOG1(g_Log, "this:0x%p/CManageServerDispatch Created", this);
}
CManageServerDispatch::~CManageServerDispatch()
{
DETLOG1(g_Log, "this:0x%p/CManageServerDispatch Destroyed", this);
}
void CManageServerDispatch::Connected()
{
// 접속 IP를 key로 잡아서 세팅한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().SetDispatch(dwDispatchID, this);
// TODO : 서버 IP로 검색해서, RunInfo들을 전송한다.
CManageClientManager::RunTable runInfoTable;
CManageClientManager::GetInstance().GetRunInfoFromIP(dwDispatchID, runInfoTable);
if(!CManageClientManager::SendRunInfo(GetSession(), runInfoTable))
{
ERRLOG3(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Send runInfo failed",
&GetSession(), this, remoteAddr.get_addr_string());
}
DETLOG2(g_Log, "this:0x%p/Key:%u/CManageServerDispatch Connected", this, dwDispatchID);
}
class CSendProcessData
{
public:
CSendProcessData(ServerManage::ProcessStatus* lpProcessData,
unsigned short usProcessDataNum)
: m_lpProcessData(lpProcessData), m_usProcessDataNum(usProcessDataNum)
{
}
bool operator () (CManageToolServerDispatch& toolDispatch)
{
ServerManage::SendManagePacket(toolDispatch.GetSession(), ServerManage::CMD::ProcessStatus,
0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * m_usProcessDataNum, 0, m_lpProcessData, 0);
return true;
}
private:
ServerManage::ProcessStatus* m_lpProcessData;
unsigned short m_usProcessDataNum;
};
void CManageServerDispatch::Disconnected()
{
// 접속 IP를 key로 잡아서 세팅한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().RemoveDispatch(dwDispatchID);
CManageClientManager::RunTable runInfoTable;
CManageClientManager::GetInstance().GetRunInfoFromIP(dwDispatchID, runInfoTable);
CManageClientManager::RunTable::iterator pos = runInfoTable.begin();
CManageClientManager::RunTable::iterator end = runInfoTable.end();
const int MAX_PROCESS_STATUS_SEND_ONCE =
(PktMaxLen - sizeof(ServerManage::ManageCommand)) / sizeof(ServerManage::ProcessStatus);
ServerManage::ProcessStatus procesStatus[MAX_PROCESS_STATUS_SEND_ONCE];
unsigned short usSendProcessStatus = 0;
for(; pos != end; ++pos)
{
ServerManage::RunInfo& runInfo = pos->second;
// Default - Deactivated Process.
ServerManage::ProcessStatus* lpCurrentProcessStatus = procesStatus + usSendProcessStatus;
memset(lpCurrentProcessStatus, 0, sizeof(ServerManage::ProcessStatus));
lpCurrentProcessStatus->m_dwRunID = runInfo.m_dwRunID;
++usSendProcessStatus;
if(usSendProcessStatus == MAX_PROCESS_STATUS_SEND_ONCE)
{
CToolUserManager::GetInstance().ProcessCurrentUser(
CSendProcessData(procesStatus, usSendProcessStatus));
usSendProcessStatus = 0;
}
}
if(0 < usSendProcessStatus)
{
CToolUserManager::GetInstance().ProcessCurrentUser(
CSendProcessData(procesStatus, usSendProcessStatus));
usSendProcessStatus = 0;
}
DETLOG2(g_Log, "this:0x%p/Key:%u/CManageServerDispatch Disconnected", this, dwDispatchID);
}
bool CManageServerDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::LengthType nPacketLen = lpPktBase->GetLen();
bool bResult = false;
switch(lpPktBase->GetCmd())
{
case ServerManage::CMD::ProcessStatus:
CUserStatistics::GetInstance().CheckClearUser(lpPktBase);
RelayPacketToManageTools(lpPktBase);
break;
case ServerManage::CMD::RelayCommand:
RelayPacketToManageTools(lpPktBase);
break;
default:
{
in_addr addr;
addr.S_un.S_addr = m_UserInfo.dwIP;
ERRLOG4(g_Log, "ID:%s/Name:%s/IP:%s/Cmd:0x%02x/Undefined command.",
m_UserInfo.szID, m_UserInfo.szFullName, inet_ntoa(addr),
lpPktBase->GetCmd());
}
break;
}
return true;
}
bool CManageServerDispatch::RelayPacketToManageTools(PktBase* lpPktBase)
{
unsigned char cError = 0;
bool bDoNotRelay = false;
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(!ServerManage::CheckManagePacketLength(lpPktBase))
{
cError = ServerManage::INVALID_MANAGE_PACKET_ERROR;
}
if(sizeof(ServerManage::PktManagePacket) <= lpManageCommand->usDataLen)
{
ServerManage::PktManagePacket* lpPktManagePacket =
reinterpret_cast<ServerManage::PktManagePacket*>(lpManageCommand + 1);
switch(lpPktManagePacket->m_dwSubCommand)
{
case ServerManage::CMD::SubCmd_ServerUserNum:
{
ServerManage::PktManageUserNum* lpPktManageUserNum =
static_cast<ServerManage::PktManageUserNum*>(lpPktManagePacket);
/*
DETLOG2(g_Log, "RunID:%d/PID:%d/Setting UserInfo",
lpManageCommand->dwRunID, lpPktManageUserNum->m_dwPID);
*/
CUserStatistics::GetInstance().SerializeIn(lpManageCommand->dwRunID,
reinterpret_cast<ServerManage::UserNumPair*>(lpPktManageUserNum + 1),
lpPktManageUserNum->m_dwUserInfoNum);
}
break;
}
}
if(0 == cError && !bDoNotRelay)
{
CToolUserManager::GetInstance().ProcessCurrentUser(
ServerManage::CSendManagePacketToClient(*lpManageCommand,
reinterpret_cast<char*>(lpManageCommand + 1)));
return true;
}
return ServerManage::SendManagePacket(GetSession(),
lpPktBase->GetCmd(), 0, 0, 0, 0, 0, 0, 0, cError);
}

View File

@@ -0,0 +1,30 @@
#ifndef _GM_MANAGE_SERVER_DISPATCH_H_
#define _GM_MANAGE_SERVER_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
class CManageServerDispatch : public CRylServerDispatch
{
public:
static CMultiDispatch& GetDispatchTable();
CManageServerDispatch(CSession& Session);
virtual ~CManageServerDispatch();
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
bool RelayPacketToManageTools(PktBase* lpPktBase);
ServerManage::UserInfo m_UserInfo;
bool m_bAuthorized;
};
#endif

View File

@@ -0,0 +1,320 @@
#include "stdafx.h"
#include "ManageServerDispatch.h"
#include "ManageToolServerDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <UserManage/ToolUserManageTable.h>
#include <ServerManage/ManageClientManager.h>
#include <Setup/SetupClient.h>
#include <Log/ServerLog.h>
#include <Network/Packet/WrapPacket.h>
#include <mmsystem.h>
enum ManageToolServerConst
{
MANAGE_TOOL_SERVER_DEFAULT_DISPATCH_NUM = 10
};
CManageToolServerDispatch::CManageToolServerDispatch(CSession& Session)
: CRylServerDispatch(Session, MANAGE_TOOL_SERVER_DEFAULT_DISPATCH_NUM),
m_bAuthorized(false), m_dwLastPingRecvTime(timeGetTime())
{
memset(&m_UserInfo, 0, sizeof(ServerManage::UserInfo));
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Created", this);
}
CManageToolServerDispatch::~CManageToolServerDispatch()
{
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Destroyed", this);
}
void CManageToolServerDispatch::Connected()
{
// 인증 성공시 LoginTable에 삽입된다.
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Connected", this);
}
void CManageToolServerDispatch::Disconnected()
{
if(0 != m_UserInfo.szID[0])
{
CToolUserManager::GetInstance().Logout(m_UserInfo.szID);
}
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Disconnected", this);
}
bool CManageToolServerDispatch::Dispatch()
{
unsigned long dwCurrentTime = timeGetTime();
// 2분 동안 핑을 못받으면 접속을 끊는다.
if (1000 * 60 * 2 < dwCurrentTime - m_dwLastPingRecvTime)
{
INFLOG4(g_Log, "Disconnect by ping %s:%d / %u / %u ",
GetRemoteAddr().get_addr_string(), GetRemoteAddr().get_port_in(),
dwCurrentTime, m_dwLastPingRecvTime);
return false;
}
return CRylServerDispatch::Dispatch();
}
bool CManageToolServerDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::LengthType nPacketLen = lpPktBase->GetLen();
bool bResult = true;
const TCHAR* szErrorString = 0;
bool bSendInvalidUserPacketAck = false;
bool bSendInvalidManagePacketAck = false;
if (ServerManage::CMD::Ping == lpPktBase->GetCmd())
{
m_dwLastPingRecvTime = timeGetTime();
PktBase pktBase;
memset(&pktBase, 0, sizeof(PktBase));
pktBase.SetServerInfo(m_dwLastPingRecvTime);
if (PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktBase),
sizeof(PktBase), ServerManage::CMD::Ping, pktBase.GetState(), pktBase.GetError()))
{
GetSendStream().PutBuffer(reinterpret_cast<char*>(&pktBase),
sizeof(PktBase), ServerManage::CMD::Ping);
}
}
else if(ServerManage::CMD::AuthUser == lpPktBase->GetCmd())
{
if(!AuthUser(lpPktBase))
{
szErrorString = "Authorize failed.";
}
else
{
m_bAuthorized = true;
// 인증이 성공하면 RunInfo를 전송한다.
if(!CManageClientManager::SendRunInfo(GetSession(),
CManageClientManager::GetInstance().GetRunInfoTable()))
{
ERRLOG3(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Send runInfo failed",
&GetSession(), this, GetSession().GetRemoteAddr().get_addr_string());
}
}
}
else if(m_bAuthorized)
{
switch(lpPktBase->GetCmd())
{
// 다음 커맨드들은, RunID가 속한 서버로 메시지를 Relay한다.
// Relay하지 못한 경우는 실패를 돌려준다.
case ServerManage::CMD::RunProcess:
case ServerManage::CMD::QuitProcess:
case ServerManage::CMD::ForceTerminate:
case ServerManage::CMD::ProcessStatus:
case ServerManage::CMD::RelayCommand:
case ServerManage::CMD::AutoPatch:
case ServerManage::CMD::ChangeSetup:
case ServerManage::CMD::ReloadSetup:
case ServerManage::CMD::ExecuteCommand:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
(m_UserInfo.usAdminLevel == CToolUserManager::MASTER
|| m_UserInfo.usAdminLevel == CToolUserManager::GENERAL))
{
bResult = RelayPacketToManageClient(lpPktBase);
}
else
{
bSendInvalidManagePacketAck = true;
}
break;
case ServerManage::CMD::AddUser:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = AddUser(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::DelUser:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = DelUser(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::ModUser:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = ModUser(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::RequestPromote:
if(m_UserInfo.usAdminLevel == CToolUserManager::MASTER ||
m_UserInfo.usAdminLevel == CToolUserManager::GENERAL)
{
bResult = RequestPromote(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::RequestUserReaction:
if(m_UserInfo.usAdminLevel == CToolUserManager::MASTER ||
m_UserInfo.usAdminLevel == CToolUserManager::GENERAL)
{
bResult = ProcessUserReaction(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::UserList:
if(m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = UserList(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
default:
szErrorString = "Unknown packet. Cannot process.";
break;
}
}
else
{
szErrorString = "Unauthorized user send command. Cannot process.";
}
if(!bResult)
{
szErrorString = "Packet process failed.";
}
if(bSendInvalidManagePacketAck)
{
ServerManage::SendManagePacket(GetSession(), lpPktBase->GetCmd(),
0, 0, 0, 0, 0, 0, 0, ServerManage::INVALID_MANAGE_RIGHTS);
}
if(bSendInvalidUserPacketAck)
{
ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), 0, 0,
lpPktBase->GetCmd(), ServerManage::INVALID_USERMANAGE_RIGHTS);
}
if(0 != szErrorString)
{
in_addr addr;
addr.S_un.S_addr = m_UserInfo.dwIP;
ERRLOG5(g_Log, "ID:%s/Name:%s/IP:%s/Cmd:0x%02x/%s",
m_UserInfo.szID, m_UserInfo.szFullName, inet_ntoa(addr),
lpPktBase->GetCmd(), szErrorString);
}
return true;
}
bool CManageToolServerDispatch::RelayPacketToManageClient(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(!ServerManage::CheckManagePacketLength(lpPktBase))
{
cError = ServerManage::INVALID_MANAGE_PACKET_ERROR;
}
if(CManageClientManager::MAX_RUNID == lpManageCommand->dwRunID)
{
CManageServerDispatch::GetDispatchTable().Process(
ServerManage::CSendManagePacketToClient(*lpManageCommand,
reinterpret_cast<char*>(lpManageCommand + 1)));
}
else
{
ServerManage::RunInfo runInfo;
if(CManageClientManager::GetInstance().GetRunInfo(
lpManageCommand->dwRunID, runInfo))
{
GET_MULTI_DISPATCH(lpManageServerDispatch,
runInfo.m_dwServerIP,
CManageServerDispatch,
CManageServerDispatch::GetDispatchTable());
if(0 != lpManageServerDispatch)
{
DETLOG4(g_Log, "ID:%s/FullName:%s/Send Relay Packet(Cmd:%d), RunID:%u",
m_UserInfo.szID, m_UserInfo.szFullName,
lpManageCommand->GetCmd(), lpManageCommand->dwRunID);
if(!ServerManage::SendManagePacket(lpManageServerDispatch->GetSession(),
lpManageCommand->GetCmd(), lpManageCommand->nMessage,
lpManageCommand->wParam, lpManageCommand->lParam,
lpManageCommand->dwRunID, lpManageCommand->usDataLen, lpManageCommand->usFlags,
reinterpret_cast<char*>(lpManageCommand + 1), 0))
{
cError = ServerManage::SEND_MANAGE_COMMAND_ERROR;
}
}
else
{
cError = ServerManage::CANNOT_FIND_CLIENT_DISPATCH;
}
}
else
{
cError = ServerManage::UNKNOWN_RUN_INFO;
}
}
return ServerManage::SendManagePacket(GetSession(),
lpPktBase->GetCmd(), 0, 0, 0, 0, 0, 0, 0, cError);
}

View File

@@ -0,0 +1,44 @@
#ifndef _GM_MANAGE_TOOL_SERVER_DISPATCH_H_
#define _GM_MANAGE_TOOL_SERVER_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
// forward decl.
class CToolUserManager;
class CManageToolServerDispatch : public CRylServerDispatch
{
public:
CManageToolServerDispatch(CSession& Session);
virtual ~CManageToolServerDispatch();
const ServerManage::UserInfo& GetUserInfo() const { return m_UserInfo; }
private:
virtual void Connected();
virtual void Disconnected();
virtual bool Dispatch();
virtual bool DispatchPacket(PktBase* lpPktBase);
bool RelayPacketToManageClient(PktBase* lpPktBase);
bool AuthUser(PktBase* lpPktBase);
bool AddUser(PktBase* lpPktBase);
bool DelUser(PktBase* lpPktBase);
bool ModUser(PktBase* lpPktBase);
bool RequestPromote(PktBase* lpPktBase);
bool ProcessUserReaction(PktBase* lpPktBase);
bool UserList(PktBase* lpPktBase);
ServerManage::UserInfo m_UserInfo;
unsigned long m_dwLastPingRecvTime;
bool m_bAuthorized;
};
#endif

View File

@@ -0,0 +1,308 @@
#include "stdafx.h"
#include "ManageToolServerDispatch.h"
#include <tchar.h>
#include <Log/ServerLog.h>
#include <UserManage/ToolUserManageTable.h>
#include <Network/Session/Session.h>
#include <Network/Dispatch/SendManagePacket.h>
bool CManageToolServerDispatch::AuthUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError)
{
m_UserInfo = *lpUserInfo;
m_UserInfo.dwIP = GetSession().GetRemoteAddr().get_addr_in().sin_addr.S_un.S_addr;
// 인증 성공시 LoginTable에 삽입된다.
cError = CToolUserManager::GetInstance().Authorize(*this, m_UserInfo);
if (cError != ServerManage::NO_USER_COMMAND_ERROR)
{
ERRLOG2(g_Log, "ID:%s/IP:%s/Authorize failed",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
}
}
if(0 == cError)
{
DETLOG2(g_Log, "ID:%s/IP:%s/Authorize success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
// 다른 유저들에게 로그인 정보를 보낸다.
ServerManage::SendUserInfo(GetBufferFactory(), 0, &m_UserInfo, 1,
ServerManage::CMD::UserLogin, 0);
// 현재 관리자 정보를 준다.
ServerManage::SendUserInfo(GetBufferFactory(), 0,
&CToolUserManager::GetInstance().GetManageUser(), 1,
ServerManage::CMD::ManagerInfo, 0);
// 다른 유저들의 로그인 정보를 받는다.
CToolUserManager::GetInstance().SendAllLoginUserInfo(GetSession());
#pragma todo("서버 Setup을 준다")
}
ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), &m_UserInfo, 1,
ServerManage::CMD::AuthUser, cError);
return (0 == cError);
}
bool CManageToolServerDispatch::AddUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().AddUser(*lpUserInfo))
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Adduser failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
cError = ServerManage::ADD_USER_FAILED;
}
DETLOG3(g_Log, "ID:%s/IP:%s/Adduser success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
memset(lpUserInfo->szPassword, 0, ServerManage::UserInfo::PASS_LEN);
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), lpUserInfo, 1,
ServerManage::CMD::AddUser, cError);
}
bool CManageToolServerDispatch::DelUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().DelUser(lpUserInfo->szID))
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Delete user failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
cError = ServerManage::DELETE_USER_FAILED;
}
DETLOG3(g_Log, "ID:%s/IP:%s/Delete user success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), lpUserInfo, 1,
ServerManage::CMD::DelUser, cError);
}
bool CManageToolServerDispatch::ModUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().ModifyUser(*lpUserInfo))
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Modify user failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
cError = ServerManage::MODIFY_USER_FAILED;
}
DETLOG3(g_Log, "ID:%s/IP:%s/Modify user success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
memset(lpUserInfo->szPassword, 0, ServerManage::UserInfo::PASS_LEN);
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), lpUserInfo, 1,
ServerManage::CMD::ModUser, cError);
}
bool CManageToolServerDispatch::UserList(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 0))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().SendAllUserInfo(GetSession()))
{
ERRLOG2(g_Log, "ID:%s/IP:%s/Send userlist failed",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
cError = ServerManage::SEND_USER_LIST_FAILED;
}
DETLOG2(g_Log, "ID:%s/IP:%s/Send userlist success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), 0, 0,
ServerManage::CMD::UserList, cError);
}
bool CManageToolServerDispatch::RequestPromote(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError)
{
const ServerManage::UserInfo& masterUser = CToolUserManager::GetInstance().GetManageUser();
if(0 == masterUser.szID[0] || m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
// 현재 Promote유저가 있는지 살핀다. 없거나, Master면 바로 Promote를 하고 Broadcast를 한다.
CToolUserManager::GetInstance().Promote(m_UserInfo);
ServerManage::SendUserInfo(GetBufferFactory(), 0,
&m_UserInfo, 1, ServerManage::CMD::ManagerInfo, 0);
}
else if(m_UserInfo.usAdminLevel == CToolUserManager::GENERAL)
{
// 현재 Promote유저가 있고, 내가 General레벨이면, 정중히 요청을 한다.
CManageToolServerDispatch* lpToolUserDispatch =
CToolUserManager::GetInstance().GetManageUserDispatch();
ServerManage::UserInfo userInfo = m_UserInfo;
userInfo.usSubCommand = ServerManage::CMD::REQUEST_TAKEBACK_PROMOTE;
// 아직 연결되어 있으면 요청 패킷을 보냄.
if(0 == lpToolUserDispatch
|| !ServerManage::SendUserInfo(GetBufferFactory(),
&lpToolUserDispatch->GetSession(), &userInfo, 1,
ServerManage::CMD::RequestUserReaction, 0))
{
cError = ServerManage::PROMOTE_TAKEBACK_FAILED;
}
}
else
{
cError = ServerManage::PROMOTE_USER_FAILED;
}
}
if(0 != cError)
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Promote user failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), 0, 0,
ServerManage::CMD::RequestPromote, cError);
}
return true;
}
bool CManageToolServerDispatch::ProcessUserReaction(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
CManageToolServerDispatch* lpRequestDispatch = 0;
if(0 == cError)
{
switch(lpUserInfo->usSubCommand)
{
case ServerManage::CMD::ACK_TAKEBACK_PROMOTE:
// 처음 요청자를 찾아서 Promote 성공 패킷을 보낸다.
lpRequestDispatch = CToolUserManager::GetInstance().GetUserDispatch(lpUserInfo->szID);
if(0 != lpRequestDispatch)
{
ServerManage::UserInfo manager = lpRequestDispatch->GetUserInfo();
// Promote 처리.
CToolUserManager::GetInstance().Promote(manager);
// 누가 Manager인지 만천하에 알린다.
ServerManage::SendUserInfo(GetBufferFactory(), 0,
&manager, 1, ServerManage::CMD::ManagerInfo, 0);
// 본인에게 Ack.
ServerManage::SendUserInfo(GetBufferFactory(), &lpRequestDispatch->GetSession(),
&manager, 1, ServerManage::CMD::RequestPromote, 0);
}
break;
case ServerManage::CMD::NAK_TAKEBACK_PROMOTE:
// 처음 요청자를 찾아서 Promote 실패 패킷을 보낸다.
lpRequestDispatch = CToolUserManager::GetInstance().GetUserDispatch(lpUserInfo->szID);
if(0 != lpRequestDispatch)
{
ServerManage::SendUserInfo(GetBufferFactory(), &lpRequestDispatch->GetSession(),
&m_UserInfo, 1, ServerManage::CMD::RequestPromote, ServerManage::REJECTED_PROMOTE_USER);
}
break;
}
}
return true;
}

View File

@@ -0,0 +1,47 @@
#include "stdafx.h"
#include "StatServerDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Log/ServerLog.h>
enum StatServerConst
{
STAT_SERVER_DEFAULT_DISPATCH_NUM = 10
};
CStatServerDispatch::CStatServerDispatch(CSession& Session)
: CRylServerDispatch(Session, STAT_SERVER_DEFAULT_DISPATCH_NUM)
{
DETLOG1(g_Log, "this:0x%p/CStatServerDispatch Created", this);
}
CStatServerDispatch::~CStatServerDispatch()
{
DETLOG1(g_Log, "this:0x%p/CStatServerDispatch Destroyed", this);
}
CSingleDispatch& CStatServerDispatch::GetDispatch()
{
static CSingleDispatch statServerDispatch;
return statServerDispatch;
}
void CStatServerDispatch::Connected()
{
GetDispatch().SetDispatch(this);
}
void CStatServerDispatch::Disconnected()
{
GetDispatch().RemoveDispatch(this);
}
bool CStatServerDispatch::DispatchPacket(PktBase* lpPktBase)
{
return true;
}

View File

@@ -0,0 +1,26 @@
#ifndef _STAT_SERVER_DISPATCH_H_
#define _STAT_SERVER_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
class CStatServerDispatch : public CRylServerDispatch
{
public:
CStatServerDispatch(CSession& Session);
virtual ~CStatServerDispatch();
static CSingleDispatch& GetDispatch();
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
};
#endif

View File

@@ -0,0 +1,58 @@
#include "stdafx.h"
#include "StatServerMultiDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <Log/ServerLog.h>
#include <Setup/SetupClient.h>
enum StatServerConst
{
STAT_SERVER_DEFAULT_DISPATCH_NUM = 10
};
CMultiDispatch& CStatServerMultiDispatch::GetDispatchTable()
{
static CMultiDispatch multiDispatch;
return multiDispatch;
}
CStatServerMultiDispatch::CStatServerMultiDispatch(CSession& Session)
: CRylServerDispatch(Session, STAT_SERVER_DEFAULT_DISPATCH_NUM)
{
DETLOG1(g_Log, "this:0x%p/CStatServerMultiDispatch Created", this);
}
CStatServerMultiDispatch::~CStatServerMultiDispatch()
{
DETLOG1(g_Log, "this:0x%p/CStatServerMultiDispatch Destroyed", this);
}
void CStatServerMultiDispatch::Connected()
{
// 접속 IP를 key로 잡아서 세팅한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().SetDispatch(dwDispatchID, this);
DETLOG2(g_Log, "this:0x%p/Key:%u/CStatServerMultiDispatch Connected", this, dwDispatchID);
}
void CStatServerMultiDispatch::Disconnected()
{
// 접속 IP를 key로 잡아서 삭제한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().RemoveDispatch(dwDispatchID);
DETLOG2(g_Log, "this:0x%p/Key:%u/CStatServerMultiDispatch Disconnected", this, dwDispatchID);
}
bool CStatServerMultiDispatch::DispatchPacket(PktBase* lpPktBase)
{
return true;
}

View File

@@ -0,0 +1,25 @@
#ifndef _STAT_SERVER_MULTI_DISPATCH_H_
#define _STAT_SERVER_MULTI_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
class CStatServerMultiDispatch : public CRylServerDispatch
{
public:
static CMultiDispatch& GetDispatchTable();
CStatServerMultiDispatch(CSession& Session);
virtual ~CStatServerMultiDispatch();
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
};
#endif

View File

@@ -0,0 +1,208 @@
#include "stdafx.h"
#include "SendManagePacket.h"
#include <tchar.h>
#include <Network/Session/Session.h>
#include <Network/Dispatch/Dispatch.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Stream/Buffer/Buffer.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Utility/Compress/MiniLZO/MiniLZOWrapper.h>
#include <UserManage/ToolUserManageTable.h>
#include <Log/ServerLog.h>
/*!
\brief 관리 패킷 전송
\param Session 세션
\param cCmd 커맨드
\param nMessage 윈도우 메시지 번호
\param wParam WPARAM
\param lParam LPARAM
\param dwRunID RunID
\param usDataLen 데이터 길이
\param usFlags 추가 데이터 플래그
\param lpData 보낼 데이터
\param cError 에러 커맨드
\return 패킷 전송 성공 여부
*/
bool ServerManage::SendManagePacket(CSession& Session,
unsigned char cCmd,
unsigned int nMessage,
WPARAM wParam,
LPARAM lParam,
unsigned long dwRunID,
unsigned short usDataLen,
unsigned short usFlags,
const void* lpData,
unsigned char cError)
{
CBuffer* lpBuffer = CREATE_BUFFER(Session.GetPolicy().GetBufferFactory(),
(sizeof(ManageCommand) + usDataLen));
if(0 != lpBuffer)
{
ManageCommand* lpManageCommand = reinterpret_cast<ManageCommand*>(lpBuffer->wr_ptr());
lpManageCommand->nMessage = nMessage; // 메시지 번호
lpManageCommand->wParam = wParam; // 파라미터1
lpManageCommand->lParam = lParam; // 파라미터2
lpManageCommand->dwRunID = dwRunID; // 메세지 받을 곳의 IP
lpManageCommand->usDataLen = (0 != lpData) ? usDataLen : 0; // 추가 데이터 길이
lpManageCommand->usFlags = usFlags; // 기타 커맨드 (내용에 따라서 다름)
if(0 != lpData)
{
memcpy(reinterpret_cast<char*>(lpManageCommand + 1), lpData, usDataLen);
}
if(PacketWrap::WrapCrypt(lpBuffer, sizeof(ManageCommand) + usDataLen, cCmd, 0, cError)
&& Session.SendPending(lpBuffer))
{
return true;
}
SAFE_RELEASE_BUFFER(lpBuffer);
}
return false;
}
/*!
\brief 관리 패킷 전송
\param bufferFactory BufferFactory
\param lpTarget 세션. 0이면 Broadcast
\param lpUserInfo 유저 정보 (내부적으로 패스워드만 제거하고 보낸다)
\param cUserInfoNum 유저 정보 개수
\param cCommand 커맨드.
\param cError 에러.
\return 패킷 전송 성공 여부
*/
bool ServerManage::SendUserInfo(CBufferFactory& bufferFactory,
CSession* lpTarget,
const ServerManage::UserInfo* lpUserInfo,
unsigned char cUserInfoNum,
unsigned char cCommand,
unsigned char cError)
{
// 다른 유저들에게 자신이 추가되었다는 메시지를 던진다.
CBuffer* lpBuffer = CREATE_BUFFER(bufferFactory,
sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum);
CBuffer* lpCompressedBuffer = CREATE_BUFFER(bufferFactory,
CMiniLZO::GetLeastCompressBuffer(sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum));
if(0 != lpBuffer && 0 != lpCompressedBuffer)
{
ServerManage::UserCommand* lpUserCommand = reinterpret_cast<ServerManage::UserCommand*>(lpBuffer->wr_ptr());
ServerManage::UserInfo* lpFirstUserInfo = reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
ServerManage::UserInfo* lpLastUserInfo = lpFirstUserInfo + cUserInfoNum;
lpUserCommand->cUserInfoNum = cUserInfoNum;
std::copy(lpUserInfo, lpUserInfo + cUserInfoNum, lpFirstUserInfo);
for(ServerManage::UserInfo* lpTempUserInfo = lpFirstUserInfo;
lpTempUserInfo != lpLastUserInfo; ++lpTempUserInfo)
{
memset(lpTempUserInfo->szPassword, 0, sizeof(ServerManage::UserInfo::PASS_LEN) * sizeof(TCHAR));
}
if(PacketWrap::WrapCompress(lpCompressedBuffer, lpBuffer->rd_ptr(),
sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum,
cCommand, 0, cError))
{
if(lpTarget)
{
if(lpTarget->SendPending(lpCompressedBuffer))
{
SAFE_RELEASE_BUFFER(lpBuffer);
return true;
}
}
else
{
CToolUserManager::GetInstance().SendToAllLoginUser(
lpCompressedBuffer->rd_ptr(), lpCompressedBuffer->length(), lpUserCommand->GetCmd());
SAFE_RELEASE_BUFFER(lpCompressedBuffer);
SAFE_RELEASE_BUFFER(lpBuffer);
return true;
}
}
}
SAFE_RELEASE_BUFFER(lpCompressedBuffer);
SAFE_RELEASE_BUFFER(lpBuffer);
return false;
}
bool ServerManage::CheckUserPacketLength(PktBase* lpPktBase, int nExpectUserInfoNum)
{
PktBase::LengthType nLength = lpPktBase->GetLen();
if(nLength < sizeof(ServerManage::UserCommand))
{
return false;
}
ServerManage::UserCommand* lpUserCommand = reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo = reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(0 < nExpectUserInfoNum)
{
if(nExpectUserInfoNum != lpUserCommand->cUserInfoNum ||
nLength != sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * nExpectUserInfoNum)
{
ERRLOG2(g_Log, "Invalid packet size : userinfo num : %d, packet size : %d",
lpUserCommand->cUserInfoNum, nLength);
return false;
}
}
else if(nLength != sizeof(ServerManage::UserCommand))
{
return false;
}
return true;
}
bool ServerManage::CheckManagePacketLength(PktBase* lpPktBase)
{
unsigned short usPacketLength = lpPktBase->GetLen();
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(usPacketLength < sizeof(ServerManage::ManageCommand) ||
(usPacketLength != lpManageCommand->usDataLen + sizeof(ServerManage::ManageCommand)))
{
ERRLOG2(g_Log, "Invalid packet size : DataLen : %d, Packet size : %d",
lpManageCommand->usDataLen, lpPktBase->GetLen());
return false;
}
return true;
}
ServerManage::CSendManagePacketToClient::CSendManagePacketToClient(ManageCommand& manageCommand,
const char* lpData)
: m_ManageCommand(manageCommand),
m_lpData(lpData)
{
}
bool ServerManage::CSendManagePacketToClient::operator() (CPacketDispatch& dispatch)
{
return SendManagePacket(dispatch.GetSession(),
m_ManageCommand.GetCmd(), m_ManageCommand.nMessage,
m_ManageCommand.wParam, m_ManageCommand.lParam,
m_ManageCommand.dwRunID, m_ManageCommand.usDataLen, m_ManageCommand.usFlags,
m_lpData, static_cast<unsigned char>(m_ManageCommand.GetError()));
}

View File

@@ -0,0 +1,67 @@
#ifndef _SEND_MANAGE_PACKET_H_
#define _SEND_MANAGE_PACKET_H_
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <windows.h>
// forward decl.
struct PktBase;
class CSession;
class CBufferFactory;
class CPacketDispatch;
namespace ServerManage
{
// forward decl.
struct ManageCommand;
struct UserInfo;
bool CheckManagePacketLength(PktBase* lpPktBase);
bool CheckUserPacketLength(PktBase* lpPktBase, int nExpectUserInfoNum = -1);
// 서버 관리 패킷을 보낸다.
bool SendManagePacket(
CSession& Session, // 세션
unsigned char cCmd, // 커맨드
unsigned int nMessage, // 윈도우 메시지 번호
WPARAM wParam, // WPARAM
LPARAM lParam, // LPARAM
unsigned long dwRunID, // RunID
unsigned short usDataLen, // 데이터 길이
unsigned short usFlags, // 추가 데이터 플래그
const void* lpData, // 보낼 데이터
unsigned char cError); // 에러 커맨드
// 유저 정보 패킷을 보낸다.
bool SendUserInfo(
CBufferFactory& bufferFactory, // BufferFactory
CSession* lpTarget, // 세션. 0이면 Broadcast
const ServerManage::UserInfo* lpUserInfo, // ( )
unsigned char cUserInfoNum, // 유저 정보 개수
unsigned char cCommand, // 커맨드.
unsigned char cError); // 에러.
class CSendManagePacketToClient
{
public:
CSendManagePacketToClient(ManageCommand& manageCommand, const char* lpData);
bool operator() (CPacketDispatch& dispatch);
bool operator() (unsigned long dwKeyType, CPacketDispatch& dispatch)
{ return operator() (dispatch); }
private:
ManageCommand& m_ManageCommand;
const char* m_lpData;
};
};
#endif