mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge branch 'master' of git://github.com/oy/teeworlds into DDRace
Conflicts: src/engine/console.h src/engine/server/server.cpp src/engine/server/server.h src/engine/shared/config.h src/engine/shared/console.cpp src/engine/shared/console.h src/engine/shared/network_server.cpp @heinrich5991 todo
This commit is contained in:
commit
ee670118a5
|
@ -135,7 +135,7 @@ static IOHANDLE logfile = 0;
|
|||
static void logger_file(const char *line)
|
||||
{
|
||||
io_write(logfile, line, strlen(line));
|
||||
io_write(logfile, "\n", 1);
|
||||
io_write_newline(logfile);
|
||||
io_flush(logfile);
|
||||
}
|
||||
|
||||
|
@ -152,8 +152,6 @@ void dbg_logger_file(const char *filename)
|
|||
}
|
||||
/* */
|
||||
|
||||
int memory_alloced = 0;
|
||||
|
||||
typedef struct MEMHEADER
|
||||
{
|
||||
const char *filename;
|
||||
|
@ -175,8 +173,10 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al
|
|||
{
|
||||
/* TODO: fix alignment */
|
||||
/* TODO: add debugging */
|
||||
MEMTAIL *tail;
|
||||
MEMHEADER *header = (struct MEMHEADER *)malloc(size+sizeof(MEMHEADER)+sizeof(MEMTAIL));
|
||||
MEMTAIL *tail = (struct MEMTAIL *)(((char*)(header+1))+size);
|
||||
dbg_assert(header != 0, "mem_alloc failure");
|
||||
tail = (struct MEMTAIL *)(((char*)(header+1))+size);
|
||||
header->size = size;
|
||||
header->filename = filename;
|
||||
header->line = line;
|
||||
|
@ -232,8 +232,9 @@ void mem_debug_dump(IOHANDLE file)
|
|||
{
|
||||
while(header)
|
||||
{
|
||||
str_format(buf, sizeof(buf), "%s(%d): %d\n", header->filename, header->line, header->size);
|
||||
str_format(buf, sizeof(buf), "%s(%d): %d", header->filename, header->line, header->size);
|
||||
io_write(file, buf, strlen(buf));
|
||||
io_write_newline(file);
|
||||
header = header->next;
|
||||
}
|
||||
|
||||
|
@ -356,6 +357,15 @@ unsigned io_write(IOHANDLE io, const void *buffer, unsigned size)
|
|||
return fwrite(buffer, 1, size, (FILE*)io);
|
||||
}
|
||||
|
||||
unsigned io_write_newline(IOHANDLE io)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
return fwrite("\r\n", 1, 2, (FILE*)io);
|
||||
#else
|
||||
return fwrite("\n", 1, 1, (FILE*)io);
|
||||
#endif
|
||||
}
|
||||
|
||||
int io_close(IOHANDLE io)
|
||||
{
|
||||
fclose((FILE*)io);
|
||||
|
@ -595,18 +605,18 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b)
|
|||
return mem_comp(a, b, sizeof(NETADDR));
|
||||
}
|
||||
|
||||
void net_addr_str(const NETADDR *addr, char *string, int max_length)
|
||||
void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port)
|
||||
{
|
||||
if(addr->type == NETTYPE_IPV4)
|
||||
{
|
||||
if(addr->port != 0)
|
||||
if(add_port != 0)
|
||||
str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port);
|
||||
else
|
||||
str_format(string, max_length, "%d.%d.%d.%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3]);
|
||||
}
|
||||
else if(addr->type == NETTYPE_IPV6)
|
||||
{
|
||||
if(addr->port != 0)
|
||||
if(add_port != 0)
|
||||
str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
|
||||
(addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7],
|
||||
(addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15],
|
||||
|
@ -1510,7 +1520,7 @@ int net_socket_read_wait(NETSOCKET sock, int time)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned time_timestamp()
|
||||
int time_timestamp()
|
||||
{
|
||||
return time(0);
|
||||
}
|
||||
|
|
|
@ -239,6 +239,18 @@ unsigned io_skip(IOHANDLE io, int size);
|
|||
*/
|
||||
unsigned io_write(IOHANDLE io, const void *buffer, unsigned size);
|
||||
|
||||
/*
|
||||
Function: io_write_newline
|
||||
Writes newline to file.
|
||||
|
||||
Parameters:
|
||||
io - Handle to the file.
|
||||
|
||||
Returns:
|
||||
Number of bytes written.
|
||||
*/
|
||||
unsigned io_write_newline(IOHANDLE io);
|
||||
|
||||
/*
|
||||
Function: io_seek
|
||||
Seeks to a specified offset in the file.
|
||||
|
@ -425,7 +437,7 @@ int64 time_freq();
|
|||
Returns:
|
||||
The time as a UNIX timestamp
|
||||
*/
|
||||
unsigned time_timestamp();
|
||||
int time_timestamp();
|
||||
|
||||
/* Group: Network General */
|
||||
typedef struct
|
||||
|
@ -499,12 +511,13 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b);
|
|||
addr - Address to turn into a string.
|
||||
string - Buffer to fill with the string.
|
||||
max_length - Maximum size of the string.
|
||||
add_port - add port to string or not
|
||||
|
||||
Remarks:
|
||||
- The string will always be zero terminated
|
||||
|
||||
*/
|
||||
void net_addr_str(const NETADDR *addr, char *string, int max_length);
|
||||
void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port);
|
||||
|
||||
/*
|
||||
Function: net_addr_from_str
|
||||
|
@ -1130,25 +1143,6 @@ void mem_debug_dump(IOHANDLE file);
|
|||
|
||||
void swap_endian(void *data, unsigned elem_size, unsigned num);
|
||||
|
||||
/* Group: Debug levels */
|
||||
//by format
|
||||
enum {
|
||||
DBG_FMT_RAW = 1, //raw output
|
||||
DBG_FMT_TIME = 2, //show time
|
||||
DBG_FMT_SYS = 3, //show sys
|
||||
DBG_FMT_FULL = 4 //show both
|
||||
};
|
||||
|
||||
enum {
|
||||
DBG_LEVEL_IMPORTANT = 0, //important always showed messages
|
||||
DBG_LEVEL_ERROR = 1, //error messages
|
||||
DBG_LEVEL_WARNING = 2, //warning messages
|
||||
DBG_LEVEL_MSG = 3, //extra debug messages
|
||||
DBG_LEVEL_INFO = 4 //info messages
|
||||
};
|
||||
|
||||
#define DBG_LEVEL_LOW DBG_LEVEL_IMPORTANT
|
||||
#define DBG_LEVEL_HIGH DBG_LEVEL_INFO
|
||||
|
||||
typedef void (*DBG_LOGGER)(const char *line);
|
||||
void dbg_logger(DBG_LOGGER logger);
|
||||
|
|
|
@ -546,6 +546,7 @@ void CClient::DisconnectWithReason(const char *pReason)
|
|||
|
||||
//
|
||||
m_RconAuthed = 0;
|
||||
m_UseTempRconCommands = 0;
|
||||
m_pConsole->DeregisterTempAll();
|
||||
m_NetClient.Disconnect(pReason);
|
||||
SetState(IClient::STATE_OFFLINE);
|
||||
|
@ -967,7 +968,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
|||
Info.m_NumPlayers < 0 || Info.m_NumPlayers > Info.m_NumClients || Info.m_MaxPlayers < 0 || Info.m_MaxPlayers > Info.m_MaxClients)
|
||||
return;
|
||||
|
||||
net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress));
|
||||
net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress), true);
|
||||
|
||||
for(int i = 0; i < Info.m_NumClients; i++)
|
||||
{
|
||||
|
@ -1156,9 +1157,12 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
|||
int Result = Unpacker.GetInt();
|
||||
if(Unpacker.Error() == 0)
|
||||
m_RconAuthed = Result;
|
||||
int Old = m_UseTempRconCommands;
|
||||
m_UseTempRconCommands = Unpacker.GetInt();
|
||||
if(Unpacker.Error() != 0)
|
||||
m_UseTempRconCommands = 0;
|
||||
if(Old != 0 && m_UseTempRconCommands == 0)
|
||||
m_pConsole->DeregisterTempAll();
|
||||
}
|
||||
else if(Msg == NETMSG_RCON_LINE)
|
||||
{
|
||||
|
|
|
@ -370,7 +370,6 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
|
|||
}*/
|
||||
|
||||
pEntry->m_GotInfo = 1;
|
||||
Sort();
|
||||
}
|
||||
|
||||
CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
|
||||
|
@ -388,7 +387,7 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
|
|||
pEntry->m_Info.m_NetAddr = Addr;
|
||||
|
||||
pEntry->m_Info.m_Latency = 999;
|
||||
net_addr_str(&Addr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress));
|
||||
net_addr_str(&Addr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), true);
|
||||
str_copy(pEntry->m_Info.m_aName, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aName));
|
||||
|
||||
// check if it's a favorite
|
||||
|
@ -528,7 +527,7 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons
|
|||
if(g_Config.m_Debug)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true);
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf),"requesting server info from %s", aAddrStr);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf);
|
||||
|
@ -669,7 +668,7 @@ void CServerBrowser::AddFavorite(const NETADDR &Addr)
|
|||
if(g_Config.m_Debug)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true);
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "added fav, %s", aAddrStr);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf);
|
||||
|
@ -723,12 +722,11 @@ void CServerBrowser::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
|
|||
{
|
||||
CServerBrowser *pSelf = (CServerBrowser *)pUserData;
|
||||
|
||||
int i;
|
||||
char aAddrStr[128];
|
||||
char aBuffer[256];
|
||||
for(i = 0; i < pSelf->m_NumFavoriteServers; i++)
|
||||
for(int i = 0; i < pSelf->m_NumFavoriteServers; i++)
|
||||
{
|
||||
net_addr_str(&pSelf->m_aFavoriteServers[i], aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&pSelf->m_aFavoriteServers[i], aAddrStr, sizeof(aAddrStr), true);
|
||||
str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr);
|
||||
pConfig->WriteLine(aBuffer);
|
||||
}
|
||||
|
|
|
@ -285,7 +285,8 @@ class CTextRender : public IEngineTextRender
|
|||
Oldest = i;
|
||||
}
|
||||
|
||||
if(time_get()-pSizeData->m_aCharacters[Oldest].m_TouchTime < time_freq())
|
||||
if(time_get()-pSizeData->m_aCharacters[Oldest].m_TouchTime < time_freq() &&
|
||||
(pSizeData->m_NumXChars < MAX_CHARACTERS || pSizeData->m_NumYChars < MAX_CHARACTERS))
|
||||
{
|
||||
IncreaseTextureSize(pSizeData);
|
||||
return GetSlot(pSizeData);
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
|
||||
virtual bool LineIsValid(const char *pStr) = 0;
|
||||
virtual void ExecuteLine(const char *Sptr, int ClientID = -1) = 0;
|
||||
virtual void ExecuteLineFlag(const char *Sptr, int FlasgMask) = 0;
|
||||
virtual void ExecuteLineStroked(int Stroke, const char *pStr, int ClientID = -1) = 0;
|
||||
virtual void ExecuteFile(const char *pFilename, int ClientID = -1) = 0;
|
||||
|
||||
|
|
1
src/engine/external/pnglite/VERSION
vendored
Normal file
1
src/engine/external/pnglite/VERSION
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
0.1.17
|
1
src/engine/external/wavpack/VERSION
vendored
Normal file
1
src/engine/external/wavpack/VERSION
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
4.40
|
|
@ -55,6 +55,12 @@ public:
|
|||
|
||||
virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
RCON_CID_SERV=-1,
|
||||
RCON_CID_VOTE=-2,
|
||||
};
|
||||
virtual void SetRconCID(int ClientID) = 0;
|
||||
virtual bool IsAuthed(int ClientID) = 0;
|
||||
virtual void Kick(int ClientID, const char *pReason) = 0;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <engine/shared/econ.h>
|
||||
#include <engine/shared/filecollection.h>
|
||||
#include <engine/shared/mapchecker.h>
|
||||
#include <engine/shared/netban.h>
|
||||
#include <engine/shared/network.h>
|
||||
#include <engine/shared/packer.h>
|
||||
#include <engine/shared/protocol.h>
|
||||
|
@ -45,37 +46,48 @@
|
|||
|
||||
static const char SERVER_BANMASTERFILE[] = "banmasters.cfg";
|
||||
|
||||
static const char *StrLtrim(const char *pStr)
|
||||
{
|
||||
while(*pStr && *pStr >= 0 && *pStr <= 32)
|
||||
pStr++;
|
||||
return pStr;
|
||||
}
|
||||
|
||||
static void StrRtrim(char *pStr)
|
||||
{
|
||||
int i = str_length(pStr);
|
||||
while(i >= 0)
|
||||
{
|
||||
if(pStr[i] < 0 || pStr[i] > 32)
|
||||
break;
|
||||
pStr[i] = 0;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int StrAllnum(const char *pStr)
|
||||
static const char *StrUTF8Ltrim(const char *pStr)
|
||||
{
|
||||
while(*pStr)
|
||||
{
|
||||
if(!(*pStr >= '0' && *pStr <= '9'))
|
||||
return 0;
|
||||
pStr++;
|
||||
const char *pStrOld = pStr;
|
||||
int Code = str_utf8_decode(&pStr);
|
||||
|
||||
// check if unicode is not empty
|
||||
if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
|
||||
(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
|
||||
Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
|
||||
{
|
||||
return pStrOld;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return pStr;
|
||||
}
|
||||
|
||||
static void StrUTF8Rtrim(char *pStr)
|
||||
{
|
||||
const char *p = pStr;
|
||||
const char *pEnd = 0;
|
||||
while(*p)
|
||||
{
|
||||
const char *pStrOld = p;
|
||||
int Code = str_utf8_decode(&p);
|
||||
|
||||
// check if unicode is not empty
|
||||
if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
|
||||
(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
|
||||
Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
|
||||
{
|
||||
pEnd = 0;
|
||||
}
|
||||
else if(pEnd == 0)
|
||||
pEnd = pStrOld;
|
||||
}
|
||||
if(pEnd != 0)
|
||||
*(const_cast<char *>(pEnd)) = 0;
|
||||
}
|
||||
|
||||
|
||||
CSnapIDPool::CSnapIDPool()
|
||||
{
|
||||
Reset();
|
||||
|
@ -164,6 +176,115 @@ void CSnapIDPool::FreeID(int ID)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void CServerBan::Init(IConsole *pConsole, IStorage *pStorage, CServer* pServer)
|
||||
{
|
||||
CNetBan::Init(pConsole, pStorage);
|
||||
|
||||
m_pServer = pServer;
|
||||
|
||||
// overwrites base command, todo: improve this
|
||||
Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBanExt, this, "Ban player with ip/client id for x minutes for any reason");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int CServerBan::BanExt(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason)
|
||||
{
|
||||
// validate address
|
||||
if(Server()->m_RconClientID >= 0 && Server()->m_RconClientID < MAX_CLIENTS &&
|
||||
Server()->m_aClients[Server()->m_RconClientID].m_State != CServer::CClient::STATE_EMPTY)
|
||||
{
|
||||
if(NetMatch(pData, Server()->m_NetServer.ClientAddr(Server()->m_RconClientID)))
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (you can't ban yourself)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(i == Server()->m_RconClientID || Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY)
|
||||
continue;
|
||||
|
||||
if(Server()->m_aClients[i].m_Authed >= Server()->m_RconAuthLevel && NetMatch(pData, Server()->m_NetServer.ClientAddr(i)))
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (command denied)");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(Server()->m_RconClientID == IServer::RCON_CID_VOTE)
|
||||
{
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY)
|
||||
continue;
|
||||
|
||||
if(Server()->m_aClients[i].m_Authed != CServer::AUTHED_NO && NetMatch(pData, Server()->m_NetServer.ClientAddr(i)))
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (command denied)");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Result = Ban(pBanPool, pData, Seconds, pReason);
|
||||
if(Result != 0)
|
||||
return Result;
|
||||
|
||||
// drop banned clients
|
||||
typename T::CDataType Data = *pData;
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY)
|
||||
continue;
|
||||
|
||||
if(NetMatch(&Data, Server()->m_NetServer.ClientAddr(i)))
|
||||
{
|
||||
CNetHash NetHash(&Data);
|
||||
char aBuf[256];
|
||||
MakeBanInfo(pBanPool->Find(&Data, &NetHash), aBuf, sizeof(aBuf), MSGTYPE_PLAYER);
|
||||
Server()->m_NetServer.Drop(i, aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
int CServerBan::BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason)
|
||||
{
|
||||
return BanExt(&m_BanAddrPool, pAddr, Seconds, pReason);
|
||||
}
|
||||
|
||||
int CServerBan::BanRange(const CNetRange *pRange, int Seconds, const char *pReason)
|
||||
{
|
||||
if(pRange->IsValid())
|
||||
return BanExt(&m_BanRangePool, pRange, Seconds, pReason);
|
||||
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CServerBan::ConBanExt(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServerBan *pThis = static_cast<CServerBan *>(pUser);
|
||||
|
||||
const char *pStr = pResult->GetString(0);
|
||||
int Minutes = pResult->NumArguments()>1 ? clamp(pResult->GetInteger(1), 0, 44640) : 30;
|
||||
const char *pReason = pResult->NumArguments()>2 ? pResult->GetString(2) : "No reason given";
|
||||
|
||||
if(StrAllnum(pStr))
|
||||
{
|
||||
int ClientID = str_toint(pStr);
|
||||
if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->Server()->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid client id)");
|
||||
else
|
||||
pThis->BanAddr(pThis->Server()->m_NetServer.ClientAddr(ClientID), Minutes*60, pReason);
|
||||
}
|
||||
else
|
||||
ConBan(pResult, pUser);
|
||||
}
|
||||
|
||||
|
||||
void CServer::CClient::Reset()
|
||||
{
|
||||
// reset input
|
||||
|
@ -193,7 +314,7 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
|
|||
|
||||
m_MapReload = 0;
|
||||
|
||||
m_RconClientID = -1;
|
||||
m_RconClientID = IServer::RCON_CID_SERV;
|
||||
m_RconAuthLevel = AUTHED_ADMIN;
|
||||
|
||||
Init();
|
||||
|
@ -205,8 +326,8 @@ int CServer::TrySetClientName(int ClientID, const char *pName)
|
|||
char aTrimmedName[64];
|
||||
|
||||
// trim the name
|
||||
str_copy(aTrimmedName, StrLtrim(pName), sizeof(aTrimmedName));
|
||||
StrRtrim(aTrimmedName);
|
||||
str_copy(aTrimmedName, StrUTF8Ltrim(pName), sizeof(aTrimmedName));
|
||||
StrUTF8Rtrim(aTrimmedName);
|
||||
|
||||
// check if new and old name are the same
|
||||
if(m_aClients[ClientID].m_aName[0] && str_comp(m_aClients[ClientID].m_aName, aTrimmedName) == 0)
|
||||
|
@ -337,6 +458,11 @@ int CServer::Init()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void CServer::SetRconCID(int ClientID)
|
||||
{
|
||||
m_RconClientID = ClientID;
|
||||
}
|
||||
|
||||
bool CServer::IsAuthed(int ClientID)
|
||||
{
|
||||
return m_aClients[ClientID].m_Authed;
|
||||
|
@ -359,11 +485,7 @@ int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo)
|
|||
void CServer::GetClientAddr(int ClientID, char *pAddrStr, int Size)
|
||||
{
|
||||
if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME)
|
||||
{
|
||||
NETADDR Addr = m_NetServer.ClientAddr(ClientID);
|
||||
Addr.port = 0;
|
||||
net_addr_str(&Addr, pAddrStr, Size);
|
||||
}
|
||||
net_addr_str(m_NetServer.ClientAddr(ClientID), pAddrStr, Size, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -601,7 +723,6 @@ int CServer::NewClientCallback(int ClientID, void *pUser)
|
|||
pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
|
||||
pThis->m_aClients[ClientID].m_AuthTries = 0;
|
||||
pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
|
||||
memset(&pThis->m_aClients[ClientID].m_Addr, 0, sizeof(NETADDR));
|
||||
pThis->m_aClients[ClientID].Reset();
|
||||
return 0;
|
||||
}
|
||||
|
@ -610,9 +731,8 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
|||
{
|
||||
CServer *pThis = (CServer *)pUser;
|
||||
|
||||
NETADDR Addr = pThis->m_NetServer.ClientAddr(ClientID);
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(pThis->m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
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, "server", aBuf);
|
||||
|
@ -629,7 +749,6 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
|||
pThis->m_aClients[ClientID].m_AuthTries = 0;
|
||||
pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
|
||||
pThis->m_aPrevStates[ClientID] = CClient::STATE_EMPTY;
|
||||
memset(&pThis->m_aClients[ClientID].m_Addr, 0, sizeof(NETADDR));
|
||||
pThis->m_aClients[ClientID].m_Snapshots.PurgeAll();
|
||||
return 0;
|
||||
}
|
||||
|
@ -708,7 +827,6 @@ void CServer::UpdateClientRconCommands()
|
|||
void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
||||
{
|
||||
int ClientID = pPacket->m_ClientID;
|
||||
NETADDR Addr;
|
||||
CUnpacker Unpacker;
|
||||
Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize);
|
||||
|
||||
|
@ -794,9 +912,8 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
{
|
||||
if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING)
|
||||
{
|
||||
Addr = m_NetServer.ClientAddr(ClientID);
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr);
|
||||
|
@ -810,10 +927,8 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
{
|
||||
if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID))
|
||||
{
|
||||
Addr = m_NetServer.ClientAddr(ClientID);
|
||||
m_aClients[ClientID].m_Addr = Addr;
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr);
|
||||
|
@ -886,9 +1001,9 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
m_RconClientID = ClientID;
|
||||
m_RconAuthLevel = m_aClients[ClientID].m_Authed;
|
||||
Console()->SetAccessLevel(m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : m_aClients[ClientID].m_Authed == AUTHED_MOD ? IConsole::ACCESS_LEVEL_MOD : IConsole::ACCESS_LEVEL_USER);
|
||||
Console()->ExecuteLine(pCmd, ClientID);
|
||||
Console()->ExecuteLineFlag(pCmd, CFGFLAG_SERVER);
|
||||
Console()->SetAccessLevel(IConsole::ACCESS_LEVEL_ADMIN);
|
||||
m_RconClientID = -1;
|
||||
m_RconClientID = IServer::RCON_CID_SERV;
|
||||
m_RconAuthLevel = AUTHED_ADMIN;
|
||||
}
|
||||
}
|
||||
|
@ -955,10 +1070,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
if(!g_Config.m_SvRconBantime)
|
||||
m_NetServer.Drop(ClientID, "Too many remote console authentication tries");
|
||||
else
|
||||
{
|
||||
NETADDR Addr = m_NetServer.ClientAddr(ClientID);
|
||||
BanAdd(Addr, g_Config.m_SvRconBantime*60, "Too many remote console authentication tries");
|
||||
}
|
||||
m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), g_Config.m_SvRconBantime*60, "Too many remote console authentication tries");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1002,7 +1114,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
}
|
||||
}
|
||||
|
||||
void CServer::SendServerInfo(NETADDR *pAddr, int Token)
|
||||
void CServer::SendServerInfo(const NETADDR *pAddr, int Token)
|
||||
{
|
||||
CNetChunk Packet;
|
||||
CPacker p;
|
||||
|
@ -1071,38 +1183,10 @@ void CServer::UpdateServerInfo()
|
|||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(m_aClients[i].m_State != CClient::STATE_EMPTY)
|
||||
{
|
||||
NETADDR Addr = m_NetServer.ClientAddr(i);
|
||||
SendServerInfo(&Addr, -1);
|
||||
}
|
||||
SendServerInfo(m_NetServer.ClientAddr(i), -1);
|
||||
}
|
||||
}
|
||||
|
||||
int CServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason)
|
||||
{
|
||||
Addr.port = 0;
|
||||
char aAddrStr[128];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
char aBuf[256];
|
||||
if(Seconds)
|
||||
str_format(aBuf, sizeof(aBuf), "banned %s for %d minutes", aAddrStr, Seconds/60);
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "banned %s for life", aAddrStr);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
|
||||
return m_NetServer.BanAdd(Addr, Seconds, pReason);
|
||||
}
|
||||
|
||||
int CServer::BanRemove(NETADDR Addr)
|
||||
{
|
||||
return m_NetServer.BanRemove(Addr);
|
||||
}
|
||||
|
||||
int CServer::BanRemoveAll()
|
||||
{
|
||||
return m_NetServer.BanRemoveAll();
|
||||
}
|
||||
|
||||
|
||||
void CServer::PumpNetwork()
|
||||
{
|
||||
|
@ -1151,7 +1235,8 @@ void CServer::PumpNetwork()
|
|||
return;
|
||||
}
|
||||
|
||||
m_NetServer.BanAdd(Addr, g_Config.m_SvGlobalBantime * 60, aReason);
|
||||
// TODO(heinrich5991): fix banmaster global ban addition
|
||||
//m_NetServer.BanAdd(Addr, g_Config.m_SvGlobalBantime * 60, aReason);
|
||||
dbg_msg("globalbans", "added ban, ip=%s, reason='%s'", aIp, aReason);
|
||||
}
|
||||
}
|
||||
|
@ -1160,6 +1245,7 @@ void CServer::PumpNetwork()
|
|||
ProcessClientPacket(&Packet);
|
||||
}
|
||||
|
||||
m_ServerBan.Update();
|
||||
m_Econ.Update();
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1348,7 @@ int CServer::Run()
|
|||
BindAddr.port = g_Config.m_SvPort;
|
||||
}
|
||||
|
||||
if(!m_NetServer.Open(BindAddr, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0))
|
||||
if(!m_NetServer.Open(BindAddr, &m_ServerBan, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0))
|
||||
{
|
||||
dbg_msg("server", "couldn't open socket. port might already be in use");
|
||||
return -1;
|
||||
|
@ -1270,7 +1356,8 @@ int CServer::Run()
|
|||
|
||||
m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
|
||||
|
||||
m_Econ.Init(Console());
|
||||
m_ServerBan.Init(Console(), Storage(), this);
|
||||
m_Econ.Init(Console(), &m_ServerBan);
|
||||
|
||||
Console()->ExecuteFile(SERVER_BANMASTERFILE);
|
||||
|
||||
|
@ -1435,170 +1522,23 @@ void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
|
|||
((CServer *)pUser)->Kick(pResult->GetInteger(0), "Kicked by console");
|
||||
}
|
||||
|
||||
void CServer::ConBan(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
NETADDR Addr;
|
||||
CServer *pServer = (CServer *)pUser;
|
||||
const char *pStr = pResult->GetString(0);
|
||||
int Minutes = 30;
|
||||
const char *pReason = "No reason given";
|
||||
|
||||
if(pResult->NumArguments() > 1)
|
||||
Minutes = min(max(0, pResult->GetInteger(1)), 1000000); // todo: fix this in year 2035
|
||||
|
||||
if(pResult->NumArguments() > 2)
|
||||
pReason = pResult->GetString(2);
|
||||
|
||||
if(net_addr_from_str(&Addr, pStr) == 0)
|
||||
{
|
||||
if(pServer->m_RconClientID >= 0 && pServer->m_RconClientID < MAX_CLIENTS && pServer->m_aClients[pServer->m_RconClientID].m_State != CClient::STATE_EMPTY)
|
||||
{
|
||||
NETADDR AddrCheck = pServer->m_NetServer.ClientAddr(pServer->m_RconClientID);
|
||||
Addr.port = AddrCheck.port = 0;
|
||||
if(net_addr_comp(&Addr, &AddrCheck) == 0)
|
||||
{
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't ban yourself");
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(i == pServer->m_RconClientID)
|
||||
continue;
|
||||
|
||||
AddrCheck = pServer->m_NetServer.ClientAddr(i);
|
||||
AddrCheck.port = 0;
|
||||
if(net_addr_comp(&Addr, &AddrCheck) == 0 && pServer->m_aClients[i].m_Authed > pServer->m_RconAuthLevel)
|
||||
{
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "ban command denied");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
pServer->BanAdd(Addr, Minutes*60, pReason);
|
||||
}
|
||||
else if(StrAllnum(pStr))
|
||||
{
|
||||
int ClientID = str_toint(pStr);
|
||||
|
||||
if(ClientID < 0 || ClientID >= MAX_CLIENTS || pServer->m_aClients[ClientID].m_State == CClient::STATE_EMPTY)
|
||||
{
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid client id");
|
||||
return;
|
||||
}
|
||||
else if(pServer->m_RconClientID == ClientID)
|
||||
{
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't ban yourself");
|
||||
return;
|
||||
}
|
||||
else if(pServer->m_aClients[ClientID].m_Authed > pServer->m_RconAuthLevel)
|
||||
{
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "ban command denied");
|
||||
return;
|
||||
}
|
||||
|
||||
Addr = pServer->m_NetServer.ClientAddr(ClientID);
|
||||
pServer->BanAdd(Addr, Minutes*60, pReason);
|
||||
}
|
||||
else
|
||||
{
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid network address to ban");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::ConUnban(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
NETADDR Addr;
|
||||
CServer *pServer = (CServer *)pUser;
|
||||
const char *pStr = pResult->GetString(0);
|
||||
|
||||
if(net_addr_from_str(&Addr, pStr) == 0 && !pServer->BanRemove(Addr))
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "unbanned %s", aAddrStr);
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
}
|
||||
else if(StrAllnum(pStr))
|
||||
{
|
||||
int BanIndex = str_toint(pStr);
|
||||
CNetServer::CBanInfo Info;
|
||||
if(BanIndex < 0 || !pServer->m_NetServer.BanGet(BanIndex, &Info))
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid ban index");
|
||||
else if(!pServer->BanRemove(Info.m_Addr))
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Info.m_Addr, aAddrStr, sizeof(aAddrStr));
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "unbanned %s", aAddrStr);
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid network address");
|
||||
}
|
||||
|
||||
void CServer::ConUnbanAll(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServer *pServer = (CServer *)pUser;
|
||||
if(!pServer->BanRemoveAll())
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "unbanned all");
|
||||
}
|
||||
|
||||
void CServer::ConBans(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
unsigned Now = time_timestamp();
|
||||
char aBuf[1024];
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
CServer* pServer = (CServer *)pUser;
|
||||
|
||||
int Num = pServer->m_NetServer.BanNum();
|
||||
for(int i = 0; i < Num; i++)
|
||||
{
|
||||
CNetServer::CBanInfo Info;
|
||||
pServer->m_NetServer.BanGet(i, &Info);
|
||||
NETADDR Addr = Info.m_Addr;
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
|
||||
if(Info.m_Expires == -1)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "#%i %s for life", i, aAddrStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned t = Info.m_Expires - Now;
|
||||
str_format(aBuf, sizeof(aBuf), "#%i %s for %d minutes and %d seconds", i, aAddrStr, t/60, t%60);
|
||||
}
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
|
||||
}
|
||||
str_format(aBuf, sizeof(aBuf), "%d ban(s)", Num);
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
|
||||
}
|
||||
|
||||
void CServer::ConStatus(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
int i;
|
||||
NETADDR Addr;
|
||||
char aBuf[1024];
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
CServer* pServer = (CServer *)pUser;
|
||||
CServer* pThis = static_cast<CServer *>(pUser);
|
||||
|
||||
for(i = 0; i < MAX_CLIENTS; i++)
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(pServer->m_aClients[i].m_State != CClient::STATE_EMPTY)
|
||||
if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY)
|
||||
{
|
||||
Addr = pServer->m_NetServer.ClientAddr(i);
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
|
||||
if(pServer->m_aClients[i].m_State == CClient::STATE_INGAME)
|
||||
net_addr_str(pThis->m_NetServer.ClientAddr(i), aAddrStr, sizeof(aAddrStr), true);
|
||||
if(pThis->m_aClients[i].m_State == CClient::STATE_INGAME)
|
||||
str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d", i, aAddrStr,
|
||||
pServer->m_aClients[i].m_aName, pServer->m_aClients[i].m_Score);
|
||||
pThis->m_aClients[i].m_aName, pThis->m_aClients[i].m_Score);
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr);
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1653,6 +1593,27 @@ void CServer::ConMapReload(IConsole::IResult *pResult, void *pUser)
|
|||
((CServer *)pUser)->m_MapReload = 1;
|
||||
}
|
||||
|
||||
void CServer::ConLogout(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServer *pServer = (CServer *)pUser;
|
||||
|
||||
if(pServer->m_RconClientID >= 0 && pServer->m_RconClientID < MAX_CLIENTS &&
|
||||
pServer->m_aClients[pServer->m_RconClientID].m_State != CServer::CClient::STATE_EMPTY)
|
||||
{
|
||||
CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
|
||||
Msg.AddInt(0); //authed
|
||||
Msg.AddInt(0); //cmdlist
|
||||
pServer->SendMsgEx(&Msg, MSGFLAG_VITAL, pServer->m_RconClientID, true);
|
||||
|
||||
pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO;
|
||||
pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0;
|
||||
pServer->SendRconLine(pServer->m_RconClientID, "Logout successful.");
|
||||
char aBuf[32];
|
||||
str_format(aBuf, sizeof(aBuf), "ClientID=%d logged out", pServer->m_RconClientID);
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||
{
|
||||
pfnCallback(pResult, pCallbackUserData);
|
||||
|
@ -1711,12 +1672,9 @@ void CServer::RegisterCommands()
|
|||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||
|
||||
Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason");
|
||||
Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBan, this, "Ban player with ip/id for x minutes for any reason");
|
||||
Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnban, this, "Unban ip");
|
||||
Console()->Register("unban_all", "", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnbanAll, this, "Clear all bans");
|
||||
Console()->Register("bans", "", CFGFLAG_SERVER|CFGFLAG_STORE, ConBans, this, "Show banlist");
|
||||
Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players");
|
||||
Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "Shut down");
|
||||
Console()->Register("logout", "", CFGFLAG_SERVER, ConLogout, this, "Logout of rcon");
|
||||
|
||||
Console()->Register("record", "?s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "Record to a file");
|
||||
Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "Stop recording");
|
||||
|
@ -1782,7 +1740,7 @@ int main(int argc, const char **argv) // ignore_convention
|
|||
IEngine *pEngine = CreateEngine("Teeworlds");
|
||||
IEngineMap *pEngineMap = CreateEngineMap();
|
||||
IGameServer *pGameServer = CreateGameServer();
|
||||
IConsole *pConsole = CreateConsole(CFGFLAG_SERVER);
|
||||
IConsole *pConsole = CreateConsole(CFGFLAG_SERVER|CFGFLAG_ECON);
|
||||
IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer();
|
||||
IStorage *pStorage = CreateStorage("Teeworlds", argc, argv); // ignore_convention
|
||||
IConfig *pConfig = CreateConfig();
|
||||
|
@ -1848,8 +1806,10 @@ int main(int argc, const char **argv) // ignore_convention
|
|||
|
||||
void CServer::GetClientAddr(int ClientID, NETADDR *pAddr)
|
||||
{
|
||||
if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME)
|
||||
*pAddr = m_NetServer.ClientAddr(ClientID);
|
||||
if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME) {
|
||||
NETADDR temp = *m_NetServer.ClientAddr(ClientID);
|
||||
pAddr = &temp;
|
||||
}
|
||||
}
|
||||
|
||||
char *CServer::GetAnnouncementLine(char const *pFileName)
|
||||
|
@ -1913,7 +1873,7 @@ void CServer::ConBanmasters(IConsole::IResult *pResult, void *pUser)
|
|||
for(int i = 0; i < NumBanmasters; i++)
|
||||
{
|
||||
NETADDR *pBanmaster = pServer->m_NetServer.BanmasterGet(i);
|
||||
net_addr_str(pBanmaster, aIpString, sizeof(aIpString));
|
||||
net_addr_str(pBanmaster, aIpString, sizeof(aIpString), false);
|
||||
str_format(aBuf, sizeof(aBuf), "%d: %s", i, aIpString);
|
||||
pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server/banmaster", aBuf);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <base/math.h>
|
||||
#include <engine/shared/mapchecker.h>
|
||||
#include <engine/shared/econ.h>
|
||||
#include <engine/shared/netban.h>
|
||||
|
||||
class CSnapIDPool
|
||||
{
|
||||
|
@ -50,6 +51,25 @@ public:
|
|||
void FreeID(int ID);
|
||||
};
|
||||
|
||||
|
||||
class CServerBan : public CNetBan
|
||||
{
|
||||
class CServer *m_pServer;
|
||||
|
||||
template<class T> int BanExt(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason);
|
||||
|
||||
public:
|
||||
class CServer *Server() const { return m_pServer; }
|
||||
|
||||
void Init(class IConsole *pConsole, class IStorage *pStorage, class CServer* pServer);
|
||||
|
||||
int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
|
||||
int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
|
||||
|
||||
static void ConBanExt(class IConsole::IResult *pResult, void *pUser);
|
||||
};
|
||||
|
||||
|
||||
class CServer : public IServer
|
||||
{
|
||||
class IGameServer *m_pGameServer;
|
||||
|
@ -116,10 +136,6 @@ public:
|
|||
const IConsole::CCommandInfo *m_pRconCmdToSend;
|
||||
|
||||
void Reset();
|
||||
|
||||
// DDRace
|
||||
|
||||
NETADDR m_Addr;
|
||||
};
|
||||
|
||||
CClient m_aClients[MAX_CLIENTS];
|
||||
|
@ -129,6 +145,7 @@ public:
|
|||
CSnapIDPool m_IDPool;
|
||||
CNetServer m_NetServer;
|
||||
CEcon m_Econ;
|
||||
CServerBan m_ServerBan;
|
||||
|
||||
IEngineMap *m_pMap;
|
||||
|
||||
|
@ -171,6 +188,7 @@ public:
|
|||
|
||||
int Init();
|
||||
|
||||
void SetRconCID(int ClientID);
|
||||
bool IsAuthed(int ClientID);
|
||||
int GetClientInfo(int ClientID, CClientInfo *pInfo);
|
||||
void GetClientAddr(int ClientID, char *pAddrStr, int Size);
|
||||
|
@ -199,13 +217,9 @@ public:
|
|||
|
||||
void ProcessClientPacket(CNetChunk *pPacket);
|
||||
|
||||
void SendServerInfo(NETADDR *pAddr, int Token);
|
||||
void SendServerInfo(const NETADDR *pAddr, int Token);
|
||||
void UpdateServerInfo();
|
||||
|
||||
int BanAdd(NETADDR Addr, int Seconds, const char *pReason);
|
||||
int BanRemove(NETADDR Addr);
|
||||
int BanRemoveAll();
|
||||
|
||||
void PumpNetwork();
|
||||
|
||||
char *GetMapName();
|
||||
|
@ -215,15 +229,12 @@ public:
|
|||
int Run();
|
||||
|
||||
static void ConKick(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConBan(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConUnban(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConUnbanAll(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConBans(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConStatus(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConStatus(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConShutdown(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConRecord(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConStopRecord(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConMapReload(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConLogout(IConsole::IResult *pResult, void *pUser);
|
||||
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 ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
|
|
|
@ -111,13 +111,8 @@ public:
|
|||
{
|
||||
if(!m_ConfigFile)
|
||||
return;
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
static const char Newline[] = "\r\n";
|
||||
#else
|
||||
static const char Newline[] = "\n";
|
||||
#endif
|
||||
io_write(m_ConfigFile, pLine, str_length(pLine));
|
||||
io_write(m_ConfigFile, Newline, sizeof(Newline)-1);
|
||||
io_write_newline(m_ConfigFile);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@ enum
|
|||
CFGFLAG_SERVER=4,
|
||||
CFGFLAG_STORE=8,
|
||||
CFGFLAG_MASTER=16,
|
||||
|
||||
CFGFLAG_ECON=32,
|
||||
// DDRace
|
||||
|
||||
CMDFLAG_TEST=32,
|
||||
CFGFLAG_CHAT = 64
|
||||
CMDFLAG_TEST=64,
|
||||
CFGFLAG_CHAT = 128
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -89,12 +89,12 @@ MACRO_CONFIG_INT(SvRconBantime, sv_rcon_bantime, 5, 0, 1440, CFGFLAG_SERVER, "Th
|
|||
MACRO_CONFIG_INT(SvAutoDemoRecord, sv_auto_demo_record, 0, 0, 1, CFGFLAG_SERVER, "Automatically record demos")
|
||||
MACRO_CONFIG_INT(SvAutoDemoMax, sv_auto_demo_max, 10, 0, 1000, CFGFLAG_SERVER, "Maximum number of automatically recorded demos (0 = no limit)")
|
||||
|
||||
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(EcPort, ec_port, 0, 0, 0, CFGFLAG_SERVER, "Port to use for the external console")
|
||||
MACRO_CONFIG_STR(EcPassword, ec_password, 32, "", CFGFLAG_SERVER, "External console password")
|
||||
MACRO_CONFIG_INT(EcBantime, ec_bantime, 0, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if econ authentication fails. 0 just closes the connection")
|
||||
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_STR(EcBindaddr, ec_bindaddr, 128, "localhost", CFGFLAG_ECON, "Address to bind the external console to. Anything but 'localhost' is dangerous")
|
||||
MACRO_CONFIG_INT(EcPort, ec_port, 0, 0, 0, CFGFLAG_ECON, "Port to use for the external console")
|
||||
MACRO_CONFIG_STR(EcPassword, ec_password, 32, "", CFGFLAG_ECON, "External console password")
|
||||
MACRO_CONFIG_INT(EcBantime, ec_bantime, 0, 0, 1440, CFGFLAG_ECON, "The time a client gets banned if econ authentication fails. 0 just closes the connection")
|
||||
MACRO_CONFIG_INT(EcAuthTimeout, ec_auth_timeout, 30, 1, 120, CFGFLAG_ECON, "Time in seconds before the the econ authentification times out")
|
||||
MACRO_CONFIG_INT(EcOutputLevel, ec_output_level, 1, 0, 2, CFGFLAG_ECON, "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(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "console.h"
|
||||
#include "linereader.h"
|
||||
|
||||
// todo: rework this
|
||||
|
||||
const char *CConsole::CResult::GetString(unsigned Index)
|
||||
{
|
||||
if (Index < 0 || Index >= m_NumArgs)
|
||||
|
@ -168,7 +170,7 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat)
|
|||
char* pVictim = 0;
|
||||
|
||||
if (Command != 'v')
|
||||
pResult->AddArgument(pStr);
|
||||
pResult->AddArgument(pStr);
|
||||
else
|
||||
pVictim = pStr;
|
||||
|
||||
|
@ -361,14 +363,14 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID)
|
|||
for (int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
Result.SetVictim(i);
|
||||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
}
|
||||
}
|
||||
else
|
||||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
}
|
||||
else
|
||||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
|
||||
if (pCommand->m_Flags&CMDFLAG_TEST)
|
||||
m_Cheated = true;
|
||||
|
@ -425,6 +427,14 @@ void CConsole::ExecuteLine(const char *pStr, int ClientID)
|
|||
CConsole::ExecuteLineStroked(0, pStr, ClientID); // then release it
|
||||
}
|
||||
|
||||
void CConsole::ExecuteLineFlag(const char *pStr, int FlagMask)
|
||||
{
|
||||
int Temp = m_FlagMask;
|
||||
m_FlagMask = FlagMask;
|
||||
ExecuteLine(pStr);
|
||||
m_FlagMask = Temp;
|
||||
}
|
||||
|
||||
|
||||
void CConsole::ExecuteFile(const char *pFilename, int ClientID)
|
||||
{
|
||||
|
@ -696,7 +706,7 @@ void CConsole::ParseArguments(int NumArgs, const char **ppArguments)
|
|||
|
||||
void CConsole::AddCommandSorted(CCommand *pCommand)
|
||||
{
|
||||
if(!m_pFirstCommand || str_comp(pCommand->m_pName, m_pFirstCommand->m_pName) < 0)
|
||||
if(!m_pFirstCommand || str_comp(pCommand->m_pName, m_pFirstCommand->m_pName) <= 0)
|
||||
{
|
||||
if(m_pFirstCommand && m_pFirstCommand->m_pNext)
|
||||
pCommand->m_pNext = m_pFirstCommand;
|
||||
|
@ -708,7 +718,7 @@ void CConsole::AddCommandSorted(CCommand *pCommand)
|
|||
{
|
||||
for(CCommand *p = m_pFirstCommand; p; p = p->m_pNext)
|
||||
{
|
||||
if(!p->m_pNext || str_comp(pCommand->m_pName, p->m_pNext->m_pName) < 0)
|
||||
if(!p->m_pNext || str_comp(pCommand->m_pName, p->m_pNext->m_pName) <= 0)
|
||||
{
|
||||
pCommand->m_pNext = p->m_pNext;
|
||||
p->m_pNext = pCommand;
|
||||
|
@ -721,7 +731,13 @@ void CConsole::AddCommandSorted(CCommand *pCommand)
|
|||
void CConsole::Register(const char *pName, const char *pParams,
|
||||
int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp)
|
||||
{
|
||||
CCommand *pCommand = new(mem_alloc(sizeof(CCommand), sizeof(void*))) CCommand;
|
||||
CCommand *pCommand = FindCommand(pName, Flags);
|
||||
bool DoAdd = false;
|
||||
if(pCommand == 0)
|
||||
{
|
||||
pCommand = new(mem_alloc(sizeof(CCommand), sizeof(void*))) CCommand;
|
||||
DoAdd = true;
|
||||
}
|
||||
pCommand->m_pfnCallback = pfnFunc;
|
||||
pCommand->m_pUserData = pUser;
|
||||
|
||||
|
@ -732,7 +748,8 @@ void CConsole::Register(const char *pName, const char *pParams,
|
|||
pCommand->m_Flags = Flags;
|
||||
pCommand->m_Temp = false;
|
||||
|
||||
AddCommandSorted(pCommand);
|
||||
if(DoAdd)
|
||||
AddCommandSorted(pCommand);
|
||||
|
||||
if(pCommand->m_Flags&CFGFLAG_CHAT)
|
||||
pCommand->SetAccessLevel(ACCESS_LEVEL_USER);
|
||||
|
|
|
@ -172,7 +172,7 @@ class CConsole : public IConsole
|
|||
public:
|
||||
CConsole(int FlagMask);
|
||||
|
||||
virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int Flagmask) const;
|
||||
virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int FlagMask) const;
|
||||
virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp);
|
||||
virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser);
|
||||
|
||||
|
@ -186,6 +186,7 @@ public:
|
|||
|
||||
virtual bool LineIsValid(const char *pStr);
|
||||
virtual void ExecuteLine(const char *pStr, int ClientID = -1);
|
||||
virtual void ExecuteLineFlag(const char *pStr, int FlagMask);
|
||||
virtual void ExecuteFile(const char *pFilename, int ClientID = -1);
|
||||
|
||||
virtual int RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData);
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
#include <engine/shared/config.h>
|
||||
|
||||
#include "econ.h"
|
||||
#include "netban.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));
|
||||
net_addr_str(pThis->m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
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);
|
||||
|
@ -26,9 +27,8 @@ 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));
|
||||
net_addr_str(pThis->m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
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);
|
||||
|
@ -52,7 +52,15 @@ void CEcon::ConchainEconOutputLevelUpdate(IConsole::IResult *pResult, void *pUse
|
|||
}
|
||||
}
|
||||
|
||||
void CEcon::Init(IConsole *pConsole)
|
||||
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");
|
||||
}
|
||||
|
||||
void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan)
|
||||
{
|
||||
m_pConsole = pConsole;
|
||||
|
||||
|
@ -60,6 +68,7 @@ void CEcon::Init(IConsole *pConsole)
|
|||
m_aClients[i].m_State = CClient::STATE_EMPTY;
|
||||
|
||||
m_Ready = false;
|
||||
m_UserClientID = -1;
|
||||
|
||||
if(g_Config.m_EcPort == 0 || g_Config.m_EcPassword[0] == 0)
|
||||
return;
|
||||
|
@ -74,7 +83,7 @@ void CEcon::Init(IConsole *pConsole)
|
|||
BindAddr.port = g_Config.m_EcPort;
|
||||
}
|
||||
|
||||
if(m_NetConsole.Open(BindAddr, 0))
|
||||
if(m_NetConsole.Open(BindAddr, pNetBan, 0))
|
||||
{
|
||||
m_NetConsole.SetCallbacks(NewClientCallback, DelClientCallback, this);
|
||||
m_Ready = true;
|
||||
|
@ -84,6 +93,8 @@ void CEcon::Init(IConsole *pConsole)
|
|||
|
||||
Console()->Chain("ec_output_level", ConchainEconOutputLevelUpdate, this);
|
||||
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_EcOutputLevel, SendLineCB, this);
|
||||
|
||||
Console()->Register("logout", "", CFGFLAG_ECON, ConLogout, this, "Logout of econ");
|
||||
}
|
||||
else
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD,"econ", "couldn't open socket. port might already be in use");
|
||||
|
@ -115,18 +126,15 @@ void CEcon::Update()
|
|||
else
|
||||
{
|
||||
m_aClients[ClientID].m_AuthTries++;
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, MAX_AUTH_TRIES);
|
||||
m_NetConsole.Send(ClientID, aBuf);
|
||||
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);
|
||||
if(m_aClients[ClientID].m_AuthTries >= MAX_AUTH_TRIES)
|
||||
{
|
||||
if(!g_Config.m_EcBantime)
|
||||
m_NetConsole.Drop(ClientID, "Too many authentication tries");
|
||||
else
|
||||
{
|
||||
NETADDR Addr = m_NetConsole.ClientAddr(ClientID);
|
||||
m_NetConsole.AddBan(Addr, g_Config.m_EcBantime*60);
|
||||
}
|
||||
m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), g_Config.m_EcBantime*60, "Too many authentication tries");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +143,9 @@ void CEcon::Update()
|
|||
char aFormatted[256];
|
||||
str_format(aFormatted, sizeof(aBuf), "cid=%d cmd='%s'", ClientID, aBuf);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aFormatted);
|
||||
m_UserClientID = ClientID;
|
||||
Console()->ExecuteLine(aBuf);
|
||||
m_UserClientID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "network.h"
|
||||
|
||||
|
||||
class CEcon
|
||||
{
|
||||
enum
|
||||
|
@ -31,9 +32,11 @@ class CEcon
|
|||
|
||||
bool m_Ready;
|
||||
int m_PrintCBIndex;
|
||||
int m_UserClientID;
|
||||
|
||||
static void SendLineCB(const char *pLine, void *pUserData);
|
||||
static void ConchainEconOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
static void ConLogout(IConsole::IResult *pResult, void *pUserData);
|
||||
|
||||
static int NewClientCallback(int ClientID, void *pUser);
|
||||
static int DelClientCallback(int ClientID, const char *pReason, void *pUser);
|
||||
|
@ -41,7 +44,7 @@ class CEcon
|
|||
public:
|
||||
IConsole *Console() { return m_pConsole; }
|
||||
|
||||
void Init(IConsole *pConsole);
|
||||
void Init(IConsole *pConsole, class CNetBan *pNetBan);
|
||||
void Update();
|
||||
void Send(int ClientID, const char *pLine);
|
||||
void Shutdown();
|
||||
|
|
|
@ -192,13 +192,13 @@ public:
|
|||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
if(m_aMasterServers[i].m_Addr.type != NETTYPE_INVALID)
|
||||
net_addr_str(&m_aMasterServers[i].m_Addr, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&m_aMasterServers[i].m_Addr, aAddrStr, sizeof(aAddrStr), true);
|
||||
else
|
||||
aAddrStr[0] = 0;
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "%s %s\n", m_aMasterServers[i].m_aHostname, aAddrStr);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%s %s", m_aMasterServers[i].m_aHostname, aAddrStr);
|
||||
io_write(File, aBuf, str_length(aBuf));
|
||||
io_write_newline(File);
|
||||
}
|
||||
|
||||
io_close(File);
|
||||
|
|
615
src/engine/shared/netban.cpp
Normal file
615
src/engine/shared/netban.cpp
Normal file
|
@ -0,0 +1,615 @@
|
|||
#include <base/math.h>
|
||||
|
||||
#include <engine/console.h>
|
||||
#include <engine/storage.h>
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
#include "netban.h"
|
||||
|
||||
|
||||
bool CNetBan::StrAllnum(const char *pStr)
|
||||
{
|
||||
while(*pStr)
|
||||
{
|
||||
if(!(*pStr >= '0' && *pStr <= '9'))
|
||||
return false;
|
||||
pStr++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CNetBan::CNetHash::CNetHash(const NETADDR *pAddr)
|
||||
{
|
||||
if(pAddr->type==NETTYPE_IPV4)
|
||||
m_Hash = (pAddr->ip[0]+pAddr->ip[1]+pAddr->ip[2]+pAddr->ip[3])&0xFF;
|
||||
else
|
||||
m_Hash = (pAddr->ip[0]+pAddr->ip[1]+pAddr->ip[2]+pAddr->ip[3]+pAddr->ip[4]+pAddr->ip[5]+pAddr->ip[6]+pAddr->ip[7]+
|
||||
pAddr->ip[8]+pAddr->ip[9]+pAddr->ip[10]+pAddr->ip[11]+pAddr->ip[12]+pAddr->ip[13]+pAddr->ip[14]+pAddr->ip[15])&0xFF;
|
||||
m_HashIndex = 0;
|
||||
}
|
||||
|
||||
CNetBan::CNetHash::CNetHash(const CNetRange *pRange)
|
||||
{
|
||||
m_Hash = 0;
|
||||
m_HashIndex = 0;
|
||||
for(int i = 0; pRange->m_LB.ip[i] == pRange->m_UB.ip[i]; ++i)
|
||||
{
|
||||
m_Hash += pRange->m_LB.ip[i];
|
||||
++m_HashIndex;
|
||||
}
|
||||
m_Hash &= 0xFF;
|
||||
}
|
||||
|
||||
int CNetBan::CNetHash::MakeHashArray(const NETADDR *pAddr, CNetHash aHash[17])
|
||||
{
|
||||
int Length = pAddr->type==NETTYPE_IPV4 ? 4 : 16;
|
||||
aHash[0].m_Hash = 0;
|
||||
aHash[0].m_HashIndex = 0;
|
||||
for(int i = 1, Sum = 0; i <= Length; ++i)
|
||||
{
|
||||
Sum += pAddr->ip[i-1];
|
||||
aHash[i].m_Hash = Sum&0xFF;
|
||||
aHash[i].m_HashIndex = i%Length;
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
|
||||
|
||||
template<class T, int HashCount>
|
||||
typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Add(const T *pData, const CBanInfo *pInfo, const CNetHash *pNetHash)
|
||||
{
|
||||
if(!m_pFirstFree)
|
||||
return 0;
|
||||
|
||||
// create new ban
|
||||
CBan<T> *pBan = m_pFirstFree;
|
||||
pBan->m_Data = *pData;
|
||||
pBan->m_Info = *pInfo;
|
||||
pBan->m_NetHash = *pNetHash;
|
||||
if(pBan->m_pNext)
|
||||
pBan->m_pNext->m_pPrev = pBan->m_pPrev;
|
||||
if(pBan->m_pPrev)
|
||||
pBan->m_pPrev->m_pNext = pBan->m_pNext;
|
||||
else
|
||||
m_pFirstFree = pBan->m_pNext;
|
||||
|
||||
// add it to the hash list
|
||||
if(m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash])
|
||||
m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]->m_pHashPrev = pBan;
|
||||
pBan->m_pHashPrev = 0;
|
||||
pBan->m_pHashNext = m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash];
|
||||
m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash] = pBan;
|
||||
|
||||
// insert it into the used list
|
||||
if(m_pFirstUsed)
|
||||
{
|
||||
for(CBan<T> *p = m_pFirstUsed; ; p = p->m_pNext)
|
||||
{
|
||||
if(p->m_Info.m_Expires == CBanInfo::EXPIRES_NEVER || (pInfo->m_Expires != CBanInfo::EXPIRES_NEVER && pInfo->m_Expires <= p->m_Info.m_Expires))
|
||||
{
|
||||
// insert before
|
||||
pBan->m_pNext = p;
|
||||
pBan->m_pPrev = p->m_pPrev;
|
||||
if(p->m_pPrev)
|
||||
p->m_pPrev->m_pNext = pBan;
|
||||
else
|
||||
m_pFirstUsed = pBan;
|
||||
p->m_pPrev = pBan;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!p->m_pNext)
|
||||
{
|
||||
// last entry
|
||||
p->m_pNext = pBan;
|
||||
pBan->m_pPrev = p;
|
||||
pBan->m_pNext = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstUsed = pBan;
|
||||
pBan->m_pNext = pBan->m_pPrev = 0;
|
||||
}
|
||||
|
||||
// update ban count
|
||||
++m_CountUsed;
|
||||
|
||||
return pBan;
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
int CNetBan::CBanPool<T, HashCount>::Remove(CBan<T> *pBan)
|
||||
{
|
||||
if(pBan == 0)
|
||||
return -1;
|
||||
|
||||
// remove from hash list
|
||||
if(pBan->m_pHashNext)
|
||||
pBan->m_pHashNext->m_pHashPrev = pBan->m_pHashPrev;
|
||||
if(pBan->m_pHashPrev)
|
||||
pBan->m_pHashPrev->m_pHashNext = pBan->m_pHashNext;
|
||||
else
|
||||
m_paaHashList[pBan->m_NetHash.m_HashIndex][pBan->m_NetHash.m_Hash] = pBan->m_pHashNext;
|
||||
pBan->m_pHashNext = pBan->m_pHashPrev = 0;
|
||||
|
||||
// remove from used list
|
||||
if(pBan->m_pNext)
|
||||
pBan->m_pNext->m_pPrev = pBan->m_pPrev;
|
||||
if(pBan->m_pPrev)
|
||||
pBan->m_pPrev->m_pNext = pBan->m_pNext;
|
||||
else
|
||||
m_pFirstUsed = pBan->m_pNext;
|
||||
|
||||
// add to recycle list
|
||||
if(m_pFirstFree)
|
||||
m_pFirstFree->m_pPrev = pBan;
|
||||
pBan->m_pPrev = 0;
|
||||
pBan->m_pNext = m_pFirstFree;
|
||||
m_pFirstFree = pBan;
|
||||
|
||||
// update ban count
|
||||
--m_CountUsed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
void CNetBan::CBanPool<T, HashCount>::Update(CBan<CDataType> *pBan, const CBanInfo *pInfo)
|
||||
{
|
||||
pBan->m_Info = *pInfo;
|
||||
|
||||
// remove from used list
|
||||
if(pBan->m_pNext)
|
||||
pBan->m_pNext->m_pPrev = pBan->m_pPrev;
|
||||
if(pBan->m_pPrev)
|
||||
pBan->m_pPrev->m_pNext = pBan->m_pNext;
|
||||
else
|
||||
m_pFirstUsed = pBan->m_pNext;
|
||||
|
||||
// insert it into the used list
|
||||
if(m_pFirstUsed)
|
||||
{
|
||||
for(CBan<T> *p = m_pFirstUsed; ; p = p->m_pNext)
|
||||
{
|
||||
if(p->m_Info.m_Expires == CBanInfo::EXPIRES_NEVER || (pInfo->m_Expires != CBanInfo::EXPIRES_NEVER && pInfo->m_Expires <= p->m_Info.m_Expires))
|
||||
{
|
||||
// insert before
|
||||
pBan->m_pNext = p;
|
||||
pBan->m_pPrev = p->m_pPrev;
|
||||
if(p->m_pPrev)
|
||||
p->m_pPrev->m_pNext = pBan;
|
||||
else
|
||||
m_pFirstUsed = pBan;
|
||||
p->m_pPrev = pBan;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!p->m_pNext)
|
||||
{
|
||||
// last entry
|
||||
p->m_pNext = pBan;
|
||||
pBan->m_pPrev = p;
|
||||
pBan->m_pNext = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstUsed = pBan;
|
||||
pBan->m_pNext = pBan->m_pPrev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
void CNetBan::CBanPool<T, HashCount>::Reset()
|
||||
{
|
||||
mem_zero(m_paaHashList, sizeof(m_paaHashList));
|
||||
mem_zero(m_aBans, sizeof(m_aBans));
|
||||
m_pFirstUsed = 0;
|
||||
m_CountUsed = 0;
|
||||
|
||||
for(int i = 1; i < MAX_BANS-1; ++i)
|
||||
{
|
||||
m_aBans[i].m_pNext = &m_aBans[i+1];
|
||||
m_aBans[i].m_pPrev = &m_aBans[i-1];
|
||||
}
|
||||
|
||||
m_aBans[0].m_pNext = &m_aBans[1];
|
||||
m_aBans[MAX_BANS-1].m_pPrev = &m_aBans[MAX_BANS-2];
|
||||
m_pFirstFree = &m_aBans[0];
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Find(const T *pData, const CNetHash *pNetHash) const
|
||||
{
|
||||
for(CBan<T> *pBan = m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; pBan; pBan = pBan->m_pHashNext)
|
||||
{
|
||||
if(NetComp(&pBan->m_Data, pData) == 0)
|
||||
return pBan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Get(int Index) const
|
||||
{
|
||||
if(Index < 0 || Index >= Num())
|
||||
return 0;
|
||||
|
||||
for(CNetBan::CBan<T> *pBan = m_pFirstUsed; pBan; pBan = pBan->m_pNext, --Index)
|
||||
{
|
||||
if(Index == 0)
|
||||
return pBan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void CNetBan::MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const
|
||||
{
|
||||
if(pBan == 0)
|
||||
{
|
||||
if(BuffSize > 0)
|
||||
pBuf[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// build type based part
|
||||
char aBuf[256];
|
||||
if(Type == MSGTYPE_PLAYER)
|
||||
str_copy(aBuf, "You have been banned", sizeof(aBuf));
|
||||
else
|
||||
{
|
||||
char aTemp[256];
|
||||
switch(Type)
|
||||
{
|
||||
case MSGTYPE_LIST:
|
||||
str_format(aBuf, sizeof(aBuf), "%s banned", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break;
|
||||
case MSGTYPE_BANADD:
|
||||
str_format(aBuf, sizeof(aBuf), "banned %s", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break;
|
||||
case MSGTYPE_BANREM:
|
||||
str_format(aBuf, sizeof(aBuf), "unbanned %s", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break;
|
||||
default:
|
||||
aBuf[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// add info part
|
||||
if(pBan->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER)
|
||||
{
|
||||
int Mins = ((pBan->m_Info.m_Expires-time_timestamp()) + 59) / 60;
|
||||
if(Mins <= 1)
|
||||
str_format(pBuf, BuffSize, "%s for 1 minute (%s)", aBuf, pBan->m_Info.m_aReason);
|
||||
else
|
||||
str_format(pBuf, BuffSize, "%s for %d minutes (%s)", aBuf, Mins, pBan->m_Info.m_aReason);
|
||||
}
|
||||
else
|
||||
str_format(pBuf, BuffSize, "%s for life (%s)", aBuf, pBan->m_Info.m_aReason);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int CNetBan::Ban(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason)
|
||||
{
|
||||
// do not ban localhost
|
||||
if(NetMatch(pData, &m_LocalhostIPV4) || NetMatch(pData, &m_LocalhostIPV6))
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (localhost)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Stamp = Seconds > 0 ? time_timestamp()+Seconds : CBanInfo::EXPIRES_NEVER;
|
||||
|
||||
// set up info
|
||||
CBanInfo Info = {0};
|
||||
Info.m_Expires = Stamp;
|
||||
str_copy(Info.m_aReason, pReason, sizeof(Info.m_aReason));
|
||||
|
||||
// check if it already exists
|
||||
CNetHash NetHash(pData);
|
||||
CBan<typename T::CDataType> *pBan = pBanPool->Find(pData, &NetHash);
|
||||
if(pBan)
|
||||
{
|
||||
// adjust the ban
|
||||
pBanPool->Update(pBan, &Info);
|
||||
char aBuf[128];
|
||||
MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// add ban and print result
|
||||
pBan = pBanPool->Add(pData, &Info, &NetHash);
|
||||
if(pBan)
|
||||
{
|
||||
char aBuf[128];
|
||||
MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_BANADD);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (full banlist)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int CNetBan::Unban(T *pBanPool, const typename T::CDataType *pData)
|
||||
{
|
||||
CNetHash NetHash(pData);
|
||||
CBan<typename T::CDataType> *pBan = pBanPool->Find(pData, &NetHash);
|
||||
if(pBan)
|
||||
{
|
||||
char aBuf[256];
|
||||
MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_BANREM);
|
||||
pBanPool->Remove(pBan);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban failed (invalid entry)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CNetBan::Init(IConsole *pConsole, IStorage *pStorage)
|
||||
{
|
||||
m_pConsole = pConsole;
|
||||
m_pStorage = pStorage;
|
||||
m_BanAddrPool.Reset();
|
||||
m_BanRangePool.Reset();
|
||||
|
||||
net_host_lookup("localhost", &m_LocalhostIPV4, NETTYPE_IPV4);
|
||||
net_host_lookup("localhost", &m_LocalhostIPV6, NETTYPE_IPV6);
|
||||
|
||||
Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBan, this, "Ban ip for x minutes for any reason");
|
||||
Console()->Register("ban_range", "ss?ir", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBanRange, this, "Ban ip range for x minutes for any reason");
|
||||
Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnban, this, "Unban ip/banlist entry");
|
||||
Console()->Register("unban_range", "ss", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnbanRange, this, "Unban ip range");
|
||||
Console()->Register("unban_all", "", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnbanAll, this, "Unban all entries");
|
||||
Console()->Register("bans", "", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBans, this, "Show banlist");
|
||||
Console()->Register("bans_save", "s", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBansSave, this, "Save banlist in a file");
|
||||
}
|
||||
|
||||
void CNetBan::Update()
|
||||
{
|
||||
int Now = time_timestamp();
|
||||
|
||||
// remove expired bans
|
||||
char aBuf[256], aNetStr[256];
|
||||
while(m_BanAddrPool.First() && m_BanAddrPool.First()->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER && m_BanAddrPool.First()->m_Info.m_Expires < Now)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "ban %s expired", NetToString(&m_BanAddrPool.First()->m_Data, aNetStr, sizeof(aNetStr)));
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
m_BanAddrPool.Remove(m_BanAddrPool.First());
|
||||
}
|
||||
while(m_BanRangePool.First() && m_BanRangePool.First()->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER && m_BanRangePool.First()->m_Info.m_Expires < Now)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "ban %s expired", NetToString(&m_BanRangePool.First()->m_Data, aNetStr, sizeof(aNetStr)));
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
m_BanRangePool.Remove(m_BanRangePool.First());
|
||||
}
|
||||
}
|
||||
|
||||
int CNetBan::BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason)
|
||||
{
|
||||
return Ban(&m_BanAddrPool, pAddr, Seconds, pReason);
|
||||
}
|
||||
|
||||
int CNetBan::BanRange(const CNetRange *pRange, int Seconds, const char *pReason)
|
||||
{
|
||||
if(pRange->IsValid())
|
||||
return Ban(&m_BanRangePool, pRange, Seconds, pReason);
|
||||
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetBan::UnbanByAddr(const NETADDR *pAddr)
|
||||
{
|
||||
return Unban(&m_BanAddrPool, pAddr);
|
||||
}
|
||||
|
||||
int CNetBan::UnbanByRange(const CNetRange *pRange)
|
||||
{
|
||||
if(pRange->IsValid())
|
||||
return Unban(&m_BanRangePool, pRange);
|
||||
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetBan::UnbanByIndex(int Index)
|
||||
{
|
||||
int Result;
|
||||
char aBuf[256];
|
||||
CBanAddr *pBan = m_BanAddrPool.Get(Index);
|
||||
if(pBan)
|
||||
{
|
||||
NetToString(&pBan->m_Data, aBuf, sizeof(aBuf));
|
||||
Result = m_BanAddrPool.Remove(pBan);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBanRange *pBan = m_BanRangePool.Get(Index-m_BanAddrPool.Num());
|
||||
if(pBan)
|
||||
{
|
||||
NetToString(&pBan->m_Data, aBuf, sizeof(aBuf));
|
||||
Result = m_BanRangePool.Remove(pBan);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban failed (invalid index)");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
char aMsg[256];
|
||||
str_format(aMsg, sizeof(aMsg), "unbanned index %i (%s)", Index, aBuf);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg);
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool CNetBan::IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize) const
|
||||
{
|
||||
CNetHash aHash[17];
|
||||
int Length = CNetHash::MakeHashArray(pAddr, aHash);
|
||||
|
||||
// check ban adresses
|
||||
CBanAddr *pBan = m_BanAddrPool.Find(pAddr, &aHash[Length]);
|
||||
if(pBan)
|
||||
{
|
||||
MakeBanInfo(pBan, pBuf, BufferSize, MSGTYPE_PLAYER);
|
||||
return true;
|
||||
}
|
||||
|
||||
// check ban ranges
|
||||
for(int i = Length-1; i >= 0; --i)
|
||||
{
|
||||
for(CBanRange *pBan = m_BanRangePool.First(&aHash[i]); pBan; pBan = pBan->m_pHashNext)
|
||||
{
|
||||
if(NetMatch(&pBan->m_Data, pAddr, i, Length))
|
||||
{
|
||||
MakeBanInfo(pBan, pBuf, BufferSize, MSGTYPE_PLAYER);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CNetBan::ConBan(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
const char *pStr = pResult->GetString(0);
|
||||
int Minutes = pResult->NumArguments()>1 ? clamp(pResult->GetInteger(1), 0, 44640) : 30;
|
||||
const char *pReason = pResult->NumArguments()>2 ? pResult->GetString(2) : "No reason given";
|
||||
|
||||
NETADDR Addr;
|
||||
if(net_addr_from_str(&Addr, pStr) == 0)
|
||||
pThis->BanAddr(&Addr, Minutes*60, pReason);
|
||||
else
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid network address)");
|
||||
}
|
||||
|
||||
void CNetBan::ConBanRange(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
const char *pStr1 = pResult->GetString(0);
|
||||
const char *pStr2 = pResult->GetString(1);
|
||||
int Minutes = pResult->NumArguments()>2 ? clamp(pResult->GetInteger(2), 0, 44640) : 30;
|
||||
const char *pReason = pResult->NumArguments()>3 ? pResult->GetString(3) : "No reason given";
|
||||
|
||||
CNetRange Range;
|
||||
if(net_addr_from_str(&Range.m_LB, pStr1) == 0 && net_addr_from_str(&Range.m_UB, pStr2) == 0)
|
||||
pThis->BanRange(&Range, Minutes*60, pReason);
|
||||
else
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid range)");
|
||||
}
|
||||
|
||||
void CNetBan::ConUnban(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
const char *pStr = pResult->GetString(0);
|
||||
if(StrAllnum(pStr))
|
||||
pThis->UnbanByIndex(str_toint(pStr));
|
||||
else
|
||||
{
|
||||
NETADDR Addr;
|
||||
if(net_addr_from_str(&Addr, pStr) == 0)
|
||||
pThis->UnbanByAddr(&Addr);
|
||||
else
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban error (invalid network address)");
|
||||
}
|
||||
}
|
||||
|
||||
void CNetBan::ConUnbanRange(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
const char *pStr1 = pResult->GetString(0);
|
||||
const char *pStr2 = pResult->GetString(1);
|
||||
|
||||
CNetRange Range;
|
||||
if(net_addr_from_str(&Range.m_LB, pStr1) == 0 && net_addr_from_str(&Range.m_UB, pStr2) == 0)
|
||||
pThis->UnbanByRange(&Range);
|
||||
else
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban error (invalid range)");
|
||||
}
|
||||
|
||||
void CNetBan::ConUnbanAll(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
pThis->UnbanAll();
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unbanned all entries");
|
||||
}
|
||||
|
||||
void CNetBan::ConBans(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
int Count = 0;
|
||||
char aBuf[256], aMsg[256];
|
||||
for(CBanAddr *pBan = pThis->m_BanAddrPool.First(); pBan; pBan = pBan->m_pNext)
|
||||
{
|
||||
pThis->MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST);
|
||||
str_format(aMsg, sizeof(aMsg), "#%i %s", Count++, aBuf);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg);
|
||||
}
|
||||
for(CBanRange *pBan = pThis->m_BanRangePool.First(); pBan; pBan = pBan->m_pNext)
|
||||
{
|
||||
pThis->MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST);
|
||||
str_format(aMsg, sizeof(aMsg), "#%i %s", Count++, aBuf);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg);
|
||||
}
|
||||
str_format(aMsg, sizeof(aMsg), "%d %s", Count, Count==1?"ban":"bans");
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg);
|
||||
}
|
||||
|
||||
void CNetBan::ConBansSave(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CNetBan *pThis = static_cast<CNetBan *>(pUser);
|
||||
|
||||
char aBuf[256];
|
||||
IOHANDLE File = pThis->Storage()->OpenFile(pResult->GetString(0), IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
if(!File)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "failed to save banlist to '%s'", pResult->GetString(0));
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
int Now = time_timestamp();
|
||||
char aAddrStr1[NETADDR_MAXSTRSIZE], aAddrStr2[NETADDR_MAXSTRSIZE];
|
||||
for(CBanAddr *pBan = pThis->m_BanAddrPool.First(); pBan; pBan = pBan->m_pNext)
|
||||
{
|
||||
int Min = pBan->m_Info.m_Expires>-1 ? (pBan->m_Info.m_Expires-Now+59)/60 : -1;
|
||||
net_addr_str(&pBan->m_Data, aAddrStr1, sizeof(aAddrStr1), false);
|
||||
str_format(aBuf, sizeof(aBuf), "ban_ip %s %i %s", aAddrStr1, Min, pBan->m_Info.m_aReason);
|
||||
io_write(File, aBuf, str_length(aBuf));
|
||||
io_write_newline(File);
|
||||
}
|
||||
for(CBanRange *pBan = pThis->m_BanRangePool.First(); pBan; pBan = pBan->m_pNext)
|
||||
{
|
||||
int Min = pBan->m_Info.m_Expires>-1 ? (pBan->m_Info.m_Expires-Now+59)/60 : -1;
|
||||
net_addr_str(&pBan->m_Data.m_LB, aAddrStr1, sizeof(aAddrStr1), false);
|
||||
net_addr_str(&pBan->m_Data.m_UB, aAddrStr2, sizeof(aAddrStr2), false);
|
||||
str_format(aBuf, sizeof(aBuf), "ban_range %s %i %s", aAddrStr1, aAddrStr2, Min, pBan->m_Info.m_aReason);
|
||||
io_write(File, aBuf, str_length(aBuf));
|
||||
io_write_newline(File);
|
||||
}
|
||||
|
||||
io_close(File);
|
||||
str_format(aBuf, sizeof(aBuf), "saved banlist to '%s'", pResult->GetString(0));
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf);
|
||||
}
|
184
src/engine/shared/netban.h
Normal file
184
src/engine/shared/netban.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
#ifndef ENGINE_SHARED_NETBAN_H
|
||||
#define ENGINE_SHARED_NETBAN_H
|
||||
|
||||
#include <base/system.h>
|
||||
|
||||
|
||||
inline int NetComp(const NETADDR *pAddr1, const NETADDR *pAddr2)
|
||||
{
|
||||
return mem_comp(pAddr1, pAddr2, pAddr1->type==NETTYPE_IPV4 ? 8 : 20);
|
||||
}
|
||||
|
||||
class CNetRange
|
||||
{
|
||||
public:
|
||||
NETADDR m_LB;
|
||||
NETADDR m_UB;
|
||||
|
||||
bool IsValid() const { return m_LB.type == m_UB.type && NetComp(&m_LB, &m_UB) < 0; }
|
||||
};
|
||||
|
||||
inline int NetComp(const CNetRange *pRange1, const CNetRange *pRange2)
|
||||
{
|
||||
return NetComp(&pRange1->m_LB, &pRange2->m_LB) || NetComp(&pRange1->m_UB, &pRange2->m_UB);
|
||||
}
|
||||
|
||||
|
||||
class CNetBan
|
||||
{
|
||||
protected:
|
||||
bool NetMatch(const NETADDR *pAddr1, const NETADDR *pAddr2) const
|
||||
{
|
||||
return NetComp(pAddr1, pAddr2) == 0;
|
||||
}
|
||||
|
||||
bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr, int Start, int Length) const
|
||||
{
|
||||
return pRange->m_LB.type == pAddr->type &&
|
||||
mem_comp(&pRange->m_LB.ip[Start], &pAddr->ip[Start], Length-Start) <= 0 && mem_comp(&pRange->m_UB.ip[Start], &pAddr->ip[Start], Length-Start) >= 0;
|
||||
}
|
||||
|
||||
bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr) const
|
||||
{
|
||||
return NetMatch(pRange, pAddr, 0, pRange->m_LB.type==NETTYPE_IPV4 ? 4 : 16);
|
||||
}
|
||||
|
||||
const char *NetToString(const NETADDR *pData, char *pBuffer, unsigned BufferSize) const
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pData, aAddrStr, sizeof(aAddrStr), false);
|
||||
str_format(pBuffer, BufferSize, "'%s'", aAddrStr);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
const char *NetToString(const CNetRange *pData, char *pBuffer, unsigned BufferSize) const
|
||||
{
|
||||
char aAddrStr1[NETADDR_MAXSTRSIZE], aAddrStr2[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&pData->m_LB, aAddrStr1, sizeof(aAddrStr1), false);
|
||||
net_addr_str(&pData->m_UB, aAddrStr2, sizeof(aAddrStr2), false);
|
||||
str_format(pBuffer, BufferSize, "'%s' - '%s'", aAddrStr1, aAddrStr2);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
// todo: move?
|
||||
static bool StrAllnum(const char *pStr);
|
||||
|
||||
class CNetHash
|
||||
{
|
||||
public:
|
||||
int m_Hash;
|
||||
int m_HashIndex; // matching parts for ranges, 0 for addr
|
||||
|
||||
CNetHash() {}
|
||||
CNetHash(const NETADDR *pAddr);
|
||||
CNetHash(const CNetRange *pRange);
|
||||
|
||||
static int MakeHashArray(const NETADDR *pAddr, CNetHash aHash[17]);
|
||||
};
|
||||
|
||||
struct CBanInfo
|
||||
{
|
||||
enum
|
||||
{
|
||||
EXPIRES_NEVER=-1,
|
||||
REASON_LENGTH=64,
|
||||
};
|
||||
int m_Expires;
|
||||
char m_aReason[REASON_LENGTH];
|
||||
};
|
||||
|
||||
template<class T> struct CBan
|
||||
{
|
||||
T m_Data;
|
||||
CBanInfo m_Info;
|
||||
CNetHash m_NetHash;
|
||||
|
||||
// hash list
|
||||
CBan *m_pHashNext;
|
||||
CBan *m_pHashPrev;
|
||||
|
||||
// used or free list
|
||||
CBan *m_pNext;
|
||||
CBan *m_pPrev;
|
||||
};
|
||||
|
||||
template<class T, int HashCount> class CBanPool
|
||||
{
|
||||
public:
|
||||
typedef T CDataType;
|
||||
|
||||
CBan<CDataType> *Add(const CDataType *pData, const CBanInfo *pInfo, const CNetHash *pNetHash);
|
||||
int Remove(CBan<CDataType> *pBan);
|
||||
void Update(CBan<CDataType> *pBan, const CBanInfo *pInfo);
|
||||
void Reset();
|
||||
|
||||
int Num() const { return m_CountUsed; }
|
||||
bool IsFull() const { return m_CountUsed == MAX_BANS; }
|
||||
|
||||
CBan<CDataType> *First() const { return m_pFirstUsed; }
|
||||
CBan<CDataType> *First(const CNetHash *pNetHash) const { return m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; }
|
||||
CBan<CDataType> *Find(const CDataType *pData, const CNetHash *pNetHash) const;
|
||||
CBan<CDataType> *Get(int Index) const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
MAX_BANS=1024,
|
||||
};
|
||||
|
||||
CBan<CDataType> *m_paaHashList[HashCount][256];
|
||||
CBan<CDataType> m_aBans[MAX_BANS];
|
||||
CBan<CDataType> *m_pFirstFree;
|
||||
CBan<CDataType> *m_pFirstUsed;
|
||||
int m_CountUsed;
|
||||
};
|
||||
|
||||
typedef CBanPool<NETADDR, 1> CBanAddrPool;
|
||||
typedef CBanPool<CNetRange, 16> CBanRangePool;
|
||||
typedef CBan<NETADDR> CBanAddr;
|
||||
typedef CBan<CNetRange> CBanRange;
|
||||
|
||||
template<class T> void MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const;
|
||||
template<class T> int Ban(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason);
|
||||
template<class T> int Unban(T *pBanPool, const typename T::CDataType *pData);
|
||||
|
||||
class IConsole *m_pConsole;
|
||||
class IStorage *m_pStorage;
|
||||
CBanAddrPool m_BanAddrPool;
|
||||
CBanRangePool m_BanRangePool;
|
||||
NETADDR m_LocalhostIPV4, m_LocalhostIPV6;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MSGTYPE_PLAYER=0,
|
||||
MSGTYPE_LIST,
|
||||
MSGTYPE_BANADD,
|
||||
MSGTYPE_BANREM,
|
||||
};
|
||||
|
||||
class IConsole *Console() const { return m_pConsole; }
|
||||
class IStorage *Storage() const { return m_pStorage; }
|
||||
|
||||
virtual ~CNetBan() {}
|
||||
virtual void Init(class IConsole *pConsole, class IStorage *pStorage);
|
||||
void Update();
|
||||
|
||||
virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
|
||||
virtual int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
|
||||
int UnbanByAddr(const NETADDR *pAddr);
|
||||
int UnbanByRange(const CNetRange *pRange);
|
||||
int UnbanByIndex(int Index);
|
||||
void UnbanAll() { m_BanAddrPool.Reset(); m_BanRangePool.Reset(); }
|
||||
bool IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize) const;
|
||||
|
||||
static void ConBan(class IConsole::IResult *pResult, void *pUser);
|
||||
static void ConBanRange(class IConsole::IResult *pResult, void *pUser);
|
||||
static void ConUnban(class IConsole::IResult *pResult, void *pUser);
|
||||
static void ConUnbanRange(class IConsole::IResult *pResult, void *pUser);
|
||||
static void ConUnbanAll(class IConsole::IResult *pResult, void *pUser);
|
||||
static void ConBans(class IConsole::IResult *pResult, void *pUser);
|
||||
static void ConBansSave(class IConsole::IResult *pResult, void *pUser);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -73,8 +73,6 @@ enum
|
|||
NET_CTRLMSG_ACCEPT=3,
|
||||
NET_CTRLMSG_CLOSE=4,
|
||||
|
||||
NET_SERVER_MAXBANS=1024,
|
||||
|
||||
NET_CONN_BUFFERSIZE=1024*32,
|
||||
|
||||
NET_ENUM_TERMINATOR
|
||||
|
@ -182,7 +180,7 @@ public:
|
|||
const char *ErrorString();
|
||||
void SignalResend();
|
||||
int State() const { return m_State; }
|
||||
NETADDR PeerAddress() const { return m_PeerAddr; }
|
||||
const NETADDR *PeerAddress() const { return &m_PeerAddr; }
|
||||
|
||||
void ResetErrorString() { m_ErrorString[0] = 0; }
|
||||
const char *ErrorString() const { return m_ErrorString; }
|
||||
|
@ -214,7 +212,7 @@ public:
|
|||
void Disconnect(const char *pReason);
|
||||
|
||||
int State() const { return m_State; }
|
||||
NETADDR PeerAddress() const { return m_PeerAddr; }
|
||||
const NETADDR *PeerAddress() const { return &m_PeerAddr; }
|
||||
const char *ErrorString() const { return m_aErrorString; }
|
||||
|
||||
void Reset();
|
||||
|
@ -244,59 +242,29 @@ public:
|
|||
// server side
|
||||
class CNetServer
|
||||
{
|
||||
public:
|
||||
struct CBanInfo
|
||||
{
|
||||
NETADDR m_Addr;
|
||||
int m_Expires;
|
||||
char m_Reason[128];
|
||||
};
|
||||
|
||||
private:
|
||||
struct CSlot
|
||||
{
|
||||
public:
|
||||
CNetConnection m_Connection;
|
||||
};
|
||||
|
||||
struct CBan
|
||||
{
|
||||
public:
|
||||
CBanInfo m_Info;
|
||||
|
||||
// hash list
|
||||
CBan *m_pHashNext;
|
||||
CBan *m_pHashPrev;
|
||||
|
||||
// used or free list
|
||||
CBan *m_pNext;
|
||||
CBan *m_pPrev;
|
||||
};
|
||||
|
||||
|
||||
NETSOCKET m_Socket;
|
||||
class CNetBan *m_pNetBan;
|
||||
CSlot m_aSlots[NET_MAX_CLIENTS];
|
||||
int m_MaxClients;
|
||||
int m_MaxClientsPerIP;
|
||||
|
||||
CBan *m_aBans[256];
|
||||
CBan m_BanPool[NET_SERVER_MAXBANS];
|
||||
CBan *m_BanPool_FirstFree;
|
||||
CBan *m_BanPool_FirstUsed;
|
||||
|
||||
NETFUNC_NEWCLIENT m_pfnNewClient;
|
||||
NETFUNC_DELCLIENT m_pfnDelClient;
|
||||
void *m_UserPtr;
|
||||
|
||||
CNetRecvUnpacker m_RecvUnpacker;
|
||||
|
||||
void BanRemoveByObject(CBan *pBan);
|
||||
|
||||
public:
|
||||
int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
||||
|
||||
//
|
||||
bool Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int Flags);
|
||||
bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags);
|
||||
int Close();
|
||||
|
||||
//
|
||||
|
@ -307,16 +275,10 @@ public:
|
|||
//
|
||||
int Drop(int ClientID, const char *pReason);
|
||||
|
||||
// banning
|
||||
int BanAdd(NETADDR Addr, int Seconds, const char *pReason);
|
||||
int BanRemove(NETADDR Addr);
|
||||
int BanRemoveAll();
|
||||
int BanNum(); // caution, slow
|
||||
int BanGet(int Index, CBanInfo *pInfo); // caution, slow
|
||||
|
||||
// status requests
|
||||
NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
||||
const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
||||
NETSOCKET Socket() const { return m_Socket; }
|
||||
class CNetBan *NetBan() const { return m_pNetBan; }
|
||||
int NetType() const { return m_Socket.type; }
|
||||
int MaxClients() const { return m_MaxClients; }
|
||||
|
||||
|
@ -341,27 +303,13 @@ private:
|
|||
|
||||
class CNetConsole
|
||||
{
|
||||
enum
|
||||
{
|
||||
MAX_BANS=128,
|
||||
};
|
||||
|
||||
int FindBan(NETADDR Addr);
|
||||
void UpdateBans();
|
||||
|
||||
struct CBanEntry
|
||||
{
|
||||
NETADDR m_Addr;
|
||||
int m_Expires;
|
||||
} m_aBans[MAX_BANS];
|
||||
int m_NumBans;
|
||||
|
||||
struct CSlot
|
||||
{
|
||||
CConsoleNetConnection m_Connection;
|
||||
};
|
||||
|
||||
NETSOCKET m_Socket;
|
||||
class CNetBan *m_pNetBan;
|
||||
CSlot m_aSlots[NET_MAX_CONSOLE_CLIENTS];
|
||||
|
||||
NETFUNC_NEWCLIENT m_pfnNewClient;
|
||||
|
@ -374,7 +322,7 @@ public:
|
|||
void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
||||
|
||||
//
|
||||
bool Open(NETADDR BindAddr, int Flags);
|
||||
bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int Flags);
|
||||
int Close();
|
||||
|
||||
//
|
||||
|
@ -386,10 +334,9 @@ public:
|
|||
int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
|
||||
int Drop(int ClientID, const char *pReason);
|
||||
|
||||
bool AddBan(NETADDR Addr, int Seconds);
|
||||
|
||||
// status requests
|
||||
NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
||||
const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
||||
class CNetBan *NetBan() const { return m_pNetBan; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
/* (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. */
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/console.h>
|
||||
|
||||
#include "netban.h"
|
||||
#include "network.h"
|
||||
|
||||
bool CNetConsole::Open(NETADDR BindAddr, int Flags)
|
||||
|
||||
bool CNetConsole::Open(NETADDR BindAddr, CNetBan *pNetBan, int Flags)
|
||||
{
|
||||
// zero out the whole structure
|
||||
mem_zero(this, sizeof(*this));
|
||||
m_Socket.type = NETTYPE_INVALID;
|
||||
m_Socket.ipv4sock = -1;
|
||||
m_Socket.ipv6sock = -1;
|
||||
m_pNetBan = pNetBan;
|
||||
|
||||
// open socket
|
||||
m_Socket = net_tcp_create(BindAddr);
|
||||
|
@ -64,8 +70,7 @@ int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr)
|
|||
FreeSlot = i;
|
||||
if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE)
|
||||
{
|
||||
NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||
if(net_addr_comp(pAddr, &PeerAddr) == 0)
|
||||
if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress()) == 0)
|
||||
{
|
||||
str_copy(aError, "only one client per IP allowed", sizeof(aError));
|
||||
break;
|
||||
|
@ -99,26 +104,16 @@ int CNetConsole::Update()
|
|||
|
||||
if(net_tcp_accept(m_Socket, &Socket, &Addr) > 0)
|
||||
{
|
||||
int Index = FindBan(Addr);
|
||||
if(Index == -1)
|
||||
AcceptClient(Socket, &Addr);
|
||||
else
|
||||
// check if we just should drop the packet
|
||||
char aBuf[128];
|
||||
if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
|
||||
{
|
||||
char aBuf[128];
|
||||
if(m_aBans[Index].m_Expires > -1)
|
||||
{
|
||||
int Mins = (m_aBans[Index].m_Expires-time_timestamp()+ 59) / 60;
|
||||
if(Mins <= 1)
|
||||
str_format(aBuf, sizeof(aBuf), "You have been banned for 1 minute");
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "You have been banned for %d minutes", Mins);
|
||||
}
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "You have been banned for life");
|
||||
|
||||
// banned, reply with a message and drop
|
||||
net_tcp_send(Socket, aBuf, str_length(aBuf));
|
||||
net_tcp_close(Socket);
|
||||
}
|
||||
else
|
||||
AcceptClient(Socket, &Addr);
|
||||
}
|
||||
|
||||
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
||||
|
@ -129,8 +124,6 @@ int CNetConsole::Update()
|
|||
Drop(i, m_aSlots[i].m_Connection.ErrorString());
|
||||
}
|
||||
|
||||
UpdateBans();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -155,65 +148,3 @@ int CNetConsole::Send(int ClientID, const char *pLine)
|
|||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetConsole::FindBan(NETADDR Addr)
|
||||
{
|
||||
Addr.port = 0;
|
||||
for(int i = 0; i < m_NumBans; i++)
|
||||
if(net_addr_comp(&m_aBans[i].m_Addr, &Addr) == 0)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool CNetConsole::AddBan(NETADDR Addr, int Seconds)
|
||||
{
|
||||
if(m_NumBans == MAX_BANS)
|
||||
return false;
|
||||
|
||||
Addr.port = 0;
|
||||
int Index = FindBan(Addr);
|
||||
if(Index == -1)
|
||||
{
|
||||
Index = m_NumBans++;
|
||||
m_aBans[Index].m_Addr = Addr;
|
||||
}
|
||||
m_aBans[Index].m_Expires = Seconds>0 ? time_timestamp()+Seconds : -1;
|
||||
|
||||
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
|
||||
{
|
||||
if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE)
|
||||
{
|
||||
NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||
PeerAddr.port = 0;
|
||||
if(net_addr_comp(&Addr, &PeerAddr) == 0)
|
||||
{
|
||||
char aBuf[128];
|
||||
if(Seconds>0)
|
||||
{
|
||||
int Mins = (Seconds + 59) / 60;
|
||||
if(Mins <= 1)
|
||||
str_format(aBuf, sizeof(aBuf), "You have been banned for 1 minute");
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "You have been banned for %d minutes", Mins);
|
||||
}
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "You have been banned for life");
|
||||
Drop(i, aBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetConsole::UpdateBans()
|
||||
{
|
||||
int Now = time_timestamp();
|
||||
for(int i = 0; i < m_NumBans; ++i)
|
||||
if(m_aBans[i].m_Expires > 0 && m_aBans[i].m_Expires < Now)
|
||||
{
|
||||
m_aBans[i] = m_aBans[m_NumBans-1];
|
||||
--m_NumBans;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,16 @@
|
|||
/* (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. */
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/console.h>
|
||||
|
||||
#include "netban.h"
|
||||
#include "network.h"
|
||||
|
||||
|
||||
#include <banmaster/banmaster.h>
|
||||
|
||||
#define MACRO_LIST_LINK_FIRST(Object, First, Prev, Next) \
|
||||
{ if(First) First->Prev = Object; \
|
||||
Object->Prev = (struct CBan *)0; \
|
||||
Object->Next = First; \
|
||||
First = Object; }
|
||||
|
||||
#define MACRO_LIST_LINK_AFTER(Object, After, Prev, Next) \
|
||||
{ Object->Prev = After; \
|
||||
Object->Next = After->Next; \
|
||||
After->Next = Object; \
|
||||
if(Object->Next) \
|
||||
Object->Next->Prev = Object; \
|
||||
}
|
||||
|
||||
#define MACRO_LIST_UNLINK(Object, First, Prev, Next) \
|
||||
{ if(Object->Next) Object->Next->Prev = Object->Prev; \
|
||||
if(Object->Prev) Object->Prev->Next = Object->Next; \
|
||||
else First = Object->Next; \
|
||||
Object->Next = 0; Object->Prev = 0; }
|
||||
|
||||
#define MACRO_LIST_FIND(Start, Next, Expression) \
|
||||
{ while(Start && !(Expression)) Start = Start->Next; }
|
||||
|
||||
bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int Flags)
|
||||
bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags)
|
||||
{
|
||||
// zero out the whole structure
|
||||
mem_zero(this, sizeof(*this));
|
||||
|
@ -38,6 +20,8 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int
|
|||
if(!m_Socket.type)
|
||||
return false;
|
||||
|
||||
m_pNetBan = pNetBan;
|
||||
|
||||
// clamp clients
|
||||
m_MaxClients = MaxClients;
|
||||
if(m_MaxClients > NET_MAX_CLIENTS)
|
||||
|
@ -50,8 +34,6 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int
|
|||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
m_aSlots[i].m_Connection.Init(m_Socket);
|
||||
|
||||
BanRemoveAll();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -87,182 +69,8 @@ int CNetServer::Drop(int ClientID, const char *pReason)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CNetServer::BanGet(int Index, CBanInfo *pInfo)
|
||||
{
|
||||
CBan *pBan;
|
||||
for(pBan = m_BanPool_FirstUsed; pBan && Index; pBan = pBan->m_pNext, Index--)
|
||||
{}
|
||||
|
||||
if(!pBan)
|
||||
return 0;
|
||||
*pInfo = pBan->m_Info;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CNetServer::BanNum()
|
||||
{
|
||||
int Count = 0;
|
||||
CBan *pBan;
|
||||
for(pBan = m_BanPool_FirstUsed; pBan; pBan = pBan->m_pNext)
|
||||
Count++;
|
||||
return Count;
|
||||
}
|
||||
|
||||
void CNetServer::BanRemoveByObject(CBan *pBan)
|
||||
{
|
||||
int IpHash = (pBan->m_Info.m_Addr.ip[0]+pBan->m_Info.m_Addr.ip[1]+pBan->m_Info.m_Addr.ip[2]+pBan->m_Info.m_Addr.ip[3]+
|
||||
pBan->m_Info.m_Addr.ip[4]+pBan->m_Info.m_Addr.ip[5]+pBan->m_Info.m_Addr.ip[6]+pBan->m_Info.m_Addr.ip[7]+
|
||||
pBan->m_Info.m_Addr.ip[8]+pBan->m_Info.m_Addr.ip[9]+pBan->m_Info.m_Addr.ip[10]+pBan->m_Info.m_Addr.ip[11]+
|
||||
pBan->m_Info.m_Addr.ip[12]+pBan->m_Info.m_Addr.ip[13]+pBan->m_Info.m_Addr.ip[14]+pBan->m_Info.m_Addr.ip[15])&0xff;
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&pBan->m_Info.m_Addr, aAddrStr, sizeof(aAddrStr));
|
||||
dbg_msg("netserver", "removing ban on %s", aAddrStr);
|
||||
MACRO_LIST_UNLINK(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext);
|
||||
MACRO_LIST_UNLINK(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext);
|
||||
MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext);
|
||||
}
|
||||
|
||||
int CNetServer::BanRemove(NETADDR Addr)
|
||||
{
|
||||
int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+
|
||||
Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff;
|
||||
CBan *pBan = m_aBans[IpHash];
|
||||
|
||||
MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0);
|
||||
|
||||
if(pBan)
|
||||
{
|
||||
BanRemoveByObject(pBan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetServer::BanRemoveAll()
|
||||
{
|
||||
// clear bans memory
|
||||
mem_zero(m_aBans, sizeof(m_aBans));
|
||||
mem_zero(m_BanPool, sizeof(m_BanPool));
|
||||
m_BanPool_FirstFree = 0;
|
||||
m_BanPool_FirstUsed = 0;
|
||||
|
||||
// setup all pointers for bans
|
||||
for(int i = 1; i < NET_SERVER_MAXBANS-1; i++)
|
||||
{
|
||||
m_BanPool[i].m_pNext = &m_BanPool[i+1];
|
||||
m_BanPool[i].m_pPrev = &m_BanPool[i-1];
|
||||
}
|
||||
|
||||
m_BanPool[0].m_pNext = &m_BanPool[1];
|
||||
m_BanPool[NET_SERVER_MAXBANS-1].m_pPrev = &m_BanPool[NET_SERVER_MAXBANS-2];
|
||||
m_BanPool_FirstFree = &m_BanPool[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason)
|
||||
{
|
||||
int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+
|
||||
Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff;
|
||||
int Stamp = -1;
|
||||
CBan *pBan;
|
||||
|
||||
// remove the port
|
||||
Addr.port = 0;
|
||||
|
||||
if(Seconds)
|
||||
Stamp = time_timestamp() + Seconds;
|
||||
|
||||
// search to remove it if it already exists
|
||||
pBan = m_aBans[IpHash];
|
||||
MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0);
|
||||
if(pBan)
|
||||
BanRemoveByObject(pBan);
|
||||
|
||||
if(!m_BanPool_FirstFree)
|
||||
return -1;
|
||||
|
||||
// fetch and clear the new ban
|
||||
pBan = m_BanPool_FirstFree;
|
||||
MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext);
|
||||
|
||||
// setup the ban info
|
||||
pBan->m_Info.m_Expires = Stamp;
|
||||
pBan->m_Info.m_Addr = Addr;
|
||||
str_copy(pBan->m_Info.m_Reason, pReason, sizeof(pBan->m_Info.m_Reason));
|
||||
|
||||
// add it to the ban hash
|
||||
MACRO_LIST_LINK_FIRST(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext);
|
||||
|
||||
// insert it into the used list
|
||||
{
|
||||
if(m_BanPool_FirstUsed)
|
||||
{
|
||||
CBan *pInsertAfter = m_BanPool_FirstUsed;
|
||||
MACRO_LIST_FIND(pInsertAfter, m_pNext, Stamp < pInsertAfter->m_Info.m_Expires);
|
||||
|
||||
if(pInsertAfter && Stamp != -1)
|
||||
pInsertAfter = pInsertAfter->m_pPrev;
|
||||
else
|
||||
{
|
||||
// add to last
|
||||
if (m_BanPool_FirstUsed->m_Info.m_Expires == -1)
|
||||
pInsertAfter = 0;
|
||||
else
|
||||
{
|
||||
pInsertAfter = m_BanPool_FirstUsed;
|
||||
while(pInsertAfter->m_pNext && pInsertAfter->m_pNext->m_Info.m_Expires != -1)
|
||||
pInsertAfter = pInsertAfter->m_pNext;
|
||||
}
|
||||
}
|
||||
|
||||
if(pInsertAfter)
|
||||
{
|
||||
MACRO_LIST_LINK_AFTER(pBan, pInsertAfter, m_pPrev, m_pNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext);
|
||||
}
|
||||
}
|
||||
|
||||
// drop banned clients
|
||||
{
|
||||
char Buf[128];
|
||||
NETADDR BanAddr;
|
||||
|
||||
if(Stamp > -1)
|
||||
{
|
||||
int Mins = (Seconds + 59) / 60;
|
||||
if(Mins <= 1)
|
||||
str_format(Buf, sizeof(Buf), "You have been banned for 1 minute (%s)", pReason);
|
||||
else
|
||||
str_format(Buf, sizeof(Buf), "You have been banned for %d minutes (%s)", Mins, pReason);
|
||||
}
|
||||
else
|
||||
str_format(Buf, sizeof(Buf), "You have been banned for life (%s)", pReason);
|
||||
|
||||
for(int i = 0; i < MaxClients(); i++)
|
||||
{
|
||||
BanAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||
BanAddr.port = 0;
|
||||
|
||||
if(net_addr_comp(&Addr, &BanAddr) == 0)
|
||||
Drop(i, Buf);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetServer::Update()
|
||||
{
|
||||
int Now = time_timestamp();
|
||||
for(int i = 0; i < MaxClients(); i++)
|
||||
{
|
||||
m_aSlots[i].m_Connection.Update();
|
||||
|
@ -270,13 +78,6 @@ int CNetServer::Update()
|
|||
Drop(i, m_aSlots[i].m_Connection.ErrorString());
|
||||
}
|
||||
|
||||
// remove expired bans
|
||||
while(m_BanPool_FirstUsed && m_BanPool_FirstUsed->m_Info.m_Expires > -1 && m_BanPool_FirstUsed->m_Info.m_Expires < Now)
|
||||
{
|
||||
CBan *pBan = m_BanPool_FirstUsed;
|
||||
BanRemoveByObject(pBan);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -285,8 +86,6 @@ int CNetServer::Update()
|
|||
*/
|
||||
int CNetServer::Recv(CNetChunk *pChunk)
|
||||
{
|
||||
unsigned Now = time_timestamp();
|
||||
|
||||
while(1)
|
||||
{
|
||||
NETADDR Addr;
|
||||
|
@ -304,36 +103,12 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
|
||||
if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0)
|
||||
{
|
||||
CBan *pBan = 0;
|
||||
NETADDR BanAddr = Addr;
|
||||
int IpHash = (BanAddr.ip[0]+BanAddr.ip[1]+BanAddr.ip[2]+BanAddr.ip[3]+BanAddr.ip[4]+BanAddr.ip[5]+BanAddr.ip[6]+BanAddr.ip[7]+
|
||||
BanAddr.ip[8]+BanAddr.ip[9]+BanAddr.ip[10]+BanAddr.ip[11]+BanAddr.ip[12]+BanAddr.ip[13]+BanAddr.ip[14]+BanAddr.ip[15])&0xff;
|
||||
int Found = 0;
|
||||
BanAddr.port = 0;
|
||||
|
||||
// search a ban
|
||||
for(pBan = m_aBans[IpHash]; pBan; pBan = pBan->m_pHashNext)
|
||||
{
|
||||
if(net_addr_comp(&pBan->m_Info.m_Addr, &BanAddr) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// check if we just should drop the packet
|
||||
if(pBan)
|
||||
char aBuf[128];
|
||||
if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
|
||||
{
|
||||
// banned, reply with a message
|
||||
char BanStr[128];
|
||||
if(pBan->m_Info.m_Expires > -1)
|
||||
{
|
||||
int Mins = ((pBan->m_Info.m_Expires - Now)+59)/60;
|
||||
if(Mins <= 1)
|
||||
str_format(BanStr, sizeof(BanStr), "Banned for 1 minute (%s)", pBan->m_Info.m_Reason);
|
||||
else
|
||||
str_format(BanStr, sizeof(BanStr), "Banned for %d minutes (%s)", Mins, pBan->m_Info.m_Reason);
|
||||
}
|
||||
else
|
||||
str_format(BanStr, sizeof(BanStr), "Banned for life (%s)", pBan->m_Info.m_Reason);
|
||||
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, BanStr, str_length(BanStr)+1);
|
||||
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -351,16 +126,15 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
// TODO: check size here
|
||||
if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT)
|
||||
{
|
||||
Found = 0;
|
||||
bool Found = false;
|
||||
|
||||
// check if we already got this client
|
||||
for(int i = 0; i < MaxClients(); i++)
|
||||
{
|
||||
NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||
if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE &&
|
||||
net_addr_comp(&PeerAddr, &Addr) == 0)
|
||||
net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0)
|
||||
{
|
||||
Found = 1; // silent ignore.. we got this client already
|
||||
Found = true; // silent ignore.. we got this client already
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +145,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
CNetChunk Packet;
|
||||
char aBuffer[sizeof(BANMASTER_IPCHECK) + NETADDR_MAXSTRSIZE];
|
||||
mem_copy(aBuffer, BANMASTER_IPCHECK, sizeof(BANMASTER_IPCHECK));
|
||||
net_addr_str(&Addr, aBuffer + sizeof(BANMASTER_IPCHECK), sizeof(aBuffer) - sizeof(BANMASTER_IPCHECK));
|
||||
net_addr_str(&Addr, aBuffer + sizeof(BANMASTER_IPCHECK), sizeof(aBuffer) - sizeof(BANMASTER_IPCHECK), false);
|
||||
|
||||
Packet.m_ClientID = -1;
|
||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
||||
|
@ -393,7 +167,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
||||
continue;
|
||||
|
||||
OtherAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||
OtherAddr = *m_aSlots[i].m_Connection.PeerAddress();
|
||||
OtherAddr.port = 0;
|
||||
if(!net_addr_comp(&ThisAddr, &OtherAddr))
|
||||
{
|
||||
|
@ -411,7 +185,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
{
|
||||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
||||
{
|
||||
Found = 1;
|
||||
Found = true;
|
||||
m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr);
|
||||
if(m_pfnNewClient)
|
||||
m_pfnNewClient(i, m_UserPtr);
|
||||
|
@ -431,8 +205,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
// normal packet, find matching slot
|
||||
for(int i = 0; i < MaxClients(); i++)
|
||||
{
|
||||
NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
|
||||
if(net_addr_comp(&PeerAddr, &Addr) == 0)
|
||||
if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0)
|
||||
{
|
||||
if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr))
|
||||
{
|
||||
|
|
|
@ -615,16 +615,10 @@ void CGameConsole::Dump(int Type)
|
|||
IOHANDLE io = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
if(io)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
static const char Newline[] = "\r\n";
|
||||
#else
|
||||
static const char Newline[] = "\n";
|
||||
#endif
|
||||
|
||||
for(CInstance::CBacklogEntry *pEntry = pConsole->m_Backlog.First(); pEntry; pEntry = pConsole->m_Backlog.Next(pEntry))
|
||||
{
|
||||
io_write(io, pEntry->m_aText, str_length(pEntry->m_aText));
|
||||
io_write(io, Newline, sizeof(Newline)-1);
|
||||
io_write_newline(io);
|
||||
}
|
||||
io_close(io);
|
||||
}
|
||||
|
|
|
@ -212,16 +212,11 @@ void CMapLayers::OnRender()
|
|||
IOHANDLE File = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
if(File)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
static const char Newline[] = "\r\n";
|
||||
#else
|
||||
static const char Newline[] = "\n";
|
||||
#endif
|
||||
for(int y = 0; y < pTMap->m_Height; y++)
|
||||
{
|
||||
for(int x = 0; x < pTMap->m_Width; x++)
|
||||
io_write(File, &(pTiles[y*pTMap->m_Width + x].m_Index), sizeof(pTiles[y*pTMap->m_Width + x].m_Index));
|
||||
io_write(File, Newline, sizeof(Newline)-1);
|
||||
io_write_newline(File);
|
||||
}
|
||||
io_close(File);
|
||||
}
|
||||
|
|
|
@ -207,6 +207,8 @@ void CGameClient::OnConsoleInit()
|
|||
Console()->Register("force_vote", "ss?r", CFGFLAG_SERVER, 0, 0, "Force a voting option");
|
||||
Console()->Register("clear_votes", "", CFGFLAG_SERVER, 0, 0, "Clears the voting options");
|
||||
Console()->Register("vote", "r", CFGFLAG_SERVER, 0, 0, "Force a vote to yes/no");
|
||||
Console()->Register("swap_teams", "", CFGFLAG_SERVER, 0, 0, "Swap the current teams");
|
||||
Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, 0, 0, "Shuffle the current teams");
|
||||
|
||||
|
||||
// propagate pointers
|
||||
|
|
|
@ -389,7 +389,7 @@ void CGameContext::ConUnmute(IConsole::IResult *pResult, void *pUserData)
|
|||
pSelf->m_NumMutes--;
|
||||
pSelf->m_aMutes[Victim] = pSelf->m_aMutes[pSelf->m_NumMutes];
|
||||
|
||||
net_addr_str(&pSelf->m_aMutes[Victim].m_Addr, aIpBuf, sizeof(aIpBuf));
|
||||
net_addr_str(&pSelf->m_aMutes[Victim].m_Addr, aIpBuf, sizeof(aIpBuf), false);
|
||||
str_format(aBuf, sizeof(aBuf), "Unmuted %s", aIpBuf);
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", aBuf);
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ void CGameContext::ConMutes(IConsole::IResult *pResult, void *pUserData)
|
|||
"Active mutes:");
|
||||
for (int i = 0; i < pSelf->m_NumMutes; i++)
|
||||
{
|
||||
net_addr_str(&pSelf->m_aMutes[i].m_Addr, aIpBuf, sizeof(aIpBuf));
|
||||
net_addr_str(&pSelf->m_aMutes[i].m_Addr, aIpBuf, sizeof(aIpBuf), false);
|
||||
str_format(
|
||||
aBuf,
|
||||
sizeof aBuf,
|
||||
|
|
|
@ -230,7 +230,15 @@ void CGameContext::CreateSoundGlobal(int Sound, int Target)
|
|||
|
||||
CNetMsg_Sv_SoundGlobal Msg;
|
||||
Msg.m_SoundID = Sound;
|
||||
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, Target);
|
||||
if(Target == -2)
|
||||
Server()->SendPackMsg(&Msg, MSGFLAG_NOSEND, -1);
|
||||
else
|
||||
{
|
||||
int Flag = MSGFLAG_VITAL;
|
||||
if(Target != -1)
|
||||
Flag |= MSGFLAG_NORECORD;
|
||||
Server()->SendPackMsg(&Msg, Flag, Target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -432,7 +440,23 @@ void CGameContext::SendTuningParams(int ClientID)
|
|||
Msg.AddInt(pParams[i]);
|
||||
Server()->SendMsg(&Msg, MSGFLAG_VITAL, ClientID);
|
||||
}
|
||||
/*
|
||||
void CGameContext::SwapTeams()
|
||||
{
|
||||
if(!m_pController->IsTeamplay())
|
||||
return;
|
||||
|
||||
SendChat(-1, CGameContext::CHAT_ALL, "Teams were swapped");
|
||||
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(m_apPlayers[i] && m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
|
||||
m_apPlayers[i]->SetTeam(m_apPlayers[i]->GetTeam()^1, false);
|
||||
}
|
||||
|
||||
(void)m_pController->CheckTeamBalance();
|
||||
}
|
||||
*/
|
||||
void CGameContext::OnTick()
|
||||
{
|
||||
// check tuning
|
||||
|
@ -527,7 +551,9 @@ void CGameContext::OnTick()
|
|||
|
||||
if(m_VoteEnforce == VOTE_ENFORCE_YES)
|
||||
{
|
||||
Server()->SetRconCID(IServer::RCON_CID_VOTE);
|
||||
Console()->ExecuteLine(m_aVoteCommand);
|
||||
Server()->SetRconCID(IServer::RCON_CID_SERV);
|
||||
EndVote();
|
||||
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
|
||||
|
||||
|
@ -960,7 +986,6 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
char aAddrStr[NETADDR_MAXSTRSIZE] = {0};
|
||||
Server()->GetClientAddr(KickID, aAddrStr, sizeof(aAddrStr));
|
||||
str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, g_Config.m_SvVoteKickBantime);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aCmd);
|
||||
}
|
||||
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
|
||||
m_VoteKick = true;
|
||||
|
@ -1388,17 +1413,14 @@ void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData)
|
|||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
int ClientID = clamp(pResult->GetInteger(0), 0, (int)MAX_CLIENTS-1);
|
||||
int Team = clamp(pResult->GetInteger(1), -1, 1);
|
||||
int Delay = 0;
|
||||
if(pResult->NumArguments() > 2)
|
||||
Delay = pResult->GetInteger(2);
|
||||
int Delay = pResult->NumArguments()>2 ? pResult->GetInteger(2) : 0;
|
||||
if(!pSelf->m_apPlayers[ClientID])
|
||||
return;
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "moved client %d to team %d", ClientID, Team);
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
|
||||
if(!pSelf->m_apPlayers[ClientID])
|
||||
return;
|
||||
|
||||
pSelf->m_apPlayers[ClientID]->m_TeamChangeTick = pSelf->Server()->Tick()+pSelf->Server()->TickSpeed()*Delay*60;
|
||||
pSelf->m_apPlayers[ClientID]->SetTeam(Team);
|
||||
// (void)pSelf->m_pController->CheckTeamBalance();
|
||||
|
@ -1410,16 +1432,65 @@ void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData)
|
|||
int Team = clamp(pResult->GetInteger(0), -1, 1);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "moved all clients to team %d", Team);
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
str_format(aBuf, sizeof(aBuf), "All players were moved to the %s", pSelf->m_pController->GetTeamName(Team));
|
||||
pSelf->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
|
||||
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
if(pSelf->m_apPlayers[i])
|
||||
pSelf->m_apPlayers[i]->SetTeam(Team);
|
||||
pSelf->m_apPlayers[i]->SetTeam(Team, false);
|
||||
|
||||
// (void)pSelf->m_pController->CheckTeamBalance();
|
||||
}
|
||||
/*
|
||||
void CGameContext::ConSwapTeams(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
pSelf->SwapTeams();
|
||||
}
|
||||
|
||||
void CGameContext::ConShuffleTeams(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
if(!pSelf->m_pController->IsTeamplay())
|
||||
return;
|
||||
|
||||
int CounterRed = 0;
|
||||
int CounterBlue = 0;
|
||||
int PlayerTeam = 0;
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
|
||||
++PlayerTeam;
|
||||
PlayerTeam = (PlayerTeam+1)/2;
|
||||
|
||||
pSelf->SendChat(-1, CGameContext::CHAT_ALL, "Teams were shuffled");
|
||||
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
|
||||
{
|
||||
if(CounterRed == PlayerTeam)
|
||||
pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false);
|
||||
else if(CounterBlue == PlayerTeam)
|
||||
pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false);
|
||||
else
|
||||
{
|
||||
if(rand() % 2)
|
||||
{
|
||||
pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false);
|
||||
++CounterBlue;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false);
|
||||
++CounterRed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (void)pSelf->m_pController->CheckTeamBalance();
|
||||
}
|
||||
*/
|
||||
void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
|
@ -1682,6 +1753,8 @@ void CGameContext::OnConsoleInit()
|
|||
Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, "Say in chat");
|
||||
Console()->Register("set_team", "ii?i", CFGFLAG_SERVER, ConSetTeam, this, "Set team of player to team");
|
||||
Console()->Register("set_team_all", "i", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team");
|
||||
//Console()->Register("swap_teams", "", CFGFLAG_SERVER, ConSwapTeams, this, "Swap the current teams");
|
||||
//Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, ConShuffleTeams, this, "Shuffle the current teams");
|
||||
|
||||
Console()->Register("add_vote", "sr", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option");
|
||||
Console()->Register("remove_vote", "s", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option");
|
||||
|
|
|
@ -55,6 +55,8 @@ class CGameContext : public IGameServer
|
|||
static void ConSay(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConSetTeam(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConSetTeamAll(IConsole::IResult *pResult, void *pUserData);
|
||||
//static void ConSwapTeams(IConsole::IResult *pResult, void *pUserData);
|
||||
//static void ConShuffleTeams(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConAddVote(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConRemoveVote(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConForceVote(IConsole::IResult *pResult, void *pUserData);
|
||||
|
@ -142,6 +144,9 @@ public:
|
|||
void CheckPureTuning();
|
||||
void SendTuningParams(int ClientID);
|
||||
|
||||
//
|
||||
//void SwapTeams();
|
||||
|
||||
// engine events
|
||||
virtual void OnInit();
|
||||
virtual void OnConsoleInit();
|
||||
|
|
|
@ -439,7 +439,11 @@ void IGameController::ChangeMap(const char *pToMap)
|
|||
return;
|
||||
|
||||
if(m_RoundCount < g_Config.m_SvRoundsPerMap-1)
|
||||
{
|
||||
if(g_Config.m_SvRoundSwap)
|
||||
GameServer()->SwapTeams();
|
||||
return;
|
||||
}
|
||||
|
||||
// handle maprotation
|
||||
const char *pMapRotation = g_Config.m_SvMaprotation;
|
||||
|
|
|
@ -260,6 +260,8 @@ void CGameControllerCTF::Tick()
|
|||
else
|
||||
GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_PL, c);
|
||||
}
|
||||
// demo record entry
|
||||
GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, -2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ void CPlayer::Respawn()
|
|||
m_Spawning = true;
|
||||
}
|
||||
|
||||
void CPlayer::SetTeam(int Team)
|
||||
void CPlayer::SetTeam(int Team, bool DoChatMsg)
|
||||
{
|
||||
// clamp the team
|
||||
Team = GameServer()->m_pController->ClampTeam(Team);
|
||||
|
@ -312,8 +312,11 @@ void CPlayer::SetTeam(int Team)
|
|||
return;
|
||||
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
|
||||
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
|
||||
if(DoChatMsg)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
|
||||
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
|
||||
}
|
||||
|
||||
KillCharacter();
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
void TryRespawn();
|
||||
void Respawn();
|
||||
void SetTeam(int Team);
|
||||
void SetTeam(int Team, bool DoChatMsg=true);
|
||||
int GetTeam() const { return m_Team; };
|
||||
int GetCID() const { return m_ClientID; };
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ MACRO_CONFIG_STR(SvMotd, sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day t
|
|||
MACRO_CONFIG_INT(SvTeamdamage, sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage")
|
||||
MACRO_CONFIG_STR(SvMaprotation, sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between")
|
||||
MACRO_CONFIG_INT(SvRoundsPerMap, sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating")
|
||||
MACRO_CONFIG_INT(SvRoundSwap, sv_round_swap, 1, 0, 1, CFGFLAG_SERVER, "Swap teams between rounds")
|
||||
MACRO_CONFIG_INT(SvPowerups, sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja")
|
||||
MACRO_CONFIG_INT(SvScorelimit, sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)")
|
||||
MACRO_CONFIG_INT(SvTimelimit, sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)")
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
/* (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. */
|
||||
#include <base/system.h>
|
||||
#include <engine/shared/network.h>
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
#include <engine/console.h>
|
||||
#include <engine/storage.h>
|
||||
#include <engine/kernel.h>
|
||||
#include <engine/storage.h>
|
||||
|
||||
#include <engine/shared/config.h>
|
||||
#include <engine/shared/netban.h>
|
||||
#include <engine/shared/network.h>
|
||||
|
||||
#include "mastersrv.h"
|
||||
|
||||
|
||||
enum {
|
||||
MTU = 1400,
|
||||
MAX_SERVERS_PER_PACKET=75,
|
||||
MAX_PACKETS=16,
|
||||
MAX_SERVERS=MAX_SERVERS_PER_PACKET*MAX_PACKETS,
|
||||
MAX_BANS=128,
|
||||
EXPIRE_TIME = 90
|
||||
};
|
||||
|
||||
|
@ -77,14 +80,7 @@ static CCountPacketData m_CountData;
|
|||
static CCountPacketData m_CountDataLegacy;
|
||||
|
||||
|
||||
struct CBanEntry
|
||||
{
|
||||
NETADDR m_Address;
|
||||
int64 m_Expire;
|
||||
};
|
||||
|
||||
static CBanEntry m_aBans[MAX_BANS];
|
||||
static int m_NumBans = 0;
|
||||
CNetBan m_NetBan;
|
||||
|
||||
static CNetClient m_NetChecker; // NAT/FW checker
|
||||
static CNetClient m_NetOp; // main
|
||||
|
@ -217,9 +213,9 @@ void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type)
|
|||
}
|
||||
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true);
|
||||
char aAltAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pAlt, aAltAddrStr, sizeof(aAltAddrStr));
|
||||
net_addr_str(pAlt, aAltAddrStr, sizeof(aAltAddrStr), true);
|
||||
dbg_msg("mastersrv", "checking: %s (%s)", aAddrStr, aAltAddrStr);
|
||||
m_aCheckServers[m_NumCheckServers].m_Address = *pInfo;
|
||||
m_aCheckServers[m_NumCheckServers].m_AltAddress = *pAlt;
|
||||
|
@ -237,7 +233,7 @@ void AddServer(NETADDR *pInfo, ServerType Type)
|
|||
if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true);
|
||||
dbg_msg("mastersrv", "updated: %s", aAddrStr);
|
||||
m_aServers[i].m_Expire = time_get()+time_freq()*EXPIRE_TIME;
|
||||
return;
|
||||
|
@ -252,7 +248,7 @@ void AddServer(NETADDR *pInfo, ServerType Type)
|
|||
}
|
||||
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true);
|
||||
dbg_msg("mastersrv", "added: %s", aAddrStr);
|
||||
m_aServers[m_NumServers].m_Address = *pInfo;
|
||||
m_aServers[m_NumServers].m_Expire = time_get()+time_freq()*EXPIRE_TIME;
|
||||
|
@ -271,9 +267,9 @@ void UpdateServers()
|
|||
if(m_aCheckServers[i].m_TryCount == 10)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&m_aCheckServers[i].m_Address, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&m_aCheckServers[i].m_Address, aAddrStr, sizeof(aAddrStr), true);
|
||||
char aAltAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&m_aCheckServers[i].m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr));
|
||||
net_addr_str(&m_aCheckServers[i].m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr), true);
|
||||
dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr);
|
||||
|
||||
// FAIL!!
|
||||
|
@ -305,7 +301,7 @@ void PurgeServers()
|
|||
{
|
||||
// remove server
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&m_aServers[i].m_Address, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&m_aServers[i].m_Address, aAddrStr, sizeof(aAddrStr), true);
|
||||
dbg_msg("mastersrv", "expired: %s", aAddrStr);
|
||||
m_aServers[i] = m_aServers[m_NumServers-1];
|
||||
m_NumServers--;
|
||||
|
@ -315,53 +311,9 @@ void PurgeServers()
|
|||
}
|
||||
}
|
||||
|
||||
bool CheckBan(NETADDR Addr)
|
||||
{
|
||||
for(int i = 0; i < m_NumBans; i++)
|
||||
{
|
||||
if(net_addr_comp(&m_aBans[i].m_Address, &Addr) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Addr.port = 0;
|
||||
for(int i = 0; i < m_NumBans; i++)
|
||||
{
|
||||
if(net_addr_comp(&m_aBans[i].m_Address, &Addr) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConAddBan(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
if(m_NumBans == MAX_BANS)
|
||||
{
|
||||
dbg_msg("mastersrv", "error: banlist is full");
|
||||
return;
|
||||
}
|
||||
|
||||
if(net_addr_from_str(&m_aBans[m_NumBans].m_Address, pResult->GetString(0)) != 0)
|
||||
{
|
||||
dbg_msg("mastersrv", "error: invalid address");
|
||||
return;
|
||||
}
|
||||
|
||||
if(CheckBan(m_aBans[m_NumBans].m_Address))
|
||||
{
|
||||
dbg_msg("mastersrv", "duplicate ban: %s", pResult->GetString(0));
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_msg("mastersrv", "ban added: %s", pResult->GetString(0));
|
||||
m_NumBans++;
|
||||
}
|
||||
|
||||
void ReloadBans()
|
||||
{
|
||||
m_NumBans = 0;
|
||||
m_NetBan.UnbanAll();
|
||||
m_pConsole->ExecuteFile("master.cfg");
|
||||
}
|
||||
|
||||
|
@ -398,7 +350,7 @@ int main(int argc, const char **argv) // ignore_convention
|
|||
IStorage *pStorage = CreateStorage("Teeworlds", argc, argv);
|
||||
|
||||
m_pConsole = CreateConsole(CFGFLAG_MASTER);
|
||||
m_pConsole->Register("ban", "s", CFGFLAG_MASTER, ConAddBan, 0, "Ban IP from mastersrv");
|
||||
m_NetBan.Init(m_pConsole, pStorage);
|
||||
|
||||
bool RegisterFail = !pKernel->RegisterInterface(pStorage);
|
||||
RegisterFail |= !pKernel->RegisterInterface(m_pConsole);
|
||||
|
@ -418,7 +370,8 @@ int main(int argc, const char **argv) // ignore_convention
|
|||
while(m_NetOp.Recv(&Packet))
|
||||
{
|
||||
// check if the server is banned
|
||||
if(CheckBan(Packet.m_Address)) continue;
|
||||
if(m_NetBan.IsBanned(&Packet.m_Address, 0, 0))
|
||||
continue;
|
||||
|
||||
if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 &&
|
||||
mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0)
|
||||
|
@ -519,7 +472,8 @@ int main(int argc, const char **argv) // ignore_convention
|
|||
while(m_NetChecker.Recv(&Packet))
|
||||
{
|
||||
// check if the server is banned
|
||||
if(CheckBan(Packet.m_Address)) continue;
|
||||
if(m_NetBan.IsBanned(&Packet.m_Address, 0, 0))
|
||||
continue;
|
||||
|
||||
if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) &&
|
||||
mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0)
|
||||
|
|
|
@ -129,7 +129,7 @@ void Run(int Port, NETADDR Dest)
|
|||
if(m_ConfigLog)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&From, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&From, aAddrStr, sizeof(aAddrStr), true);
|
||||
dbg_msg("crapnet", "<< %08d %s (%d)", p->m_ID, aAddrStr, p->m_DataSize);
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ void Run(int Port, NETADDR Dest)
|
|||
if(m_ConfigLog)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr));
|
||||
net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr), true);
|
||||
dbg_msg("crapnet", ">> %08d %s (%d) %s", p->m_ID, aAddrStr, p->m_DataSize, aFlags);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ static int Run()
|
|||
int64 NextHeartBeat = 0;
|
||||
NETADDR BindAddr = {NETTYPE_IPV4, {0},0};
|
||||
|
||||
if(!pNet->Open(BindAddr, 0, 0, 0))
|
||||
if(!pNet->Open(BindAddr, 0, 0, 0, 0))
|
||||
return 0;
|
||||
|
||||
while(1)
|
||||
|
|
86
src/tools/tileset_borderadd.cpp
Normal file
86
src/tools/tileset_borderadd.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* (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. */
|
||||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
#include <engine/external/pnglite/pnglite.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char r, g, b, a;
|
||||
} CPixel;
|
||||
|
||||
static void TilesetBorderadd(int w, int h, CPixel *pSrc, CPixel *pDest)
|
||||
{
|
||||
int TileW = w/16;
|
||||
int TileH = h/16;
|
||||
|
||||
for(int tx = 0; tx < 16; tx++)
|
||||
{
|
||||
for(int ty = 0; ty < 16; ty++)
|
||||
{
|
||||
for(int x = 0; x < TileW + 4; x++)
|
||||
{
|
||||
for(int y = 0; y < TileH + 4; y++)
|
||||
{
|
||||
int SourceX = tx * TileW + clamp(x - 2, 0, TileW - 1);
|
||||
int SourceY = ty * TileH + clamp(y - 2, 0, TileH - 1);
|
||||
int DestX = tx * (TileW + 4) + x;
|
||||
int DestY = ty * (TileH + 4) + y;
|
||||
|
||||
int SourceI = SourceY * w + SourceX;
|
||||
int DestI = DestY * (w + 16 * 4) + DestX;
|
||||
|
||||
pDest[DestI] = pSrc[SourceI];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FixFile(const char *pFileName)
|
||||
{
|
||||
png_t Png;
|
||||
CPixel *pBuffer[2] = {0,0};
|
||||
|
||||
png_init(0, 0);
|
||||
png_open_file(&Png, pFileName);
|
||||
|
||||
if(Png.color_type != PNG_TRUECOLOR_ALPHA)
|
||||
{
|
||||
dbg_msg("tileset_borderadd", "%s: not an RGBA image", pFileName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w = Png.width;
|
||||
int h = Png.height;
|
||||
|
||||
pBuffer[0] = (CPixel*)mem_alloc(w*h*sizeof(CPixel), 1);
|
||||
pBuffer[1] = (CPixel*)mem_alloc((w+16*4)*(h+16*4)*sizeof(CPixel), 1);
|
||||
png_get_data(&Png, (unsigned char *)pBuffer[0]);
|
||||
png_close_file(&Png);
|
||||
|
||||
TilesetBorderadd(w, h, pBuffer[0], pBuffer[1]);
|
||||
|
||||
// save here
|
||||
png_open_file_write(&Png, pFileName);
|
||||
png_set_data(&Png, w + 16 * 4, h + 16 * 4, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]);
|
||||
png_close_file(&Png);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
dbg_logger_stdout();
|
||||
if(argc == 1)
|
||||
{
|
||||
dbg_msg("Usage", "%s FILE1 [ FILE2... ]", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
FixFile(argv[i]);
|
||||
return 0;
|
||||
}
|
86
src/tools/tileset_borderrem.cpp
Normal file
86
src/tools/tileset_borderrem.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* (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. */
|
||||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
#include <engine/external/pnglite/pnglite.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char r, g, b, a;
|
||||
} CPixel;
|
||||
|
||||
static void TilesetBorderrem(int w, int h, CPixel *pSrc, CPixel *pDest)
|
||||
{
|
||||
int TileW = w/16;
|
||||
int TileH = h/16;
|
||||
|
||||
for(int tx = 0; tx < 16; tx++)
|
||||
{
|
||||
for(int ty = 0; ty < 16; ty++)
|
||||
{
|
||||
for(int x = 0; x < TileW - 4; x++)
|
||||
{
|
||||
for(int y = 0; y < TileH - 4; y++)
|
||||
{
|
||||
int SourceX = tx * TileW + x + 2;
|
||||
int SourceY = ty * TileH + y + 2;
|
||||
int DestX = tx * (TileW - 4) + x;
|
||||
int DestY = ty * (TileH - 4) + y;
|
||||
|
||||
int SourceI = SourceY * w + SourceX;
|
||||
int DestI = DestY * (w - 16 * 4) + DestX;
|
||||
|
||||
pDest[DestI] = pSrc[SourceI];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FixFile(const char *pFileName)
|
||||
{
|
||||
png_t Png;
|
||||
CPixel *pBuffer[2] = {0,0};
|
||||
|
||||
png_init(0, 0);
|
||||
png_open_file(&Png, pFileName);
|
||||
|
||||
if(Png.color_type != PNG_TRUECOLOR_ALPHA)
|
||||
{
|
||||
dbg_msg("tileset_borderrem", "%s: not an RGBA image", pFileName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w = Png.width;
|
||||
int h = Png.height;
|
||||
|
||||
pBuffer[0] = (CPixel*)mem_alloc(w*h*sizeof(CPixel), 1);
|
||||
pBuffer[1] = (CPixel*)mem_alloc((w-16*4)*(h-16*4)*sizeof(CPixel), 1);
|
||||
png_get_data(&Png, (unsigned char *)pBuffer[0]);
|
||||
png_close_file(&Png);
|
||||
|
||||
TilesetBorderrem(w, h, pBuffer[0], pBuffer[1]);
|
||||
|
||||
// save here
|
||||
png_open_file_write(&Png, pFileName);
|
||||
png_set_data(&Png, w - 16 * 4, h - 16 * 4, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]);
|
||||
png_close_file(&Png);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
dbg_logger_stdout();
|
||||
if(argc == 1)
|
||||
{
|
||||
dbg_msg("Usage", "%s FILE1 [ FILE2... ]", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
FixFile(argv[i]);
|
||||
return 0;
|
||||
}
|
78
src/tools/tileset_borderset.cpp
Normal file
78
src/tools/tileset_borderset.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* (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. */
|
||||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
#include <engine/external/pnglite/pnglite.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char r, g, b, a;
|
||||
} CPixel;
|
||||
|
||||
static void TilesetBorderset(int w, int h, CPixel *pSrc, CPixel *pDest)
|
||||
{
|
||||
int TileW = w/16;
|
||||
int TileH = h/16;
|
||||
|
||||
for(int tx = 0; tx < 16; tx++)
|
||||
{
|
||||
for(int ty = 0; ty < 16; ty++)
|
||||
{
|
||||
for(int x = 0; x < TileW; x++)
|
||||
{
|
||||
for(int y = 0; y < TileH; y++)
|
||||
{
|
||||
#define TILE_INDEX(tx_, ty_, x_, y_) (((ty_) * TileH + (y_)) * w + (tx_) * TileW + (x_))
|
||||
pDest[TILE_INDEX(tx, ty, x, y)] = pSrc[TILE_INDEX(tx, ty, clamp(x, 2, TileW - 3), clamp(y, 2, TileH - 3))];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FixFile(const char *pFileName)
|
||||
{
|
||||
png_t Png;
|
||||
CPixel *pBuffer[2] = {0,0};
|
||||
|
||||
png_init(0, 0);
|
||||
png_open_file(&Png, pFileName);
|
||||
|
||||
if(Png.color_type != PNG_TRUECOLOR_ALPHA)
|
||||
{
|
||||
dbg_msg("tileset_borderset", "%s: not an RGBA image", pFileName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w = Png.width;
|
||||
int h = Png.height;
|
||||
|
||||
pBuffer[0] = (CPixel*)mem_alloc(w*h*sizeof(CPixel), 1);
|
||||
pBuffer[1] = (CPixel*)mem_alloc(w*h*sizeof(CPixel), 1);
|
||||
png_get_data(&Png, (unsigned char *)pBuffer[0]);
|
||||
png_close_file(&Png);
|
||||
|
||||
TilesetBorderset(w, h, pBuffer[0], pBuffer[1]);
|
||||
|
||||
// save here
|
||||
png_open_file_write(&Png, pFileName);
|
||||
png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]);
|
||||
png_close_file(&Png);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
dbg_logger_stdout();
|
||||
if(argc == 1)
|
||||
{
|
||||
dbg_msg("Usage", "%s FILE1 [ FILE2... ]", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
FixFile(argv[i]);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue