mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 03:28:19 +00:00
fixed econ feature and tcp
This commit is contained in:
parent
b0fdc40959
commit
a0a62bcd70
|
@ -42,10 +42,6 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifndef EWOULDBLOCK
|
|
||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#error NOT IMPLEMENTED
|
#error NOT IMPLEMENTED
|
||||||
#endif
|
#endif
|
||||||
|
@ -1102,30 +1098,31 @@ int net_set_blocking(NETSOCKET sock)
|
||||||
|
|
||||||
int net_tcp_listen(NETSOCKET sock, int backlog)
|
int net_tcp_listen(NETSOCKET sock, int backlog)
|
||||||
{
|
{
|
||||||
|
int err = -1;
|
||||||
if(sock.ipv4sock >= 0)
|
if(sock.ipv4sock >= 0)
|
||||||
listen(sock.ipv4sock, backlog);
|
err = listen(sock.ipv4sock, backlog);
|
||||||
if(sock.ipv6sock >= 0)
|
if(sock.ipv6sock >= 0)
|
||||||
listen(sock.ipv6sock, backlog);
|
err = listen(sock.ipv6sock, backlog);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a)
|
int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
socklen_t sockaddr_len;
|
socklen_t sockaddr_len;
|
||||||
struct sockaddr addr;
|
|
||||||
|
|
||||||
*new_sock = invalid_socket;
|
*new_sock = invalid_socket;
|
||||||
|
|
||||||
sockaddr_len = sizeof(addr);
|
|
||||||
|
|
||||||
if(sock.ipv4sock >= 0)
|
if(sock.ipv4sock >= 0)
|
||||||
{
|
{
|
||||||
s = accept(sock.ipv4sock, &addr, &sockaddr_len);
|
struct sockaddr_in addr;
|
||||||
|
sockaddr_len = sizeof(addr);
|
||||||
|
|
||||||
|
s = accept(sock.ipv4sock, (struct sockaddr *)&addr, &sockaddr_len);
|
||||||
|
|
||||||
if (s != -1)
|
if (s != -1)
|
||||||
{
|
{
|
||||||
sockaddr_to_netaddr(&addr, a);
|
sockaddr_to_netaddr((const struct sockaddr *)&addr, a);
|
||||||
new_sock->type = NETTYPE_IPV4;
|
new_sock->type = NETTYPE_IPV4;
|
||||||
new_sock->ipv4sock = s;
|
new_sock->ipv4sock = s;
|
||||||
return s;
|
return s;
|
||||||
|
@ -1134,18 +1131,21 @@ int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a)
|
||||||
|
|
||||||
if(sock.ipv6sock >= 0)
|
if(sock.ipv6sock >= 0)
|
||||||
{
|
{
|
||||||
s = accept(sock.ipv6sock, &addr, &sockaddr_len);
|
struct sockaddr_in6 addr;
|
||||||
|
sockaddr_len = sizeof(addr);
|
||||||
|
|
||||||
|
s = accept(sock.ipv6sock, (struct sockaddr *)&addr, &sockaddr_len);
|
||||||
|
|
||||||
if (s != -1)
|
if (s != -1)
|
||||||
{
|
{
|
||||||
sockaddr_to_netaddr(&addr, a);
|
sockaddr_to_netaddr((const struct sockaddr *)&addr, a);
|
||||||
new_sock->type = NETTYPE_IPV6;
|
new_sock->type = NETTYPE_IPV6;
|
||||||
new_sock->ipv6sock = s;
|
new_sock->ipv6sock = s;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_tcp_connect(NETSOCKET sock, const NETADDR *a)
|
int net_tcp_connect(NETSOCKET sock, const NETADDR *a)
|
||||||
|
@ -1164,7 +1164,7 @@ int net_tcp_connect(NETSOCKET sock, const NETADDR *a)
|
||||||
return connect(sock.ipv6sock, (struct sockaddr *)&addr, sizeof(addr));
|
return connect(sock.ipv6sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_tcp_connect_non_blocking(NETSOCKET sock, NETADDR bindaddr)
|
int net_tcp_connect_non_blocking(NETSOCKET sock, NETADDR bindaddr)
|
||||||
|
@ -1180,7 +1180,7 @@ int net_tcp_connect_non_blocking(NETSOCKET sock, NETADDR bindaddr)
|
||||||
|
|
||||||
int net_tcp_send(NETSOCKET sock, const void *data, int size)
|
int net_tcp_send(NETSOCKET sock, const void *data, int size)
|
||||||
{
|
{
|
||||||
int bytes = 0;
|
int bytes = -1;
|
||||||
|
|
||||||
if(sock.ipv4sock >= 0)
|
if(sock.ipv4sock >= 0)
|
||||||
bytes = send((int)sock.ipv4sock, (const char*)data, size, 0);
|
bytes = send((int)sock.ipv4sock, (const char*)data, size, 0);
|
||||||
|
@ -1192,7 +1192,7 @@ int net_tcp_send(NETSOCKET sock, const void *data, int size)
|
||||||
|
|
||||||
int net_tcp_recv(NETSOCKET sock, void *data, int maxsize)
|
int net_tcp_recv(NETSOCKET sock, void *data, int maxsize)
|
||||||
{
|
{
|
||||||
int bytes = 0;
|
int bytes = -1;
|
||||||
|
|
||||||
if(sock.ipv4sock >= 0)
|
if(sock.ipv4sock >= 0)
|
||||||
bytes = recv((int)sock.ipv4sock, (char*)data, maxsize, 0);
|
bytes = recv((int)sock.ipv4sock, (char*)data, maxsize, 0);
|
||||||
|
@ -1209,12 +1209,20 @@ int net_tcp_close(NETSOCKET sock)
|
||||||
|
|
||||||
int net_errno()
|
int net_errno()
|
||||||
{
|
{
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
return WSAGetLastError();
|
||||||
|
#else
|
||||||
return errno;
|
return errno;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_would_block()
|
int net_would_block()
|
||||||
{
|
{
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
return net_errno() == WSAEWOULDBLOCK;
|
||||||
|
#else
|
||||||
return net_errno() == EWOULDBLOCK;
|
return net_errno() == EWOULDBLOCK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_init()
|
int net_init()
|
||||||
|
|
|
@ -23,6 +23,8 @@ public:
|
||||||
TEMPCMD_NAME_LENGTH=32,
|
TEMPCMD_NAME_LENGTH=32,
|
||||||
TEMPCMD_HELP_LENGTH=64,
|
TEMPCMD_HELP_LENGTH=64,
|
||||||
TEMPCMD_PARAMS_LENGTH=16,
|
TEMPCMD_PARAMS_LENGTH=16,
|
||||||
|
|
||||||
|
MAX_PRINT_CB=4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: rework this interface to reduce the amount of virtual calls
|
// TODO: rework this interface to reduce the amount of virtual calls
|
||||||
|
@ -79,7 +81,8 @@ public:
|
||||||
virtual void ExecuteLineStroked(int Stroke, const char *pStr) = 0;
|
virtual void ExecuteLineStroked(int Stroke, const char *pStr) = 0;
|
||||||
virtual void ExecuteFile(const char *pFilename) = 0;
|
virtual void ExecuteFile(const char *pFilename) = 0;
|
||||||
|
|
||||||
virtual void RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData) = 0;
|
virtual int RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData) = 0;
|
||||||
|
virtual void SetPrintOutputLevel(int Index, int OutputLevel) = 0;
|
||||||
virtual void Print(int Level, const char *pFrom, const char *pStr) = 0;
|
virtual void Print(int Level, const char *pFrom, const char *pStr) = 0;
|
||||||
|
|
||||||
virtual void SetAccessLevel(int AccessLevel) = 0;
|
virtual void SetAccessLevel(int AccessLevel) = 0;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
#include <engine/shared/datafile.h>
|
#include <engine/shared/datafile.h>
|
||||||
#include <engine/shared/demo.h>
|
#include <engine/shared/demo.h>
|
||||||
|
#include <engine/shared/econ.h>
|
||||||
#include <engine/shared/mapchecker.h>
|
#include <engine/shared/mapchecker.h>
|
||||||
#include <engine/shared/network.h>
|
#include <engine/shared/network.h>
|
||||||
#include <engine/shared/packer.h>
|
#include <engine/shared/packer.h>
|
||||||
|
@ -317,15 +318,8 @@ int CServer::Init()
|
||||||
m_aClients[i].m_Snapshots.Init();
|
m_aClients[i].m_Snapshots.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
|
||||||
{
|
|
||||||
m_aEconClients[i].m_State = CEconClient::STATE_EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_CurrentGameTick = 0;
|
m_CurrentGameTick = 0;
|
||||||
|
|
||||||
m_UseEcon = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,30 +612,6 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CServer::NewConsoleClientCallback(int EconID, void *pUser)
|
|
||||||
{
|
|
||||||
CServer *pThis = (CServer *)pUser;
|
|
||||||
pThis->m_aEconClients[EconID].m_State = CEconClient::STATE_CONNECTED;
|
|
||||||
pThis->m_NetConsole.SetTimeout(EconID, g_Config.m_SvEconAuthTimeout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CServer::DelConsoleClientCallback(int EconID, const char *pReason, void *pUser)
|
|
||||||
{
|
|
||||||
CServer *pThis = (CServer *)pUser;
|
|
||||||
|
|
||||||
NETADDR Addr = pThis->m_NetConsole.ClientAddr(EconID);
|
|
||||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
||||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
|
||||||
char aBuf[256];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "econ client dropped. eid=%d addr=%s reason='%s'", EconID, aAddrStr, pReason);
|
|
||||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
|
|
||||||
|
|
||||||
pThis->m_aEconClients[EconID].m_State = CEconClient::STATE_EMPTY;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CServer::SendMap(int ClientID)
|
void CServer::SendMap(int ClientID)
|
||||||
{
|
{
|
||||||
CMsgPacker Msg(NETMSG_MAP_CHANGE);
|
CMsgPacker Msg(NETMSG_MAP_CHANGE);
|
||||||
|
@ -664,12 +634,7 @@ void CServer::SendRconLine(int ClientID, const char *pLine)
|
||||||
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
|
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServer::SendEconLine(int EconID, const char *pLine)
|
void CServer::SendRconLineAuthed(const char *pLine, void *pUser)
|
||||||
{
|
|
||||||
m_NetConsole.Send(EconID, pLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CServer::SendConsoleLineAuthed(const char *pLine, void *pUser)
|
|
||||||
{
|
{
|
||||||
CServer *pThis = (CServer *)pUser;
|
CServer *pThis = (CServer *)pUser;
|
||||||
static volatile int ReentryGuard = 0;
|
static volatile int ReentryGuard = 0;
|
||||||
|
@ -684,15 +649,6 @@ void CServer::SendConsoleLineAuthed(const char *pLine, void *pUser)
|
||||||
pThis->SendRconLine(i, pLine);
|
pThis->SendRconLine(i, pLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pThis->m_UseEcon)
|
|
||||||
{
|
|
||||||
for(i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
|
||||||
{
|
|
||||||
if(pThis->m_aEconClients[i].m_State == CEconClient::STATE_AUTHED)
|
|
||||||
pThis->SendEconLine(i, pLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReentryGuard--;
|
ReentryGuard--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1130,46 +1086,7 @@ void CServer::PumpNetwork()
|
||||||
ProcessClientPacket(&Packet);
|
ProcessClientPacket(&Packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_UseEcon)
|
m_Econ.Update();
|
||||||
EconPumpNetwork();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CServer::EconPumpNetwork()
|
|
||||||
{
|
|
||||||
m_NetConsole.Update();
|
|
||||||
|
|
||||||
char aBuf[NET_MAX_PACKETSIZE];
|
|
||||||
int EconID;
|
|
||||||
|
|
||||||
while(m_NetConsole.Recv(aBuf, sizeof(aBuf) - 1, &EconID))
|
|
||||||
{
|
|
||||||
dbg_assert(m_aEconClients[EconID].m_State != CEconClient::STATE_EMPTY, "got message from empty slot");
|
|
||||||
if(m_aEconClients[EconID].m_State == CEconClient::STATE_CONNECTED)
|
|
||||||
{
|
|
||||||
if(str_comp(aBuf, g_Config.m_SvRconPassword) == 0)
|
|
||||||
{
|
|
||||||
m_aEconClients[EconID].m_State = CEconClient::STATE_AUTHED;
|
|
||||||
m_NetConsole.Send(EconID, "Authentication successful. Remote console access granted.");
|
|
||||||
m_NetConsole.SetTimeout(EconID, g_Config.m_SvEconTimeout);
|
|
||||||
|
|
||||||
str_format(aBuf, sizeof(aBuf), "EconID=%d authed", EconID);
|
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_NetConsole.Send(EconID, "Wrong password");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(m_aEconClients[EconID].m_State == CEconClient::STATE_AUTHED)
|
|
||||||
{
|
|
||||||
char aFormatted[256];
|
|
||||||
str_format(aFormatted, sizeof(aBuf), "eid=%d cmd='%s'", EconID, aBuf);
|
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aFormatted);
|
|
||||||
m_RconClientID = EconID;
|
|
||||||
Console()->ExecuteLine(aBuf);
|
|
||||||
m_RconClientID = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *CServer::GetMapName()
|
char *CServer::GetMapName()
|
||||||
|
@ -1244,7 +1161,7 @@ int CServer::Run()
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
|
|
||||||
//
|
//
|
||||||
Console()->RegisterPrintCallback(SendConsoleLineAuthed, this);
|
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
|
||||||
|
|
||||||
// load map
|
// load map
|
||||||
if(!LoadMap(g_Config.m_SvMap))
|
if(!LoadMap(g_Config.m_SvMap))
|
||||||
|
@ -1275,30 +1192,7 @@ int CServer::Run()
|
||||||
|
|
||||||
m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
|
m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
|
||||||
|
|
||||||
if(g_Config.m_SvEconPort && g_Config.m_SvRconPassword[0])
|
m_Econ.Init(Console());
|
||||||
{
|
|
||||||
dbg_msg("econ", "binding econ to %s:%d", g_Config.m_SvEconBindaddr, g_Config.m_SvEconPort);
|
|
||||||
if(g_Config.m_SvEconBindaddr[0] && net_host_lookup(g_Config.m_SvEconBindaddr, &BindAddr, NETTYPE_ALL) == 0)
|
|
||||||
{
|
|
||||||
BindAddr.port = g_Config.m_SvEconPort;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mem_zero(&BindAddr, sizeof(BindAddr));
|
|
||||||
BindAddr.type = NETTYPE_ALL;
|
|
||||||
BindAddr.port = g_Config.m_SvEconPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_NetConsole.Open(BindAddr, 0))
|
|
||||||
{
|
|
||||||
m_NetConsole.SetCallbacks(NewConsoleClientCallback, DelConsoleClientCallback, this);
|
|
||||||
m_UseEcon = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dbg_msg("econ", "couldn't open econ socket. port might already be in use");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName);
|
str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName);
|
||||||
|
@ -1694,6 +1588,16 @@ void CServer::ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserDa
|
||||||
pfnCallback(pResult, pCallbackUserData);
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CServer::ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||||
|
{
|
||||||
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
|
if(pResult->NumArguments() == 1)
|
||||||
|
{
|
||||||
|
CServer *pThis = static_cast<CServer *>(pUserData);
|
||||||
|
pThis->Console()->SetPrintOutputLevel(pThis->m_PrintCBIndex, pResult->GetInteger(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CServer::RegisterCommands()
|
void CServer::RegisterCommands()
|
||||||
{
|
{
|
||||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
|
@ -1715,6 +1619,7 @@ void CServer::RegisterCommands()
|
||||||
|
|
||||||
Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
|
Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
|
||||||
Console()->Chain("mod_command", ConchainModCommandUpdate, this);
|
Console()->Chain("mod_command", ConchainModCommandUpdate, this);
|
||||||
|
Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -109,26 +109,11 @@ public:
|
||||||
|
|
||||||
CClient m_aClients[MAX_CLIENTS];
|
CClient m_aClients[MAX_CLIENTS];
|
||||||
|
|
||||||
class CEconClient
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
STATE_EMPTY=0,
|
|
||||||
STATE_CONNECTED,
|
|
||||||
STATE_AUTHED
|
|
||||||
};
|
|
||||||
|
|
||||||
int m_State;
|
|
||||||
};
|
|
||||||
|
|
||||||
CEconClient m_aEconClients[NET_MAX_CONSOLE_CLIENTS];
|
|
||||||
|
|
||||||
CSnapshotDelta m_SnapshotDelta;
|
CSnapshotDelta m_SnapshotDelta;
|
||||||
CSnapshotBuilder m_SnapshotBuilder;
|
CSnapshotBuilder m_SnapshotBuilder;
|
||||||
CSnapIDPool m_IDPool;
|
CSnapIDPool m_IDPool;
|
||||||
CNetServer m_NetServer;
|
CNetServer m_NetServer;
|
||||||
CNetConsole m_NetConsole;
|
CEcon m_Econ;
|
||||||
|
|
||||||
IEngineMap *m_pMap;
|
IEngineMap *m_pMap;
|
||||||
|
|
||||||
|
@ -138,8 +123,7 @@ public:
|
||||||
int m_MapReload;
|
int m_MapReload;
|
||||||
int m_RconClientID;
|
int m_RconClientID;
|
||||||
int m_RconAuthLevel;
|
int m_RconAuthLevel;
|
||||||
|
int m_PrintCBIndex;
|
||||||
int m_UseEcon;
|
|
||||||
|
|
||||||
int64 m_Lastheartbeat;
|
int64 m_Lastheartbeat;
|
||||||
//static NETADDR4 master_server;
|
//static NETADDR4 master_server;
|
||||||
|
@ -186,14 +170,10 @@ public:
|
||||||
static int NewClientCallback(int ClientID, void *pUser);
|
static int NewClientCallback(int ClientID, void *pUser);
|
||||||
static int DelClientCallback(int ClientID, const char *pReason, void *pUser);
|
static int DelClientCallback(int ClientID, const char *pReason, void *pUser);
|
||||||
|
|
||||||
static int NewConsoleClientCallback(int EconID, void *pUser);
|
|
||||||
static int DelConsoleClientCallback(int EconID, const char *pReason, void *pUser);
|
|
||||||
|
|
||||||
void SendMap(int ClientID);
|
void SendMap(int ClientID);
|
||||||
void SendConnectionReady(int ClientID);
|
void SendConnectionReady(int ClientID);
|
||||||
void SendRconLine(int ClientID, const char *pLine);
|
void SendRconLine(int ClientID, const char *pLine);
|
||||||
void SendEconLine(int EconID, const char *pLine);
|
static void SendRconLineAuthed(const char *pLine, void *pUser);
|
||||||
static void SendConsoleLineAuthed(const char *pLine, void *pUser);
|
|
||||||
|
|
||||||
void SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
|
void SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
|
||||||
void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
|
void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
|
||||||
|
@ -207,8 +187,6 @@ public:
|
||||||
int BanAdd(NETADDR Addr, int Seconds, const char *pReason);
|
int BanAdd(NETADDR Addr, int Seconds, const char *pReason);
|
||||||
int BanRemove(NETADDR Addr);
|
int BanRemove(NETADDR Addr);
|
||||||
|
|
||||||
void EconPumpNetwork();
|
|
||||||
|
|
||||||
void PumpNetwork();
|
void PumpNetwork();
|
||||||
|
|
||||||
char *GetMapName();
|
char *GetMapName();
|
||||||
|
@ -229,6 +207,7 @@ public:
|
||||||
static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
static void ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
static void ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
static void ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
|
||||||
void RegisterCommands();
|
void RegisterCommands();
|
||||||
|
|
||||||
|
|
|
@ -86,10 +86,12 @@ MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remo
|
||||||
MACRO_CONFIG_STR(SvRconModPassword, sv_rcon_mod_password, 32, "", CFGFLAG_SERVER, "Remote console password for moderators (limited access)")
|
MACRO_CONFIG_STR(SvRconModPassword, sv_rcon_mod_password, 32, "", CFGFLAG_SERVER, "Remote console password for moderators (limited access)")
|
||||||
MACRO_CONFIG_INT(SvRconMaxTries, sv_rcon_max_tries, 3, 0, 100, CFGFLAG_SERVER, "Maximum number of tries for remote console authentication")
|
MACRO_CONFIG_INT(SvRconMaxTries, sv_rcon_max_tries, 3, 0, 100, CFGFLAG_SERVER, "Maximum number of tries for remote console authentication")
|
||||||
MACRO_CONFIG_INT(SvRconBantime, sv_rcon_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if remote console authentication fails. 0 makes it just use kick")
|
MACRO_CONFIG_INT(SvRconBantime, sv_rcon_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if remote console authentication fails. 0 makes it just use kick")
|
||||||
MACRO_CONFIG_STR(SvEconBindaddr, sv_econ_bindaddr, 128, "localhost", CFGFLAG_SERVER, "Address to bind the external console to. Anything but 'localhost' is dangerous")
|
|
||||||
MACRO_CONFIG_INT(SvEconPort, sv_econ_port, 0, 0, 0, CFGFLAG_SERVER, "Port to use for the external console")
|
MACRO_CONFIG_STR(EcBindaddr, ec_bindaddr, 128, "localhost", CFGFLAG_SERVER, "Address to bind the external console to. Anything but 'localhost' is dangerous")
|
||||||
MACRO_CONFIG_INT(SvEconAuthTimeout, sv_econ_auth_timeout, 30, 1, 120, CFGFLAG_SERVER, "Time in seconds before the the econ authentification times out")
|
MACRO_CONFIG_INT(EcPort, ec_port, 0, 0, 0, CFGFLAG_SERVER, "Port to use for the external console")
|
||||||
MACRO_CONFIG_INT(SvEconTimeout, sv_econ_timeout, 300, 1, 3600, CFGFLAG_SERVER, "Time in seconds before the econ connection times out")
|
MACRO_CONFIG_STR(EcPassword, ec_password, 32, "", CFGFLAG_SERVER, "External console password")
|
||||||
|
MACRO_CONFIG_INT(EcAuthTimeout, ec_auth_timeout, 30, 1, 120, CFGFLAG_SERVER, "Time in seconds before the the econ authentification times out")
|
||||||
|
MACRO_CONFIG_INT(EcOutputLevel, ec_output_level, 1, 0, 2, CFGFLAG_SERVER, "Adjusts the amount of information in the external console")
|
||||||
|
|
||||||
MACRO_CONFIG_INT(Debug, debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode")
|
MACRO_CONFIG_INT(Debug, debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode")
|
||||||
MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
|
MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
|
||||||
|
|
|
@ -173,20 +173,34 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat)
|
||||||
return Error;
|
return Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsole::RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData)
|
int CConsole::RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData)
|
||||||
{
|
{
|
||||||
m_pfnPrintCallback = pfnPrintCallback;
|
if(m_NumPrintCB == MAX_PRINT_CB)
|
||||||
m_pPrintCallbackUserdata = pUserData;
|
return -1;
|
||||||
|
|
||||||
|
m_aPrintCB[m_NumPrintCB].m_OutputLevel = clamp(OutputLevel, (int)(OUTPUT_LEVEL_STANDARD), (int)(OUTPUT_LEVEL_DEBUG));
|
||||||
|
m_aPrintCB[m_NumPrintCB].m_pfnPrintCallback = pfnPrintCallback;
|
||||||
|
m_aPrintCB[m_NumPrintCB].m_pPrintCallbackUserdata = pUserData;
|
||||||
|
return m_NumPrintCB++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConsole::SetPrintOutputLevel(int Index, int OutputLevel)
|
||||||
|
{
|
||||||
|
if(Index >= 0 && Index < MAX_PRINT_CB)
|
||||||
|
m_aPrintCB[Index].m_OutputLevel = clamp(OutputLevel, (int)(OUTPUT_LEVEL_STANDARD), (int)(OUTPUT_LEVEL_DEBUG));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsole::Print(int Level, const char *pFrom, const char *pStr)
|
void CConsole::Print(int Level, const char *pFrom, const char *pStr)
|
||||||
{
|
{
|
||||||
dbg_msg(pFrom ,"%s", pStr);
|
dbg_msg(pFrom ,"%s", pStr);
|
||||||
if(Level <= g_Config.m_ConsoleOutputLevel && m_pfnPrintCallback)
|
for(int i = 0; i < m_NumPrintCB; ++i)
|
||||||
{
|
{
|
||||||
char aBuf[1024];
|
if(Level <= m_aPrintCB[i].m_OutputLevel && m_aPrintCB[i].m_pfnPrintCallback)
|
||||||
str_format(aBuf, sizeof(aBuf), "[%s]: %s", pFrom, pStr);
|
{
|
||||||
m_pfnPrintCallback(aBuf, m_pPrintCallbackUserdata);
|
char aBuf[1024];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "[%s]: %s", pFrom, pStr);
|
||||||
|
m_aPrintCB[i].m_pfnPrintCallback(aBuf, m_aPrintCB[i].m_pPrintCallbackUserdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,8 +576,8 @@ CConsole::CConsole(int FlagMask)
|
||||||
m_ExecutionQueue.Reset();
|
m_ExecutionQueue.Reset();
|
||||||
m_pFirstCommand = 0;
|
m_pFirstCommand = 0;
|
||||||
m_pFirstExec = 0;
|
m_pFirstExec = 0;
|
||||||
m_pPrintCallbackUserdata = 0;
|
mem_zero(m_aPrintCB, sizeof(m_aPrintCB));
|
||||||
m_pfnPrintCallback = 0;
|
m_NumPrintCB = 0;
|
||||||
|
|
||||||
m_pStorage = 0;
|
m_pStorage = 0;
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,13 @@ class CConsole : public IConsole
|
||||||
void ExecuteFileRecurse(const char *pFilename);
|
void ExecuteFileRecurse(const char *pFilename);
|
||||||
void ExecuteLineStroked(int Stroke, const char *pStr);
|
void ExecuteLineStroked(int Stroke, const char *pStr);
|
||||||
|
|
||||||
FPrintCallback m_pfnPrintCallback;
|
struct
|
||||||
void *m_pPrintCallbackUserdata;
|
{
|
||||||
|
int m_OutputLevel;
|
||||||
|
FPrintCallback m_pfnPrintCallback;
|
||||||
|
void *m_pPrintCallbackUserdata;
|
||||||
|
} m_aPrintCB[MAX_PRINT_CB];
|
||||||
|
int m_NumPrintCB;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -167,7 +172,8 @@ public:
|
||||||
virtual void ExecuteLine(const char *pStr);
|
virtual void ExecuteLine(const char *pStr);
|
||||||
virtual void ExecuteFile(const char *pFilename);
|
virtual void ExecuteFile(const char *pFilename);
|
||||||
|
|
||||||
virtual void RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData);
|
virtual int RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData);
|
||||||
|
virtual void SetPrintOutputLevel(int Index, int OutputLevel);
|
||||||
virtual void Print(int Level, const char *pFrom, const char *pStr);
|
virtual void Print(int Level, const char *pFrom, const char *pStr);
|
||||||
|
|
||||||
void SetAccessLevel(int AccessLevel) { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_MOD)); }
|
void SetAccessLevel(int AccessLevel) { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_MOD)); }
|
||||||
|
|
147
src/engine/shared/econ.cpp
Normal file
147
src/engine/shared/econ.cpp
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
#include <engine/console.h>
|
||||||
|
#include <engine/shared/config.h>
|
||||||
|
|
||||||
|
#include "econ.h"
|
||||||
|
|
||||||
|
int CEcon::NewClientCallback(int ClientID, void *pUser)
|
||||||
|
{
|
||||||
|
CEcon *pThis = (CEcon *)pUser;
|
||||||
|
|
||||||
|
NETADDR Addr = pThis->m_NetConsole.ClientAddr(ClientID);
|
||||||
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||||
|
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||||
|
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();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CEcon::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
||||||
|
{
|
||||||
|
CEcon *pThis = (CEcon *)pUser;
|
||||||
|
|
||||||
|
NETADDR Addr = pThis->m_NetConsole.ClientAddr(ClientID);
|
||||||
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||||
|
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEcon::SendLineCB(const char *pLine, void *pUserData)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEcon::Init(IConsole *pConsole)
|
||||||
|
{
|
||||||
|
m_pConsole = pConsole;
|
||||||
|
|
||||||
|
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
||||||
|
m_aClients[i].m_State = CClient::STATE_EMPTY;
|
||||||
|
|
||||||
|
m_Ready = false;
|
||||||
|
|
||||||
|
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)
|
||||||
|
BindAddr.port = g_Config.m_EcPort;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mem_zero(&BindAddr, sizeof(BindAddr));
|
||||||
|
BindAddr.type = NETTYPE_ALL;
|
||||||
|
BindAddr.port = g_Config.m_EcPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_NetConsole.Open(BindAddr, 0))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD,"econ", aBuf);
|
||||||
|
|
||||||
|
Console()->Chain("ec_output_level", ConchainEconOutputLevelUpdate, this);
|
||||||
|
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_EcOutputLevel, SendLineCB, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD,"econ", "couldn't open socket. port might already be in use");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEcon::Update()
|
||||||
|
{
|
||||||
|
if(!m_Ready)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_NetConsole.Update();
|
||||||
|
|
||||||
|
char aBuf[NET_MAX_PACKETSIZE];
|
||||||
|
int ClientID;
|
||||||
|
|
||||||
|
while(m_NetConsole.Recv(aBuf, (int)(sizeof(aBuf))-1, &ClientID))
|
||||||
|
{
|
||||||
|
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
|
||||||
|
m_NetConsole.Send(ClientID, "Wrong password");
|
||||||
|
}
|
||||||
|
else if(m_aClients[ClientID].m_State == CClient::STATE_AUTHED)
|
||||||
|
{
|
||||||
|
char aFormatted[256];
|
||||||
|
str_format(aFormatted, sizeof(aBuf), "cid=%d cmd='%s'", ClientID, aBuf);
|
||||||
|
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aFormatted);
|
||||||
|
Console()->ExecuteLine(aBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
43
src/engine/shared/econ.h
Normal file
43
src/engine/shared/econ.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef ENGINE_SHARED_ECON_H
|
||||||
|
#define ENGINE_SHARED_ECON_H
|
||||||
|
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
|
class CEcon
|
||||||
|
{
|
||||||
|
class CClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STATE_EMPTY=0,
|
||||||
|
STATE_CONNECTED,
|
||||||
|
STATE_AUTHED,
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_State;
|
||||||
|
int64 m_TimeConnected;
|
||||||
|
};
|
||||||
|
CClient m_aClients[NET_MAX_CONSOLE_CLIENTS];
|
||||||
|
|
||||||
|
IConsole *m_pConsole;
|
||||||
|
CNetConsole m_NetConsole;
|
||||||
|
|
||||||
|
bool m_Ready;
|
||||||
|
int m_PrintCBIndex;
|
||||||
|
|
||||||
|
static void SendLineCB(const char *pLine, void *pUserData);
|
||||||
|
static void ConchainEconOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
|
||||||
|
static int NewClientCallback(int ClientID, void *pUser);
|
||||||
|
static int DelClientCallback(int ClientID, const char *pReason, void *pUser);
|
||||||
|
|
||||||
|
public:
|
||||||
|
IConsole *Console() { return m_pConsole; }
|
||||||
|
|
||||||
|
void Init(IConsole *pConsole);
|
||||||
|
void Update();
|
||||||
|
void Send(int ClientID, const char *pLine);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -49,7 +49,7 @@ enum
|
||||||
NET_MAX_CHUNKHEADERSIZE = 5,
|
NET_MAX_CHUNKHEADERSIZE = 5,
|
||||||
NET_PACKETHEADERSIZE = 3,
|
NET_PACKETHEADERSIZE = 3,
|
||||||
NET_MAX_CLIENTS = 16,
|
NET_MAX_CLIENTS = 16,
|
||||||
NET_MAX_CONSOLE_CLIENTS = 16,
|
NET_MAX_CONSOLE_CLIENTS = 4,
|
||||||
NET_MAX_SEQUENCE = 1<<10,
|
NET_MAX_SEQUENCE = 1<<10,
|
||||||
NET_SEQUENCE_MASK = NET_MAX_SEQUENCE-1,
|
NET_SEQUENCE_MASK = NET_MAX_SEQUENCE-1,
|
||||||
|
|
||||||
|
@ -196,32 +196,27 @@ public:
|
||||||
class CConsoleNetConnection
|
class CConsoleNetConnection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
unsigned m_State;
|
int m_State;
|
||||||
|
|
||||||
NETADDR m_PeerAddr;
|
NETADDR m_PeerAddr;
|
||||||
NETSOCKET m_Socket;
|
NETSOCKET m_Socket;
|
||||||
|
|
||||||
char m_aBuffer[NET_MAX_PACKETSIZE];
|
char m_aBuffer[NET_MAX_PACKETSIZE];
|
||||||
char *m_pBufferPos;
|
int m_BufferOffset;
|
||||||
|
|
||||||
char m_aErrorString[256];
|
char m_aErrorString[256];
|
||||||
|
|
||||||
int m_Timeout;
|
bool m_LineEndingDetected;
|
||||||
int64 m_LastRecvTime;
|
char m_aLineEnding[3];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(NETSOCKET Socket);
|
|
||||||
void Init(NETSOCKET Socket, const NETADDR *pAddr);
|
void Init(NETSOCKET Socket, const NETADDR *pAddr);
|
||||||
int Connect(const NETADDR *pAddr);
|
|
||||||
void Disconnect(const char *pReason);
|
void Disconnect(const char *pReason);
|
||||||
|
|
||||||
int State() const { return m_State; }
|
int State() const { return m_State; }
|
||||||
NETADDR PeerAddress() const { return m_PeerAddr; }
|
NETADDR PeerAddress() const { return m_PeerAddr; }
|
||||||
const char *ErrorString() const { return m_aErrorString; }
|
const char *ErrorString() const { return m_aErrorString; }
|
||||||
|
|
||||||
void SetTimeout(int Timeout) { m_Timeout = Timeout; }
|
|
||||||
int Timeout() const { return m_Timeout; }
|
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
int Update();
|
int Update();
|
||||||
int Send(const char *pLine);
|
int Send(const char *pLine);
|
||||||
|
@ -337,7 +332,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
NETSOCKET m_Socket;
|
NETSOCKET m_Socket;
|
||||||
CSlot m_aSlots[NET_MAX_CLIENTS];
|
CSlot m_aSlots[NET_MAX_CONSOLE_CLIENTS];
|
||||||
|
|
||||||
NETFUNC_NEWCLIENT m_pfnNewClient;
|
NETFUNC_NEWCLIENT m_pfnNewClient;
|
||||||
NETFUNC_DELCLIENT m_pfnDelClient;
|
NETFUNC_DELCLIENT m_pfnDelClient;
|
||||||
|
@ -346,14 +341,13 @@ private:
|
||||||
CNetRecvUnpacker m_RecvUnpacker;
|
CNetRecvUnpacker m_RecvUnpacker;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
||||||
|
|
||||||
//
|
//
|
||||||
bool Open(NETADDR BindAddr, int Flags);
|
bool Open(NETADDR BindAddr, int Flags);
|
||||||
int Close();
|
int Close();
|
||||||
|
|
||||||
//
|
//
|
||||||
int Broadcast(const char *pLine);
|
|
||||||
int Recv(char *pLine, int MaxLength, int *pClientID = 0);
|
int Recv(char *pLine, int MaxLength, int *pClientID = 0);
|
||||||
int Send(int ClientID, const char *pLine);
|
int Send(int ClientID, const char *pLine);
|
||||||
int Update();
|
int Update();
|
||||||
|
@ -362,11 +356,7 @@ public:
|
||||||
int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
|
int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
|
||||||
int Drop(int ClientID, const char *pReason);
|
int Drop(int ClientID, const char *pReason);
|
||||||
|
|
||||||
//
|
|
||||||
void SetTimeout(int ClientID, int Timeout) { m_aSlots[ClientID].m_Connection.SetTimeout(Timeout); }
|
|
||||||
|
|
||||||
// status requests
|
// status requests
|
||||||
int Timeout(int ClientID) { return m_aSlots[ClientID].m_Connection.Timeout(); }
|
|
||||||
NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,25 +9,24 @@ bool CNetConsole::Open(NETADDR BindAddr, int Flags)
|
||||||
mem_zero(this, sizeof(*this));
|
mem_zero(this, sizeof(*this));
|
||||||
|
|
||||||
// open socket
|
// open socket
|
||||||
m_Socket = net_tcp_create(&BindAddr);
|
m_Socket = net_tcp_create(BindAddr);
|
||||||
if(!m_Socket.type)
|
if(!m_Socket.type)
|
||||||
return false;
|
return false;
|
||||||
if(net_tcp_listen(m_Socket, NET_MAX_CONSOLE_CLIENTS))
|
if(net_tcp_listen(m_Socket, NET_MAX_CONSOLE_CLIENTS))
|
||||||
return false;
|
return false;
|
||||||
net_tcp_set_non_blocking(m_Socket);
|
net_set_non_blocking(m_Socket);
|
||||||
|
|
||||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
||||||
m_aSlots[i].m_Connection.Init(m_Socket);
|
m_aSlots[i].m_Connection.Reset();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CNetConsole::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser)
|
void CNetConsole::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser)
|
||||||
{
|
{
|
||||||
m_pfnNewClient = pfnNewClient;
|
m_pfnNewClient = pfnNewClient;
|
||||||
m_pfnDelClient = pfnDelClient;
|
m_pfnDelClient = pfnDelClient;
|
||||||
m_UserPtr = pUser;
|
m_UserPtr = pUser;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CNetConsole::Close()
|
int CNetConsole::Close()
|
||||||
|
@ -38,11 +37,6 @@ int CNetConsole::Close()
|
||||||
|
|
||||||
int CNetConsole::Drop(int ClientID, const char *pReason)
|
int CNetConsole::Drop(int ClientID, const char *pReason)
|
||||||
{
|
{
|
||||||
NETADDR Addr = ClientAddr(ClientID);
|
|
||||||
|
|
||||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
||||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
|
||||||
|
|
||||||
if(m_pfnDelClient)
|
if(m_pfnDelClient)
|
||||||
m_pfnDelClient(ClientID, pReason, m_UserPtr);
|
m_pfnDelClient(ClientID, pReason, m_UserPtr);
|
||||||
|
|
||||||
|
@ -56,40 +50,39 @@ int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr)
|
||||||
char aError[256] = { 0 };
|
char aError[256] = { 0 };
|
||||||
int FreeSlot = -1;
|
int FreeSlot = -1;
|
||||||
|
|
||||||
|
// look for free slot or multiple client
|
||||||
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
||||||
{
|
{
|
||||||
if(FreeSlot == -1 && m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
if(FreeSlot == -1 && m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
||||||
FreeSlot = i;
|
FreeSlot = i;
|
||||||
if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE)
|
if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE)
|
||||||
{
|
{
|
||||||
NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();;
|
NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||||
if(net_addr_comp(pAddr, &PeerAddr) == 0)
|
if(net_addr_comp(pAddr, &PeerAddr) == 0)
|
||||||
{
|
{
|
||||||
str_copy(aError, "Only one client per IP allowed", sizeof(aError));
|
str_copy(aError, "only one client per IP allowed", sizeof(aError));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accept client
|
||||||
if(!aError[0] && FreeSlot != -1)
|
if(!aError[0] && FreeSlot != -1)
|
||||||
{
|
{
|
||||||
m_aSlots[FreeSlot].m_Connection.Init(Socket, pAddr);
|
m_aSlots[FreeSlot].m_Connection.Init(Socket, pAddr);
|
||||||
if(m_pfnNewClient)
|
if(m_pfnNewClient)
|
||||||
m_pfnNewClient(FreeSlot, m_UserPtr);
|
m_pfnNewClient(FreeSlot, m_UserPtr);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reject client
|
||||||
if(!aError[0])
|
if(!aError[0])
|
||||||
{
|
str_copy(aError, "no free slot available", sizeof(aError));
|
||||||
str_copy(aError, "No free slot available", sizeof(aError));
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg_msg("netconsole", "refused client, reason=\"%s\"", aError);
|
|
||||||
|
|
||||||
net_tcp_send(Socket, aError, str_length(aError));
|
net_tcp_send(Socket, aError, str_length(aError));
|
||||||
net_tcp_close(Socket);
|
net_tcp_close(Socket);
|
||||||
|
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CNetConsole::Update()
|
int CNetConsole::Update()
|
||||||
|
@ -127,18 +120,10 @@ int CNetConsole::Recv(char *pLine, int MaxLength, int *pClientID)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CNetConsole::Broadcast(const char *pLine)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
|
||||||
{
|
|
||||||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ONLINE)
|
|
||||||
Send(i, pLine);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CNetConsole::Send(int ClientID, const char *pLine)
|
int CNetConsole::Send(int ClientID, const char *pLine)
|
||||||
{
|
{
|
||||||
return m_aSlots[ClientID].m_Connection.Send(pLine);
|
if(m_aSlots[ClientID].m_Connection.State() == NET_CONNSTATE_ONLINE)
|
||||||
|
return m_aSlots[ClientID].m_Connection.Send(pLine);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
#include "config.h"
|
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
|
||||||
void CConsoleNetConnection::Reset()
|
void CConsoleNetConnection::Reset()
|
||||||
|
@ -10,9 +9,22 @@ void CConsoleNetConnection::Reset()
|
||||||
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
||||||
m_aErrorString[0] = 0;
|
m_aErrorString[0] = 0;
|
||||||
|
|
||||||
|
m_Socket.type = NETTYPE_INVALID;
|
||||||
|
m_Socket.ipv4sock = -1;
|
||||||
|
m_Socket.ipv6sock = -1;
|
||||||
m_aBuffer[0] = 0;
|
m_aBuffer[0] = 0;
|
||||||
m_pBufferPos = 0;
|
m_BufferOffset = 0;
|
||||||
m_Timeout = 0;
|
|
||||||
|
m_LineEndingDetected = false;
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
m_aLineEnding[0] = '\r';
|
||||||
|
m_aLineEnding[1] = '\n';
|
||||||
|
m_aLineEnding[2] = 0;
|
||||||
|
#else
|
||||||
|
m_aLineEnding[0] = '\n';
|
||||||
|
m_aLineEnding[1] = 0;
|
||||||
|
m_aLineEnding[2] = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsoleNetConnection::Init(NETSOCKET Socket, const NETADDR *pAddr)
|
void CConsoleNetConnection::Init(NETSOCKET Socket, const NETADDR *pAddr)
|
||||||
|
@ -20,48 +32,19 @@ void CConsoleNetConnection::Init(NETSOCKET Socket, const NETADDR *pAddr)
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
m_Socket = Socket;
|
m_Socket = Socket;
|
||||||
net_tcp_set_non_blocking(m_Socket);
|
net_set_non_blocking(m_Socket);
|
||||||
|
|
||||||
m_LastRecvTime = time_get();
|
|
||||||
|
|
||||||
m_PeerAddr = *pAddr;
|
m_PeerAddr = *pAddr;
|
||||||
m_State = NET_CONNSTATE_ONLINE;
|
m_State = NET_CONNSTATE_ONLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsoleNetConnection::Init(NETSOCKET Socket)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
m_Socket = Socket;
|
|
||||||
net_tcp_set_non_blocking(m_Socket);
|
|
||||||
|
|
||||||
m_LastRecvTime = time_get();
|
|
||||||
}
|
|
||||||
|
|
||||||
int CConsoleNetConnection::Connect(const NETADDR *pAddr)
|
|
||||||
{
|
|
||||||
if(State() != NET_CONNSTATE_OFFLINE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// init connection
|
|
||||||
Reset();
|
|
||||||
m_PeerAddr = *pAddr;
|
|
||||||
net_tcp_connect(m_Socket, pAddr);
|
|
||||||
m_State = NET_CONNSTATE_ONLINE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConsoleNetConnection::Disconnect(const char *pReason)
|
void CConsoleNetConnection::Disconnect(const char *pReason)
|
||||||
{
|
{
|
||||||
if(State() == NET_CONNSTATE_OFFLINE)
|
if(State() == NET_CONNSTATE_OFFLINE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(pReason)
|
if(pReason && pReason[0])
|
||||||
{
|
Send(pReason);
|
||||||
char aBuf[sizeof(pReason) + 4];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "%s", pReason);
|
|
||||||
Send(aBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
net_tcp_close(m_Socket);
|
net_tcp_close(m_Socket);
|
||||||
|
|
||||||
|
@ -70,32 +53,20 @@ void CConsoleNetConnection::Disconnect(const char *pReason)
|
||||||
|
|
||||||
int CConsoleNetConnection::Update()
|
int CConsoleNetConnection::Update()
|
||||||
{
|
{
|
||||||
if(m_Timeout && time_get() > m_LastRecvTime + m_Timeout * time_freq())
|
|
||||||
{
|
|
||||||
m_State = NET_CONNSTATE_ERROR;
|
|
||||||
str_copy(m_aErrorString, "timeout", sizeof(m_aErrorString));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(State() == NET_CONNSTATE_ONLINE)
|
if(State() == NET_CONNSTATE_ONLINE)
|
||||||
{
|
{
|
||||||
char aBuf[NET_MAX_PACKETSIZE];
|
if((int)(sizeof(m_aBuffer)) <= m_BufferOffset)
|
||||||
|
{
|
||||||
|
m_State = NET_CONNSTATE_ERROR;
|
||||||
|
str_copy(m_aErrorString, "too weak connection (out of buffer)", sizeof(m_aErrorString));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int Bytes = net_tcp_recv(m_Socket, aBuf, sizeof(aBuf) - 1);
|
int Bytes = net_tcp_recv(m_Socket, m_aBuffer+m_BufferOffset, (int)(sizeof(m_aBuffer))-m_BufferOffset);
|
||||||
|
|
||||||
if(Bytes > 0)
|
if(Bytes > 0)
|
||||||
{
|
{
|
||||||
aBuf[Bytes - 1] = 0;
|
m_BufferOffset += Bytes;
|
||||||
|
|
||||||
if(!m_pBufferPos)
|
|
||||||
m_aBuffer[0] = 0;
|
|
||||||
else if(m_pBufferPos != m_aBuffer)
|
|
||||||
mem_move(m_pBufferPos, m_aBuffer, str_length(m_pBufferPos) + 1); // +1 for the \0
|
|
||||||
m_pBufferPos = m_aBuffer;
|
|
||||||
|
|
||||||
str_append(m_aBuffer, aBuf, sizeof(m_aBuffer));
|
|
||||||
|
|
||||||
m_LastRecvTime = time_get();
|
|
||||||
}
|
}
|
||||||
else if(Bytes < 0)
|
else if(Bytes < 0)
|
||||||
{
|
{
|
||||||
|
@ -121,32 +92,59 @@ int CConsoleNetConnection::Recv(char *pLine, int MaxLength)
|
||||||
{
|
{
|
||||||
if(State() == NET_CONNSTATE_ONLINE)
|
if(State() == NET_CONNSTATE_ONLINE)
|
||||||
{
|
{
|
||||||
if(m_pBufferPos && *m_pBufferPos)
|
if(m_BufferOffset)
|
||||||
{
|
{
|
||||||
char *pResult = m_pBufferPos;
|
// find message start
|
||||||
|
int StartOffset = 0;
|
||||||
while(*m_pBufferPos && *m_pBufferPos != '\r' && *m_pBufferPos != '\n')
|
while(m_aBuffer[StartOffset] == '\r' || m_aBuffer[StartOffset] == '\n')
|
||||||
m_pBufferPos++;
|
|
||||||
|
|
||||||
if(*m_pBufferPos) // haven't reached the end of the buffer?
|
|
||||||
{
|
{
|
||||||
if(*m_pBufferPos == '\r' && *(m_pBufferPos + 1) == '\n')
|
// detect clients line ending format
|
||||||
|
if(!m_LineEndingDetected)
|
||||||
{
|
{
|
||||||
*m_pBufferPos = 0;
|
m_aLineEnding[0] = m_aBuffer[StartOffset];
|
||||||
m_pBufferPos += 2;
|
if(StartOffset+1 < m_BufferOffset && (m_aBuffer[StartOffset+1] == '\r' || m_aBuffer[StartOffset+1] == '\n') &&
|
||||||
|
m_aBuffer[StartOffset] != m_aBuffer[StartOffset+1])
|
||||||
|
m_aLineEnding[1] = m_aBuffer[StartOffset+1];
|
||||||
|
m_LineEndingDetected = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(++StartOffset >= m_BufferOffset)
|
||||||
{
|
{
|
||||||
*m_pBufferPos = 0;
|
m_BufferOffset = 0;
|
||||||
m_pBufferPos++;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// find message end
|
||||||
|
int EndOffset = StartOffset;
|
||||||
|
while(m_aBuffer[EndOffset] != '\r' && m_aBuffer[EndOffset] != '\n')
|
||||||
{
|
{
|
||||||
m_pBufferPos = 0;
|
if(++EndOffset >= m_BufferOffset)
|
||||||
|
{
|
||||||
|
if(StartOffset > 0)
|
||||||
|
{
|
||||||
|
mem_move(m_aBuffer, m_aBuffer+StartOffset, m_BufferOffset-StartOffset);
|
||||||
|
m_BufferOffset -= StartOffset;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
str_copy(pLine, pResult, MaxLength);
|
// extract message and update buffer
|
||||||
|
if(MaxLength-1 < EndOffset-StartOffset)
|
||||||
|
{
|
||||||
|
if(StartOffset > 0)
|
||||||
|
{
|
||||||
|
mem_move(m_aBuffer, m_aBuffer+StartOffset, m_BufferOffset-StartOffset);
|
||||||
|
m_BufferOffset -= StartOffset;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mem_copy(pLine, m_aBuffer+StartOffset, EndOffset-StartOffset);
|
||||||
|
pLine[EndOffset-StartOffset] = 0;
|
||||||
|
str_sanitize_cc(pLine);
|
||||||
|
mem_move(m_aBuffer, m_aBuffer+EndOffset, m_BufferOffset-EndOffset);
|
||||||
|
m_BufferOffset -= EndOffset;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,19 +156,31 @@ int CConsoleNetConnection::Send(const char *pLine)
|
||||||
if(State() != NET_CONNSTATE_ONLINE)
|
if(State() != NET_CONNSTATE_ONLINE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int Length = str_length(pLine);
|
|
||||||
char aBuf[1024];
|
char aBuf[1024];
|
||||||
str_copy(aBuf, pLine, sizeof(aBuf) - 2);
|
str_copy(aBuf, pLine, (int)(sizeof(aBuf))-2);
|
||||||
aBuf[Length + 1] = '\n';
|
int Length = str_length(aBuf);
|
||||||
aBuf[Length + 2] = '\0';
|
aBuf[Length] = m_aLineEnding[0];
|
||||||
|
aBuf[Length+1] = m_aLineEnding[1];
|
||||||
|
aBuf[Length+2] = m_aLineEnding[2];
|
||||||
|
Length += 3;
|
||||||
|
const char *pData = aBuf;
|
||||||
|
|
||||||
if(net_tcp_send(m_Socket, aBuf, Length + 2) < 0)
|
while(true)
|
||||||
{
|
{
|
||||||
m_State = NET_CONNSTATE_ERROR;
|
int Send = net_tcp_send(m_Socket, pData, Length);
|
||||||
str_copy(m_aErrorString, "Failed to send packet", sizeof(m_aErrorString));
|
if(Send < 0)
|
||||||
return -1;
|
{
|
||||||
|
m_State = NET_CONNSTATE_ERROR;
|
||||||
|
str_copy(m_aErrorString, "failed to send packet", sizeof(m_aErrorString));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Send >= Length)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pData += Send;
|
||||||
|
Length -= Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -662,6 +662,16 @@ void CGameConsole::ClientConsolePrintCallback(const char *pStr, void *pUserData)
|
||||||
((CGameConsole *)pUserData)->m_LocalConsole.PrintLine(pStr);
|
((CGameConsole *)pUserData)->m_LocalConsole.PrintLine(pStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGameConsole::ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||||
|
{
|
||||||
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
|
if(pResult->NumArguments() == 1)
|
||||||
|
{
|
||||||
|
CGameConsole *pThis = static_cast<CGameConsole *>(pUserData);
|
||||||
|
pThis->Console()->SetPrintOutputLevel(pThis->m_PrintCBIndex, pResult->GetInteger(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGameConsole::PrintLine(int Type, const char *pLine)
|
void CGameConsole::PrintLine(int Type, const char *pLine)
|
||||||
{
|
{
|
||||||
if(Type == CONSOLETYPE_LOCAL)
|
if(Type == CONSOLETYPE_LOCAL)
|
||||||
|
@ -679,7 +689,7 @@ void CGameConsole::OnConsoleInit()
|
||||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
|
|
||||||
//
|
//
|
||||||
Console()->RegisterPrintCallback(ClientConsolePrintCallback, this);
|
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, ClientConsolePrintCallback, this);
|
||||||
|
|
||||||
Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console");
|
Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console");
|
||||||
Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console");
|
Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console");
|
||||||
|
@ -687,6 +697,8 @@ void CGameConsole::OnConsoleInit()
|
||||||
Console()->Register("clear_remote_console", "", CFGFLAG_CLIENT, ConClearRemoteConsole, this, "Clear remote console");
|
Console()->Register("clear_remote_console", "", CFGFLAG_CLIENT, ConClearRemoteConsole, this, "Clear remote console");
|
||||||
Console()->Register("dump_local_console", "", CFGFLAG_CLIENT, ConDumpLocalConsole, this, "Dump local console");
|
Console()->Register("dump_local_console", "", CFGFLAG_CLIENT, ConDumpLocalConsole, this, "Dump local console");
|
||||||
Console()->Register("dump_remote_console", "", CFGFLAG_CLIENT, ConDumpRemoteConsole, this, "Dump remote console");
|
Console()->Register("dump_remote_console", "", CFGFLAG_CLIENT, ConDumpRemoteConsole, this, "Dump remote console");
|
||||||
|
|
||||||
|
Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameConsole::OnStateChange(int NewState, int OldState)
|
void CGameConsole::OnStateChange(int NewState, int OldState)
|
||||||
|
|
|
@ -60,6 +60,7 @@ class CGameConsole : public CComponent
|
||||||
|
|
||||||
CInstance *CurrentConsole();
|
CInstance *CurrentConsole();
|
||||||
float TimeNow();
|
float TimeNow();
|
||||||
|
int m_PrintCBIndex;
|
||||||
|
|
||||||
int m_ConsoleType;
|
int m_ConsoleType;
|
||||||
int m_ConsoleState;
|
int m_ConsoleState;
|
||||||
|
@ -77,6 +78,7 @@ class CGameConsole : public CComponent
|
||||||
static void ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData);
|
static void ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData);
|
||||||
static void ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData);
|
static void ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData);
|
||||||
static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData);
|
static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData);
|
||||||
|
static void ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
|
|
Loading…
Reference in a new issue