2011-07-30 11:40:01 +00:00
|
|
|
#include <engine/console.h>
|
|
|
|
#include <engine/shared/config.h>
|
|
|
|
|
|
|
|
#include "econ.h"
|
2011-12-29 22:36:53 +00:00
|
|
|
#include "netban.h"
|
|
|
|
|
2011-07-30 11:40:01 +00:00
|
|
|
int CEcon::NewClientCallback(int ClientID, void *pUser)
|
|
|
|
{
|
|
|
|
CEcon *pThis = (CEcon *)pUser;
|
|
|
|
|
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
2011-12-29 22:36:53 +00:00
|
|
|
net_addr_str(pThis->m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
2011-07-30 11:40:01 +00:00
|
|
|
char aBuf[128];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "client accepted. cid=%d addr=%s'", ClientID, aAddrStr);
|
|
|
|
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "econ", aBuf);
|
|
|
|
|
|
|
|
pThis->m_aClients[ClientID].m_State = CClient::STATE_CONNECTED;
|
|
|
|
pThis->m_aClients[ClientID].m_TimeConnected = time_get();
|
2011-07-31 11:05:12 +00:00
|
|
|
pThis->m_aClients[ClientID].m_AuthTries = 0;
|
2011-07-31 00:25:55 +00:00
|
|
|
|
|
|
|
pThis->m_NetConsole.Send(ClientID, "Enter password:");
|
2011-07-30 11:40:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CEcon::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
|
|
|
{
|
|
|
|
CEcon *pThis = (CEcon *)pUser;
|
|
|
|
|
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
2011-12-29 22:36:53 +00:00
|
|
|
net_addr_str(pThis->m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
2011-07-30 11:40:01 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "client dropped. cid=%d addr=%s reason='%s'", ClientID, aAddrStr, pReason);
|
|
|
|
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "econ", aBuf);
|
|
|
|
|
|
|
|
pThis->m_aClients[ClientID].m_State = CClient::STATE_EMPTY;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-20 12:37:11 +00:00
|
|
|
void CEcon::SendLineCB(const char *pLine, void *pUserData, bool Highlighted)
|
2011-07-30 11:40:01 +00:00
|
|
|
{
|
|
|
|
static_cast<CEcon *>(pUserData)->Send(-1, pLine);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CEcon::ConchainEconOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
|
|
|
{
|
|
|
|
pfnCallback(pResult, pCallbackUserData);
|
|
|
|
if(pResult->NumArguments() == 1)
|
|
|
|
{
|
|
|
|
CEcon *pThis = static_cast<CEcon *>(pUserData);
|
|
|
|
pThis->Console()->SetPrintOutputLevel(pThis->m_PrintCBIndex, pResult->GetInteger(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-30 18:12:31 +00:00
|
|
|
void CEcon::ConLogout(IConsole::IResult *pResult, void *pUserData)
|
|
|
|
{
|
|
|
|
CEcon *pThis = static_cast<CEcon *>(pUserData);
|
|
|
|
|
|
|
|
if(pThis->m_UserClientID >= 0 && pThis->m_UserClientID < NET_MAX_CONSOLE_CLIENTS && pThis->m_aClients[pThis->m_UserClientID].m_State != CClient::STATE_EMPTY)
|
|
|
|
pThis->m_NetConsole.Drop(pThis->m_UserClientID, "Logout");
|
|
|
|
}
|
|
|
|
|
2021-01-10 12:47:07 +00:00
|
|
|
void CEcon::Init(CConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan)
|
2011-07-30 11:40:01 +00:00
|
|
|
{
|
2021-01-10 12:47:07 +00:00
|
|
|
m_pConfig = pConfig;
|
2011-07-30 11:40:01 +00:00
|
|
|
m_pConsole = pConsole;
|
|
|
|
|
2020-10-26 14:14:07 +00:00
|
|
|
for(auto &Client : m_aClients)
|
|
|
|
Client.m_State = CClient::STATE_EMPTY;
|
2011-07-30 11:40:01 +00:00
|
|
|
|
|
|
|
m_Ready = false;
|
2011-12-30 18:12:31 +00:00
|
|
|
m_UserClientID = -1;
|
2011-07-30 11:40:01 +00:00
|
|
|
|
|
|
|
if(g_Config.m_EcPort == 0 || g_Config.m_EcPassword[0] == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NETADDR BindAddr;
|
|
|
|
if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
|
2012-03-04 11:47:16 +00:00
|
|
|
{
|
|
|
|
// got bindaddr
|
|
|
|
BindAddr.type = NETTYPE_ALL;
|
2011-07-30 11:40:01 +00:00
|
|
|
BindAddr.port = g_Config.m_EcPort;
|
2012-03-04 11:47:16 +00:00
|
|
|
}
|
2011-07-30 11:40:01 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mem_zero(&BindAddr, sizeof(BindAddr));
|
|
|
|
BindAddr.type = NETTYPE_ALL;
|
|
|
|
BindAddr.port = g_Config.m_EcPort;
|
|
|
|
}
|
|
|
|
|
2011-12-29 22:36:53 +00:00
|
|
|
if(m_NetConsole.Open(BindAddr, pNetBan, 0))
|
2011-07-30 11:40:01 +00:00
|
|
|
{
|
|
|
|
m_NetConsole.SetCallbacks(NewClientCallback, DelClientCallback, this);
|
|
|
|
m_Ready = true;
|
|
|
|
char aBuf[128];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "bound to %s:%d", g_Config.m_EcBindaddr, g_Config.m_EcPort);
|
2020-09-26 19:41:58 +00:00
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
|
2011-07-30 11:40:01 +00:00
|
|
|
|
|
|
|
Console()->Chain("ec_output_level", ConchainEconOutputLevelUpdate, this);
|
|
|
|
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_EcOutputLevel, SendLineCB, this);
|
2011-12-30 18:12:31 +00:00
|
|
|
|
|
|
|
Console()->Register("logout", "", CFGFLAG_ECON, ConLogout, this, "Logout of econ");
|
2011-07-30 11:40:01 +00:00
|
|
|
}
|
|
|
|
else
|
2020-09-26 19:41:58 +00:00
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", "couldn't open socket. port might already be in use");
|
2011-07-30 11:40:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CEcon::Update()
|
|
|
|
{
|
|
|
|
if(!m_Ready)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_NetConsole.Update();
|
|
|
|
|
|
|
|
char aBuf[NET_MAX_PACKETSIZE];
|
|
|
|
int ClientID;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
while(m_NetConsole.Recv(aBuf, (int)(sizeof(aBuf)) - 1, &ClientID))
|
2011-07-30 11:40:01 +00:00
|
|
|
{
|
|
|
|
dbg_assert(m_aClients[ClientID].m_State != CClient::STATE_EMPTY, "got message from empty slot");
|
|
|
|
if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTED)
|
|
|
|
{
|
|
|
|
if(str_comp(aBuf, g_Config.m_EcPassword) == 0)
|
|
|
|
{
|
|
|
|
m_aClients[ClientID].m_State = CClient::STATE_AUTHED;
|
|
|
|
m_NetConsole.Send(ClientID, "Authentication successful. External console access granted.");
|
|
|
|
|
|
|
|
str_format(aBuf, sizeof(aBuf), "cid=%d authed", ClientID);
|
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
|
|
|
|
}
|
|
|
|
else
|
2011-07-31 11:05:12 +00:00
|
|
|
{
|
|
|
|
m_aClients[ClientID].m_AuthTries++;
|
2011-12-30 18:12:31 +00:00
|
|
|
char aMsg[128];
|
|
|
|
str_format(aMsg, sizeof(aMsg), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, MAX_AUTH_TRIES);
|
|
|
|
m_NetConsole.Send(ClientID, aMsg);
|
2011-07-31 11:05:12 +00:00
|
|
|
if(m_aClients[ClientID].m_AuthTries >= MAX_AUTH_TRIES)
|
|
|
|
{
|
|
|
|
if(!g_Config.m_EcBantime)
|
|
|
|
m_NetConsole.Drop(ClientID, "Too many authentication tries");
|
|
|
|
else
|
2020-09-26 19:41:58 +00:00
|
|
|
m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), g_Config.m_EcBantime * 60, "Too many authentication tries");
|
2011-07-31 11:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-30 11:40:01 +00:00
|
|
|
}
|
|
|
|
else if(m_aClients[ClientID].m_State == CClient::STATE_AUTHED)
|
|
|
|
{
|
|
|
|
char aFormatted[256];
|
2012-01-12 18:59:27 +00:00
|
|
|
str_format(aFormatted, sizeof(aFormatted), "cid=%d cmd='%s'", ClientID, aBuf);
|
2011-07-30 11:40:01 +00:00
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aFormatted);
|
2011-12-30 18:12:31 +00:00
|
|
|
m_UserClientID = ClientID;
|
2011-07-30 11:40:01 +00:00
|
|
|
Console()->ExecuteLine(aBuf);
|
2011-12-30 18:12:31 +00:00
|
|
|
m_UserClientID = -1;
|
2011-07-30 11:40:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; ++i)
|
|
|
|
{
|
|
|
|
if(m_aClients[i].m_State == CClient::STATE_CONNECTED &&
|
|
|
|
time_get() > m_aClients[i].m_TimeConnected + g_Config.m_EcAuthTimeout * time_freq())
|
|
|
|
m_NetConsole.Drop(i, "authentication timeout");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CEcon::Send(int ClientID, const char *pLine)
|
|
|
|
{
|
|
|
|
if(!m_Ready)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(ClientID == -1)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
|
|
|
{
|
|
|
|
if(m_aClients[i].m_State == CClient::STATE_AUTHED)
|
|
|
|
m_NetConsole.Send(i, pLine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ClientID >= 0 && ClientID < NET_MAX_CONSOLE_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_AUTHED)
|
|
|
|
m_NetConsole.Send(ClientID, pLine);
|
|
|
|
}
|
2011-07-31 00:20:46 +00:00
|
|
|
|
|
|
|
void CEcon::Shutdown()
|
|
|
|
{
|
|
|
|
if(!m_Ready)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_NetConsole.Close();
|
|
|
|
}
|