server/game/src/desc_client.cpp

337 lines
8.2 KiB
C++
Raw Normal View History

2022-03-05 12:44:06 +02:00
#include "stdafx.h"
#include "config.h"
#include "utils.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "char.h"
#include "protocol.h"
#include "p2p.h"
#include "buffer_manager.h"
#include "guild_manager.h"
#include "db.h"
#include "party.h"
LPCLIENT_DESC db_clientdesc = NULL;
LPCLIENT_DESC g_pkAuthMasterDesc = NULL;
LPCLIENT_DESC g_NetmarbleDBDesc = NULL;
LPCLIENT_DESC g_TeenDesc = NULL;
static const char* GetKnownClientDescName(LPCLIENT_DESC desc) {
if (desc == db_clientdesc) {
return "db_clientdesc";
} else if (desc == g_pkAuthMasterDesc) {
return "g_pkAuthMasterDesc";
} else if (desc == g_NetmarbleDBDesc) {
return "g_NetmarbleDBDesc";
} else if (desc == g_TeenDesc) {
return "g_TeenDesc";
}
return "unknown";
}
void ClientDescEventHandler(bufferevent *bev, short events, void *ptr) {
auto * clientDesc = static_cast<LPCLIENT_DESC>(ptr);
if (events & BEV_EVENT_CONNECTED) {
sys_log(0, "SYSTEM: connected to server (ptr %p)", clientDesc);
clientDesc->OnConnectSuccessful();
// Now that we're connected, we can set the read/write/event handlers (and therefore stop using this handler)
auto * desc = static_cast<LPDESC>(clientDesc);
bufferevent_setcb(bev, DescReadHandler, DescWriteHandler, DescEventHandler, desc);
} else if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF)) {
if (events & BEV_EVENT_ERROR) {
int err = bufferevent_socket_get_dns_error(bev);
if (err)
sys_err("SYSTEM: Client connection DNS error: %s", evutil_gai_strerror(err));
}
sys_log(0, "SYSTEM: closing client connection (ptr %p)", clientDesc);
clientDesc->SetPhase(PHASE_CLOSE);
}
}
2022-03-05 12:44:06 +02:00
CLIENT_DESC::CLIENT_DESC()
{
m_iPhaseWhenSucceed = 0;
m_bRetryWhenClosed = false;
m_LastTryToConnectTime = 0;
m_tLastChannelStatusUpdateTime = 0;
}
CLIENT_DESC::~CLIENT_DESC()
{
}
void CLIENT_DESC::Destroy()
{
if (m_bufevent == nullptr)
2022-03-05 12:44:06 +02:00
return;
P2P_MANAGER::instance().UnregisterConnector(this);
if (this == db_clientdesc)
{
CPartyManager::instance().DeleteAllParty();
CPartyManager::instance().DisablePCParty();
CGuildManager::instance().StopAllGuildWar();
DBManager::instance().StopAllBilling();
}
sys_log(0, "SYSTEM: closing client socket.");
2022-03-05 12:44:06 +02:00
bufferevent_free(m_bufevent);
m_bufevent = nullptr;
2022-03-05 12:44:06 +02:00
// Chain up to base class Destroy()
DESC::Destroy();
}
void CLIENT_DESC::SetRetryWhenClosed(bool b)
{
m_bRetryWhenClosed = b;
}
bool CLIENT_DESC::Connect(int iPhaseWhenSucceed)
{
if (iPhaseWhenSucceed != 0)
m_iPhaseWhenSucceed = iPhaseWhenSucceed;
if (get_global_time() - m_LastTryToConnectTime < 3) // 3<><33>
return false;
m_LastTryToConnectTime = get_global_time();
if (m_bufevent != nullptr)
2022-03-05 12:44:06 +02:00
return false;
sys_log(0, "SYSTEM: Trying to connect to %s:%d", m_stHost.c_str(), m_wPort);
if (m_evbase == nullptr) {
sys_err("SYSTEM: event base not set!");
return false;
}
if (m_dnsBase == nullptr) {
sys_err("SYSTEM: DNS event base not set!");
return false;
}
m_bufevent = bufferevent_socket_new(m_evbase, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(m_bufevent, NULL, NULL, ClientDescEventHandler, this);
bufferevent_enable(m_bufevent, EV_READ|EV_WRITE);
bufferevent_socket_connect_hostname(m_bufevent, m_dnsBase, AF_UNSPEC, m_stHost.c_str(), m_wPort);
SetPhase(PHASE_CLIENT_CONNECTING);
return true;
}
2022-03-05 12:44:06 +02:00
void CLIENT_DESC::OnConnectSuccessful() {
sys_log(0, "SYSTEM: connected to server (ptr %p)", this);
SetPhase(m_iPhaseWhenSucceed);
2022-03-05 12:44:06 +02:00
}
void CLIENT_DESC::Setup(event_base* base, evdns_base * dns_base, const char * _host, WORD _port)
2022-03-05 12:44:06 +02:00
{
m_evbase = base;
m_dnsBase = dns_base;
2022-03-05 12:44:06 +02:00
m_stHost = _host;
m_wPort = _port;
m_bufevent = nullptr;
2022-03-05 12:44:06 +02:00
}
void CLIENT_DESC::SetPhase(int iPhase)
{
switch (iPhase)
{
case PHASE_CLIENT_CONNECTING:
sys_log(1, "PHASE_CLIENT_DESC::CONNECTING");
m_pInputProcessor = NULL;
break;
case PHASE_DBCLIENT:
{
sys_log(1, "PHASE_DBCLIENT");
if (!g_bAuthServer)
{
static bool bSentBoot = false;
if (!bSentBoot)
{
bSentBoot = true;
TPacketGDBoot p;
p.dwItemIDRange[0] = 0;
p.dwItemIDRange[1] = 0;
memcpy(p.szIP, g_szPublicIP, 16);
DBPacket(HEADER_GD_BOOT, 0, &p, sizeof(p));
}
}
TEMP_BUFFER buf;
TPacketGDSetup p;
memset(&p, 0, sizeof(p));
2022-03-05 19:59:39 +02:00
strncpy(p.szPublicIP, g_szPublicIP, sizeof(p.szPublicIP));
2022-03-05 12:44:06 +02:00
if (!g_bAuthServer)
{
p.bChannel = g_bChannel;
p.wListenPort = mother_port;
p.wP2PPort = p2p_port;
p.bAuthServer = false;
map_allow_copy(p.alMaps, 32);
const DESC_MANAGER::DESC_SET & c_set = DESC_MANAGER::instance().GetClientSet();
DESC_MANAGER::DESC_SET::const_iterator it;
for (it = c_set.begin(); it != c_set.end(); ++it)
{
LPDESC d = *it;
if (d->GetAccountTable().id != 0)
++p.dwLoginCount;
}
buf.write(&p, sizeof(p));
if (p.dwLoginCount)
{
TPacketLoginOnSetup pck;
for (it = c_set.begin(); it != c_set.end(); ++it)
{
LPDESC d = *it;
TAccountTable & r = d->GetAccountTable();
if (r.id != 0)
{
pck.dwID = r.id;
2022-03-05 19:59:39 +02:00
strncpy(pck.szLogin, r.login, sizeof(pck.szLogin));
strncpy(pck.szSocialID, r.social_id, sizeof(pck.szSocialID));
strncpy(pck.szHost, d->GetHostName(), sizeof(pck.szHost));
2022-03-05 12:44:06 +02:00
pck.dwLoginKey = d->GetLoginKey();
buf.write(&pck, sizeof(TPacketLoginOnSetup));
}
}
}
sys_log(0, "DB_SETUP current user %d size %d", p.dwLoginCount, buf.size());
// <20><>Ƽ<EFBFBD><C6BC> ó<><C3B3><EFBFBD><EFBFBD> <20><> <20>ְ<EFBFBD> <20><>.
CPartyManager::instance().EnablePCParty();
//CPartyManager::instance().SendPartyToDB();
}
else
{
p.bAuthServer = true;
buf.write(&p, sizeof(p));
}
DBPacket(HEADER_GD_SETUP, 0, buf.read_peek(), buf.size());
m_pInputProcessor = &m_inputDB;
}
break;
case PHASE_P2P:
sys_log(1, "PHASE_P2P");
m_pInputProcessor = &m_inputP2P;
break;
case PHASE_CLOSE:
m_pInputProcessor = NULL;
break;
case PHASE_TEEN:
m_inputTeen.SetStep(0);
m_pInputProcessor = &m_inputTeen;
break;
}
m_iPhase = iPhase;
}
void CLIENT_DESC::DBPacketHeader(BYTE bHeader, DWORD dwHandle, DWORD dwSize)
{
DESC::RawPacket(encode_byte(bHeader), sizeof(BYTE));
DESC::RawPacket(encode_4bytes(dwHandle), sizeof(DWORD));
DESC::RawPacket(encode_4bytes(dwSize), sizeof(DWORD));
2022-03-05 12:44:06 +02:00
}
void CLIENT_DESC::DBPacket(BYTE bHeader, DWORD dwHandle, const void * c_pvData, DWORD dwSize)
{
if (m_bufevent == nullptr) {
2022-03-05 12:44:06 +02:00
sys_log(0, "CLIENT_DESC [%s] trying DBPacket() while not connected",
GetKnownClientDescName(this));
return;
}
sys_log(1, "DB_PACKET: header %d handle %d size %d", bHeader, dwHandle, dwSize);
2022-03-05 12:44:06 +02:00
DBPacketHeader(bHeader, dwHandle, dwSize);
if (c_pvData)
DESC::RawPacket(c_pvData, dwSize);
2022-03-05 12:44:06 +02:00
}
void CLIENT_DESC::Packet(const void * c_pvData, int iSize)
{
if (m_bufevent == nullptr) {
2022-03-05 12:44:06 +02:00
sys_log(0, "CLIENT_DESC [%s] trying Packet() while not connected",
GetKnownClientDescName(this));
return;
}
DESC::RawPacket(c_pvData, iSize);
2022-03-05 12:44:06 +02:00
}
bool CLIENT_DESC::IsRetryWhenClosed()
{
return (0 == thecore_is_shutdowned() && m_bRetryWhenClosed);
}
void CLIENT_DESC::Update(DWORD t)
{
if (!g_bAuthServer) {
UpdateChannelStatus(t, false);
}
}
void CLIENT_DESC::UpdateChannelStatus(DWORD t, bool fForce)
{
enum {
CHANNELSTATUS_UPDATE_PERIOD = 5*60*1000, // 5<>и<EFBFBD><D0B8><EFBFBD>
};
if (fForce || m_tLastChannelStatusUpdateTime+CHANNELSTATUS_UPDATE_PERIOD < t) {
int iTotal;
int * paiEmpireUserCount;
int iLocal;
DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
TChannelStatus channelStatus;
channelStatus.nPort = mother_port;
if (g_bNoMoreClient) channelStatus.bStatus = 0;
else channelStatus.bStatus = iTotal > g_iFullUserCount ? 3 : iTotal > g_iBusyUserCount ? 2 : 1;
DBPacket(HEADER_GD_UPDATE_CHANNELSTATUS, 0, &channelStatus, sizeof(channelStatus));
m_tLastChannelStatusUpdateTime = t;
}
}
void CLIENT_DESC::Reset()
{
// Backup connection target info
event_base * evbase = m_evbase;
2022-03-05 12:44:06 +02:00
std::string host = m_stHost;
WORD port = m_wPort;
Destroy();
Initialize();
// Restore connection target info
m_evbase = evbase;
2022-03-05 12:44:06 +02:00
m_stHost = host;
m_wPort = port;
}