1
0
forked from metin2/server
server/game/src/desc.cpp
2022-03-05 12:44:06 +02:00

1135 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "config.h"
#include "utils.h"
#include "desc.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "char.h"
#include "protocol.h"
#include "packet.h"
#include "messenger_manager.h"
#include "sectree_manager.h"
#include "p2p.h"
#include "buffer_manager.h"
#include "sequence.h"
#include "guild.h"
#include "guild_manager.h"
#include "TrafficProfiler.h"
#include "locale_service.h"
#include "HackShield.h"
#include "log.h"
extern int max_bytes_written;
extern int current_bytes_written;
extern int total_bytes_written;
DESC::DESC()
{
Initialize();
}
DESC::~DESC()
{
}
void DESC::Initialize()
{
m_bDestroyed = false;
m_pInputProcessor = NULL;
m_lpFdw = NULL;
m_sock = INVALID_SOCKET;
m_iPhase = PHASE_CLOSE;
m_dwHandle = 0;
m_wPort = 0;
m_LastTryToConnectTime = 0;
m_lpInputBuffer = NULL;
m_iMinInputBufferLen = 0;
m_dwHandshake = 0;
m_dwHandshakeSentTime = 0;
m_iHandshakeRetry = 0;
m_dwClientTime = 0;
m_bHandshaking = false;
m_lpBufferedOutputBuffer = NULL;
m_lpOutputBuffer = NULL;
m_pkPingEvent = NULL;
m_lpCharacter = NULL;
memset( &m_accountTable, 0, sizeof(m_accountTable) );
memset( &m_SockAddr, 0, sizeof(m_SockAddr) );
memset( &m_UDPSockAddr, 0, sizeof(m_UDPSockAddr) );
m_pLogFile = NULL;
#ifndef _IMPROVED_PACKET_ENCRYPTION_
m_bEncrypted = false;
#endif
m_wP2PPort = 0;
m_bP2PChannel = 0;
m_bAdminMode = false;
m_bPong = true;
m_bChannelStatusRequested = false;
m_iCurrentSequence = 0;
m_dwMatrixRows = m_dwMatrixCols = 0;
m_bMatrixTryCount = 0;
m_pkLoginKey = NULL;
m_dwLoginKey = 0;
m_dwPanamaKey = 0;
#ifndef _IMPROVED_PACKET_ENCRYPTION_
memset( m_adwDecryptionKey, 0, sizeof(m_adwDecryptionKey) );
memset( m_adwEncryptionKey, 0, sizeof(m_adwEncryptionKey) );
#endif
m_bCRCMagicCubeIdx = 0;
m_dwProcCRC = 0;
m_dwFileCRC = 0;
m_bHackCRCQuery = 0;
m_dwBillingExpireSecond = 0;
m_outtime = 0;
m_playtime = 0;
m_offtime = 0;
m_pkDisconnectEvent = NULL;
m_seq_vector.clear();
}
void DESC::Destroy()
{
if (m_bDestroyed) {
return;
}
m_bDestroyed = true;
if (m_pkLoginKey)
m_pkLoginKey->Expire();
if (GetAccountTable().id)
DESC_MANAGER::instance().DisconnectAccount(GetAccountTable().login);
if (m_pLogFile)
{
fclose(m_pLogFile);
m_pLogFile = NULL;
}
if (m_lpCharacter)
{
m_lpCharacter->Disconnect("DESC::~DESC");
m_lpCharacter = NULL;
}
SAFE_BUFFER_DELETE(m_lpOutputBuffer);
SAFE_BUFFER_DELETE(m_lpInputBuffer);
event_cancel(&m_pkPingEvent);
event_cancel(&m_pkDisconnectEvent);
if (!g_bAuthServer)
{
if (m_accountTable.login[0] && m_accountTable.passwd[0])
{
TLogoutPacket pack;
strlcpy(pack.login, m_accountTable.login, sizeof(pack.login));
strlcpy(pack.passwd, m_accountTable.passwd, sizeof(pack.passwd));
db_clientdesc->DBPacket(HEADER_GD_LOGOUT, m_dwHandle, &pack, sizeof(TLogoutPacket));
}
}
if (m_sock != INVALID_SOCKET)
{
sys_log(0, "SYSTEM: closing socket. DESC #%d", m_sock);
Log("SYSTEM: closing socket. DESC #%d", m_sock);
fdwatch_del_fd(m_lpFdw, m_sock);
#ifdef _IMPROVED_PACKET_ENCRYPTION_
cipher_.CleanUp();
#endif
socket_close(m_sock);
m_sock = INVALID_SOCKET;
}
m_seq_vector.clear();
}
EVENTFUNC(ping_event)
{
DESC::desc_event_info* info = dynamic_cast<DESC::desc_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "ping_event> <Factor> Null pointer" );
return 0;
}
LPDESC desc = info->desc;
if (desc->IsAdminMode())
return (ping_event_second_cycle);
if (!desc->IsPong())
{
sys_log(0, "PING_EVENT: no pong %s", desc->GetHostName());
desc->SetPhase(PHASE_CLOSE);
return (ping_event_second_cycle);
}
else
{
TPacketGCPing p;
p.header = HEADER_GC_PING;
desc->Packet(&p, sizeof(struct packet_ping));
desc->SetPong(false);
}
#ifdef ENABLE_LIMIT_TIME
if ((unsigned)get_global_time() >= GLOBAL_LIMIT_TIME)
{
extern void ClearAdminPages();
ClearAdminPages();
extern g_bShutdown;
g_bShutdown = true;
}
#endif
desc->SendHandshake(get_dword_time(), 0);
return (ping_event_second_cycle);
}
bool DESC::IsPong()
{
return m_bPong;
}
void DESC::SetPong(bool b)
{
m_bPong = b;
}
bool DESC::Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSockAddr, DWORD _handle, DWORD _handshake)
{
m_lpFdw = _fdw;
m_sock = _fd;
m_stHost = inet_ntoa(c_rSockAddr.sin_addr);
m_wPort = c_rSockAddr.sin_port;
m_dwHandle = _handle;
//if (LC_IsEurope() == true || LC_IsNewCIBN())
// m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2);
//else
//NOTE: <20>̰<EFBFBD> <20><><EFBFBD>󺰷<EFBFBD> <20>ٸ<EFBFBD><D9B8><EFBFBD> <20><><EFBFBD>ƾ<EFBFBD><C6BE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֳ<EFBFBD>?
m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2);
m_iMinInputBufferLen = MAX_INPUT_LEN >> 1;
m_lpInputBuffer = buffer_new(MAX_INPUT_LEN);
m_SockAddr = c_rSockAddr;
fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);
// Ping Event
desc_event_info* info = AllocEventInfo<desc_event_info>();
info->desc = this;
assert(m_pkPingEvent == NULL);
m_pkPingEvent = event_create(ping_event, info, ping_event_second_cycle);
#ifndef _IMPROVED_PACKET_ENCRYPTION_
if (LC_IsEurope())
{
thecore_memcpy(m_adwEncryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
thecore_memcpy(m_adwDecryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
}
else
{
thecore_memcpy(m_adwEncryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
thecore_memcpy(m_adwDecryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
// Set Phase to handshake
SetPhase(PHASE_HANDSHAKE);
StartHandshake(_handshake);
sys_log(0, "SYSTEM: new connection from [%s] fd: %d handshake %u output input_len %d, ptr %p",
m_stHost.c_str(), m_sock, m_dwHandshake, buffer_size(m_lpInputBuffer), this);
Log("SYSTEM: new connection from [%s] fd: %d handshake %u ptr %p", m_stHost.c_str(), m_sock, m_dwHandshake, this);
return true;
}
int DESC::ProcessInput()
{
ssize_t bytes_read;
if (!m_lpInputBuffer)
{
sys_err("DESC::ProcessInput : nil input buffer");
return -1;
}
buffer_adjust_size(m_lpInputBuffer, m_iMinInputBufferLen);
bytes_read = socket_read(m_sock, (char *) buffer_write_peek(m_lpInputBuffer), buffer_has_space(m_lpInputBuffer));
if (bytes_read < 0)
return -1;
else if (bytes_read == 0)
return 0;
buffer_write_proceed(m_lpInputBuffer, bytes_read);
if (!m_pInputProcessor)
sys_err("no input processor");
#ifdef _IMPROVED_PACKET_ENCRYPTION_
else
{
if (cipher_.activated()) {
cipher_.Decrypt(const_cast<void*>(buffer_read_peek(m_lpInputBuffer)), buffer_size(m_lpInputBuffer));
}
int iBytesProceed = 0;
// false<73><65> <20><><EFBFBD><EFBFBD> <20>Ǹ<EFBFBD> <20>ٸ<EFBFBD> phase<73><65> <20>ٲ<EFBFBD> <20><><EFBFBD>̹Ƿ<CCB9> <20>ٽ<EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>!
while (!m_pInputProcessor->Process(this, buffer_read_peek(m_lpInputBuffer), buffer_size(m_lpInputBuffer), iBytesProceed))
{
buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
iBytesProceed = 0;
}
buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
}
#else
else if (!m_bEncrypted)
{
int iBytesProceed = 0;
// false<73><65> <20><><EFBFBD><EFBFBD> <20>Ǹ<EFBFBD> <20>ٸ<EFBFBD> phase<73><65> <20>ٲ<EFBFBD> <20><><EFBFBD>̹Ƿ<CCB9> <20>ٽ<EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>!
while (!m_pInputProcessor->Process(this, buffer_read_peek(m_lpInputBuffer), buffer_size(m_lpInputBuffer), iBytesProceed))
{
buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
iBytesProceed = 0;
}
buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
}
else
{
int iSizeBuffer = buffer_size(m_lpInputBuffer);
// 8<><38><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD>θ<EFBFBD> ó<><C3B3><EFBFBD>Ѵ<EFBFBD>. 8<><38><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20>߸<EFBFBD><DFB8><EFBFBD> <20><>ȣȭ <20><><EFBFBD>۸<EFBFBD> <20><>ȣȭ
// <20><> <20><><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> ©<><C2A9><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD> <20>Ѵ<EFBFBD>.
if (iSizeBuffer & 7) // & 7<><37> % 8<><38> <20><><EFBFBD><EFBFBD>. 2<><32> <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
iSizeBuffer -= iSizeBuffer & 7;
if (iSizeBuffer > 0)
{
TEMP_BUFFER tempbuf;
LPBUFFER lpBufferDecrypt = tempbuf.getptr();
buffer_adjust_size(lpBufferDecrypt, iSizeBuffer);
int iSizeAfter = TEA_Decrypt((DWORD *) buffer_write_peek(lpBufferDecrypt),
(DWORD *) buffer_read_peek(m_lpInputBuffer),
GetDecryptionKey(),
iSizeBuffer);
buffer_write_proceed(lpBufferDecrypt, iSizeAfter);
int iBytesProceed = 0;
// false<73><65> <20><><EFBFBD><EFBFBD> <20>Ǹ<EFBFBD> <20>ٸ<EFBFBD> phase<73><65> <20>ٲ<EFBFBD> <20><><EFBFBD>̹Ƿ<CCB9> <20>ٽ<EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>!
while (!m_pInputProcessor->Process(this, buffer_read_peek(lpBufferDecrypt), buffer_size(lpBufferDecrypt), iBytesProceed))
{
if (iBytesProceed > iSizeBuffer)
{
buffer_read_proceed(m_lpInputBuffer, iSizeBuffer);
iSizeBuffer = 0;
iBytesProceed = 0;
break;
}
buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
iSizeBuffer -= iBytesProceed;
buffer_read_proceed(lpBufferDecrypt, iBytesProceed);
iBytesProceed = 0;
}
buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
}
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
return (bytes_read);
}
int DESC::ProcessOutput()
{
if (buffer_size(m_lpOutputBuffer) <= 0)
return 0;
int buffer_left = fdwatch_get_buffer_size(m_lpFdw, m_sock);
if (buffer_left <= 0)
return 0;
int bytes_to_write = MIN(buffer_left, buffer_size(m_lpOutputBuffer));
if (bytes_to_write == 0)
return 0;
int result = socket_write(m_sock, (const char *) buffer_read_peek(m_lpOutputBuffer), bytes_to_write);
if (result == 0)
{
//sys_log(0, "%d bytes written to %s first %u", bytes_to_write, GetHostName(), *(BYTE *) buffer_read_peek(m_lpOutputBuffer));
//Log("%d bytes written", bytes_to_write);
max_bytes_written = MAX(bytes_to_write, max_bytes_written);
total_bytes_written += bytes_to_write;
current_bytes_written += bytes_to_write;
buffer_read_proceed(m_lpOutputBuffer, bytes_to_write);
if (buffer_size(m_lpOutputBuffer) != 0)
fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, true);
}
return (result);
}
void DESC::BufferedPacket(const void * c_pvData, int iSize)
{
if (m_iPhase == PHASE_CLOSE)
return;
if (!m_lpBufferedOutputBuffer)
m_lpBufferedOutputBuffer = buffer_new(MAX(1024, iSize));
buffer_write(m_lpBufferedOutputBuffer, c_pvData, iSize);
}
void DESC::Packet(const void * c_pvData, int iSize)
{
assert(iSize > 0);
if (m_iPhase == PHASE_CLOSE) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD>¸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
return;
if (m_stRelayName.length() != 0)
{
// Relay <20><>Ŷ<EFBFBD><C5B6> <20><>ȣȭ<C8A3><C8AD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
TPacketGGRelay p;
p.bHeader = HEADER_GG_RELAY;
strlcpy(p.szName, m_stRelayName.c_str(), sizeof(p.szName));
p.lSize = iSize;
if (!packet_encode(m_lpOutputBuffer, &p, sizeof(p)))
{
m_iPhase = PHASE_CLOSE;
return;
}
m_stRelayName.clear();
if (!packet_encode(m_lpOutputBuffer, c_pvData, iSize))
{
m_iPhase = PHASE_CLOSE;
return;
}
}
else
{
if (m_lpBufferedOutputBuffer)
{
buffer_write(m_lpBufferedOutputBuffer, c_pvData, iSize);
c_pvData = buffer_read_peek(m_lpBufferedOutputBuffer);
iSize = buffer_size(m_lpBufferedOutputBuffer);
}
// TRAFFIC_PROFILE
if (g_bTrafficProfileOn)
TrafficProfiler::instance().Report(TrafficProfiler::IODIR_OUTPUT, *(BYTE *) c_pvData, iSize);
// END_OF_TRAFFIC_PROFILER
#ifdef _IMPROVED_PACKET_ENCRYPTION_
void* buf = buffer_write_peek(m_lpOutputBuffer);
if (packet_encode(m_lpOutputBuffer, c_pvData, iSize))
{
if (cipher_.activated()) {
cipher_.Encrypt(buf, iSize);
}
}
else
{
m_iPhase = PHASE_CLOSE;
}
#else
if (!m_bEncrypted)
{
if (!packet_encode(m_lpOutputBuffer, c_pvData, iSize))
{
m_iPhase = PHASE_CLOSE;
}
}
else
{
if (buffer_has_space(m_lpOutputBuffer) < iSize + 8)
{
sys_err("desc buffer mem_size overflow. memsize(%u) write_pos(%u) iSize(%d)",
m_lpOutputBuffer->mem_size, m_lpOutputBuffer->write_point_pos, iSize);
m_iPhase = PHASE_CLOSE;
}
else
{
// <20><>ȣȭ<C8A3><C8AD> <20>ʿ<EFBFBD><CABF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ũ<>⸦ Ȯ<><C8AE><EFBFBD>Ѵ<EFBFBD>.
/* buffer_adjust_size(m_lpOutputBuffer, iSize + 8); */
DWORD * pdwWritePoint = (DWORD *) buffer_write_peek(m_lpOutputBuffer);
if (packet_encode(m_lpOutputBuffer, c_pvData, iSize))
{
int iSize2 = TEA_Encrypt(pdwWritePoint, pdwWritePoint, GetEncryptionKey(), iSize);
if (iSize2 > iSize)
buffer_write_proceed(m_lpOutputBuffer, iSize2 - iSize);
}
}
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
SAFE_BUFFER_DELETE(m_lpBufferedOutputBuffer);
}
//sys_log(0, "%d bytes written (first byte %d)", iSize, *(BYTE *) c_pvData);
if (m_iPhase != PHASE_CLOSE)
fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, true);
}
void DESC::LargePacket(const void * c_pvData, int iSize)
{
buffer_adjust_size(m_lpOutputBuffer, iSize);
sys_log(0, "LargePacket Size %d", iSize, buffer_size(m_lpOutputBuffer));
Packet(c_pvData, iSize);
}
void DESC::SetPhase(int _phase)
{
m_iPhase = _phase;
TPacketGCPhase pack;
pack.header = HEADER_GC_PHASE;
pack.phase = _phase;
Packet(&pack, sizeof(TPacketGCPhase));
switch (m_iPhase)
{
case PHASE_CLOSE:
// <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD>ʹ<EFBFBD><CDB4><EFBFBD><EFBFBD><EFBFBD> <20>Ǹ鼭 <20><><EFBFBD><EFBFBD>
//MessengerManager::instance().Logout(GetAccountTable().login);
m_pInputProcessor = &m_inputClose;
break;
case PHASE_HANDSHAKE:
m_pInputProcessor = &m_inputHandshake;
break;
case PHASE_SELECT:
// <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD>ʹ<EFBFBD><CDB4><EFBFBD><EFBFBD><EFBFBD> <20>Ǹ鼭 <20><><EFBFBD><EFBFBD>
//MessengerManager::instance().Logout(GetAccountTable().login); // <20>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> break <20>Ȱ<EFBFBD>
case PHASE_LOGIN:
case PHASE_LOADING:
#ifndef _IMPROVED_PACKET_ENCRYPTION_
m_bEncrypted = true;
#endif
m_pInputProcessor = &m_inputLogin;
break;
case PHASE_GAME:
case PHASE_DEAD:
#ifndef _IMPROVED_PACKET_ENCRYPTION_
m_bEncrypted = true;
#endif
m_pInputProcessor = &m_inputMain;
break;
case PHASE_AUTH:
#ifndef _IMPROVED_PACKET_ENCRYPTION_
m_bEncrypted = true;
#endif
m_pInputProcessor = &m_inputAuth;
sys_log(0, "AUTH_PHASE %p", this);
break;
}
}
void DESC::BindAccountTable(TAccountTable * pAccountTable)
{
assert(pAccountTable != NULL);
thecore_memcpy(&m_accountTable, pAccountTable, sizeof(TAccountTable));
DESC_MANAGER::instance().ConnectAccount(m_accountTable.login, this);
}
void DESC::UDPGrant(const struct sockaddr_in & c_rSockAddr)
{
m_UDPSockAddr = c_rSockAddr;
TPacketGCBindUDP pack;
pack.header = HEADER_GC_BINDUDP;
pack.addr = m_UDPSockAddr.sin_addr.s_addr;
pack.port = m_UDPSockAddr.sin_port;
Packet(&pack, sizeof(TPacketGCBindUDP));
}
void DESC::Log(const char * format, ...)
{
if (!m_pLogFile)
return;
va_list args;
time_t ct = get_global_time();
struct tm tm = *localtime(&ct);
fprintf(m_pLogFile,
"%02d %02d %02d:%02d:%02d | ",
tm.tm_mon + 1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec);
va_start(args, format);
vfprintf(m_pLogFile, format, args);
va_end(args);
fputs("\n", m_pLogFile);
fflush(m_pLogFile);
}
void DESC::StartHandshake(DWORD _handshake)
{
// Handshake
m_dwHandshake = _handshake;
SendHandshake(get_dword_time(), 0);
m_iHandshakeRetry = 0;
}
void DESC::SendHandshake(DWORD dwCurTime, long lNewDelta)
{
TPacketGCHandshake pack;
pack.bHeader = HEADER_GC_HANDSHAKE;
pack.dwHandshake = m_dwHandshake;
pack.dwTime = dwCurTime;
pack.lDelta = lNewDelta;
Packet(&pack, sizeof(TPacketGCHandshake));
m_dwHandshakeSentTime = dwCurTime;
m_bHandshaking = true;
}
bool DESC::HandshakeProcess(DWORD dwTime, long lDelta, bool bInfiniteRetry)
{
DWORD dwCurTime = get_dword_time();
if (lDelta < 0)
{
sys_err("Desc::HandshakeProcess : value error (lDelta %d, ip %s)", lDelta, m_stHost.c_str());
return false;
}
int bias = (int) (dwCurTime - (dwTime + lDelta));
if (bias >= 0 && bias <= 50)
{
if (bInfiniteRetry)
{
BYTE bHeader = HEADER_GC_TIME_SYNC;
Packet(&bHeader, sizeof(BYTE));
}
if (GetCharacter())
sys_log(0, "Handshake: client_time %u server_time %u name: %s", m_dwClientTime, dwCurTime, GetCharacter()->GetName());
else
sys_log(0, "Handshake: client_time %u server_time %u", m_dwClientTime, dwCurTime, lDelta);
m_dwClientTime = dwCurTime;
m_bHandshaking = false;
return true;
}
long lNewDelta = (long) (dwCurTime - dwTime) / 2;
if (lNewDelta < 0)
{
sys_log(0, "Handshake: lower than zero %d", lNewDelta);
lNewDelta = (dwCurTime - m_dwHandshakeSentTime) / 2;
}
sys_log(1, "Handshake: ServerTime %u dwTime %u lDelta %d SentTime %u lNewDelta %d", dwCurTime, dwTime, lDelta, m_dwHandshakeSentTime, lNewDelta);
if (!bInfiniteRetry)
if (++m_iHandshakeRetry > HANDSHAKE_RETRY_LIMIT)
{
sys_err("handshake retry limit reached! (limit %d character %s)",
HANDSHAKE_RETRY_LIMIT, GetCharacter() ? GetCharacter()->GetName() : "!NO CHARACTER!");
SetPhase(PHASE_CLOSE);
return false;
}
SendHandshake(dwCurTime, lNewDelta);
return false;
}
bool DESC::IsHandshaking()
{
return m_bHandshaking;
}
DWORD DESC::GetClientTime()
{
return m_dwClientTime;
}
#ifdef _IMPROVED_PACKET_ENCRYPTION_
void DESC::SendKeyAgreement()
{
TPacketKeyAgreement packet;
size_t data_length = TPacketKeyAgreement::MAX_DATA_LEN;
size_t agreed_length = cipher_.Prepare(packet.data, &data_length);
if (agreed_length == 0) {
// Initialization failure
SetPhase(PHASE_CLOSE);
return;
}
assert(data_length <= TPacketKeyAgreement::MAX_DATA_LEN);
packet.bHeader = HEADER_GC_KEY_AGREEMENT;
packet.wAgreedLength = (WORD)agreed_length;
packet.wDataLength = (WORD)data_length;
Packet(&packet, sizeof(packet));
}
void DESC::SendKeyAgreementCompleted()
{
TPacketKeyAgreementCompleted packet;
packet.bHeader = HEADER_GC_KEY_AGREEMENT_COMPLETED;
Packet(&packet, sizeof(packet));
}
bool DESC::FinishHandshake(size_t agreed_length, const void* buffer, size_t length)
{
return cipher_.Activate(false, agreed_length, buffer, length);
}
bool DESC::IsCipherPrepared()
{
return cipher_.IsKeyPrepared();
}
#endif // #ifdef _IMPROVED_PACKET_ENCRYPTION_
void DESC::SetRelay(const char * c_pszName)
{
m_stRelayName = c_pszName;
}
void DESC::BindCharacter(LPCHARACTER ch)
{
m_lpCharacter = ch;
}
void DESC::FlushOutput()
{
if (m_sock == INVALID_SOCKET) {
return;
}
if (buffer_size(m_lpOutputBuffer) <= 0)
return;
struct timeval sleep_tv, now_tv, start_tv;
int event_triggered = false;
gettimeofday(&start_tv, NULL);
socket_block(m_sock);
sys_log(0, "FLUSH START %d", buffer_size(m_lpOutputBuffer));
while (buffer_size(m_lpOutputBuffer) > 0)
{
gettimeofday(&now_tv, NULL);
int iSecondsPassed = now_tv.tv_sec - start_tv.tv_sec;
if (iSecondsPassed > 10)
{
if (!event_triggered || iSecondsPassed > 20)
{
SetPhase(PHASE_CLOSE);
break;
}
}
sleep_tv.tv_sec = 0;
sleep_tv.tv_usec = 10000;
int num_events = fdwatch(m_lpFdw, &sleep_tv);
if (num_events < 0)
{
sys_err("num_events < 0 : %d", num_events);
break;
}
int event_idx;
for (event_idx = 0; event_idx < num_events; ++event_idx)
{
LPDESC d2 = (LPDESC) fdwatch_get_client_data(m_lpFdw, event_idx);
if (d2 != this)
continue;
switch (fdwatch_check_event(m_lpFdw, m_sock, event_idx))
{
case FDW_WRITE:
event_triggered = true;
if (ProcessOutput() < 0)
{
sys_err("Cannot flush output buffer");
SetPhase(PHASE_CLOSE);
}
break;
case FDW_EOF:
SetPhase(PHASE_CLOSE);
break;
}
}
if (IsPhase(PHASE_CLOSE))
break;
}
if (buffer_size(m_lpOutputBuffer) == 0)
sys_log(0, "FLUSH SUCCESS");
else
sys_log(0, "FLUSH FAIL");
usleep(250000);
}
EVENTFUNC(disconnect_event)
{
DESC::desc_event_info* info = dynamic_cast<DESC::desc_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "disconnect_event> <Factor> Null pointer" );
return 0;
}
LPDESC d = info->desc;
d->m_pkDisconnectEvent = NULL;
d->SetPhase(PHASE_CLOSE);
return 0;
}
bool DESC::DelayedDisconnect(int iSec)
{
if (m_pkDisconnectEvent != NULL) {
return false;
}
desc_event_info* info = AllocEventInfo<desc_event_info>();
info->desc = this;
m_pkDisconnectEvent = event_create(disconnect_event, info, PASSES_PER_SEC(iSec));
return true;
}
void DESC::DisconnectOfSameLogin()
{
if (GetCharacter())
{
if (m_pkDisconnectEvent)
return;
GetCharacter()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>ٸ<EFBFBD> <20><>ǻ<EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20>α<EFBFBD><CEB1><EFBFBD> <20>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>մϴ<D5B4>."));
DelayedDisconnect(5);
}
else
{
SetPhase(PHASE_CLOSE);
}
}
void DESC::SetAdminMode()
{
m_bAdminMode = true;
}
bool DESC::IsAdminMode()
{
return m_bAdminMode;
}
BYTE DESC::GetSequence()
{
return gc_abSequence[m_iCurrentSequence];
}
void DESC::SetNextSequence()
{
if (++m_iCurrentSequence == SEQUENCE_MAX_NUM)
m_iCurrentSequence = 0;
}
void DESC::SendLoginSuccessPacket()
{
TAccountTable & rTable = GetAccountTable();
TPacketGCLoginSuccess p;
p.bHeader = HEADER_GC_LOGIN_SUCCESS_NEWSLOT;
p.handle = GetHandle();
p.random_key = DESC_MANAGER::instance().MakeRandomKey(GetHandle()); // FOR MARK
thecore_memcpy(p.players, rTable.players, sizeof(rTable.players));
for (int i = 0; i < PLAYER_PER_ACCOUNT; ++i)
{
CGuild* g = CGuildManager::instance().GetLinkedGuild(rTable.players[i].dwID);
if (g)
{
p.guild_id[i] = g->GetID();
strlcpy(p.guild_name[i], g->GetName(), sizeof(p.guild_name[i]));
}
else
{
p.guild_id[i] = 0;
p.guild_name[i][0] = '\0';
}
}
Packet(&p, sizeof(TPacketGCLoginSuccess));
}
//void DESC::SendServerStatePacket(int nIndex)
//{
// TPacketGCStateCheck rp;
//
// int iTotal;
// int * paiEmpireUserCount;
// int iLocal;
//
// DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
//
// rp.header = 1;
// rp.key = 0;
// rp.index = nIndex;
//
// if (g_bNoMoreClient) rp.state = 0;
// else rp.state = iTotal > g_iFullUserCount ? 3 : iTotal > g_iBusyUserCount ? 2 : 1;
//
// this->Packet(&rp, sizeof(rp));
// //printf("STATE_CHECK PACKET PROCESSED.\n");
//}
void DESC::SetMatrixCardRowsAndColumns(unsigned long rows, unsigned long cols)
{
m_dwMatrixRows = rows;
m_dwMatrixCols = cols;
}
unsigned long DESC::GetMatrixRows()
{
return m_dwMatrixRows;
}
unsigned long DESC::GetMatrixCols()
{
return m_dwMatrixCols;
}
bool DESC::CheckMatrixTryCount()
{
if (++m_bMatrixTryCount >= 3)
return false;
return true;
}
void DESC::SetLoginKey(DWORD dwKey)
{
m_dwLoginKey = dwKey;
}
void DESC::SetLoginKey(CLoginKey * pkKey)
{
m_pkLoginKey = pkKey;
sys_log(0, "SetLoginKey %u", m_pkLoginKey->m_dwKey);
}
DWORD DESC::GetLoginKey()
{
if (m_pkLoginKey)
return m_pkLoginKey->m_dwKey;
return m_dwLoginKey;
}
const BYTE* GetKey_20050304Myevan()
{
static bool bGenerated = false;
static DWORD s_adwKey[1938];
if (!bGenerated)
{
bGenerated = true;
DWORD seed = 1491971513;
for (UINT i = 0; i < BYTE(seed); ++i)
{
seed ^= 2148941891ul;
seed += 3592385981ul;
s_adwKey[i] = seed;
}
}
return (const BYTE*)s_adwKey;
}
#ifndef _IMPROVED_PACKET_ENCRYPTION_
void DESC::SetSecurityKey(const DWORD * c_pdwKey)
{
const BYTE * c_pszKey = (const BYTE *) "JyTxtHljHJlVJHorRM301vf@4fvj10-v";
if (g_iUseLocale && !LC_IsKorea())
c_pszKey = GetKey_20050304Myevan() + 37;
thecore_memcpy(&m_adwDecryptionKey, c_pdwKey, 16);
TEA_Encrypt(&m_adwEncryptionKey[0], &m_adwDecryptionKey[0], (const DWORD *) c_pszKey, 16);
sys_log(0, "SetSecurityKey decrypt %u %u %u %u encrypt %u %u %u %u",
m_adwDecryptionKey[0], m_adwDecryptionKey[1], m_adwDecryptionKey[2], m_adwDecryptionKey[3],
m_adwEncryptionKey[0], m_adwEncryptionKey[1], m_adwEncryptionKey[2], m_adwEncryptionKey[3]);
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
void DESC::AssembleCRCMagicCube(BYTE bProcPiece, BYTE bFilePiece)
{
static BYTE abXORTable[32] =
{
102, 30, 0, 0, 0, 0, 0, 0,
188, 44, 0, 0, 0, 0, 0, 0,
39, 201, 0, 0, 0, 0, 0, 0,
43, 5, 0, 0, 0, 0, 0, 0,
};
bProcPiece = (bProcPiece ^ abXORTable[m_bCRCMagicCubeIdx]);
bFilePiece = (bFilePiece ^ abXORTable[m_bCRCMagicCubeIdx+1]);
m_dwProcCRC |= bProcPiece << m_bCRCMagicCubeIdx;
m_dwFileCRC |= bFilePiece << m_bCRCMagicCubeIdx;
m_bCRCMagicCubeIdx += 8;
if (!(m_bCRCMagicCubeIdx & 31))
{
m_dwProcCRC = 0;
m_dwFileCRC = 0;
m_bCRCMagicCubeIdx = 0;
}
}
void DESC::SetBillingExpireSecond(DWORD dwSec)
{
m_dwBillingExpireSecond = dwSec;
}
DWORD DESC::GetBillingExpireSecond()
{
return m_dwBillingExpireSecond;
}
void DESC::push_seq(BYTE hdr, BYTE seq)
{
if (m_seq_vector.size()>=20)
{
m_seq_vector.erase(m_seq_vector.begin());
}
seq_t info = { hdr, seq };
m_seq_vector.push_back(info);
}
BYTE DESC::GetEmpire()
{
return m_accountTable.bEmpire;
}
void DESC::ChatPacket(BYTE type, const char * format, ...)
{
char chatbuf[CHAT_MAX_LEN + 1];
va_list args;
va_start(args, format);
int len = vsnprintf(chatbuf, sizeof(chatbuf), format, args);
va_end(args);
struct packet_chat pack_chat;
pack_chat.header = HEADER_GC_CHAT;
pack_chat.size = sizeof(struct packet_chat) + len;
pack_chat.type = type;
pack_chat.id = 0;
pack_chat.bEmpire = GetEmpire();
TEMP_BUFFER buf;
buf.write(&pack_chat, sizeof(struct packet_chat));
buf.write(chatbuf, len);
Packet(buf.read_peek(), buf.size());
}