2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2008-08-14 17:19:13 +00:00
|
|
|
#include <base/system.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/shared/network.h>
|
2011-01-22 18:54:05 +00:00
|
|
|
#include <engine/shared/config.h>
|
|
|
|
#include <engine/console.h>
|
|
|
|
#include <engine/storage.h>
|
|
|
|
#include <engine/kernel.h>
|
2007-07-21 18:07:27 +00:00
|
|
|
|
|
|
|
#include "mastersrv.h"
|
|
|
|
|
|
|
|
enum {
|
|
|
|
MTU = 1400,
|
2011-04-08 21:56:15 +00:00
|
|
|
MAX_SERVERS_PER_PACKET=77,
|
2008-11-15 13:29:56 +00:00
|
|
|
MAX_PACKETS=16,
|
|
|
|
MAX_SERVERS=MAX_SERVERS_PER_PACKET*MAX_PACKETS,
|
2011-01-22 18:54:05 +00:00
|
|
|
MAX_BANS=128,
|
2007-07-21 18:07:27 +00:00
|
|
|
EXPIRE_TIME = 90
|
|
|
|
};
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
struct CCheckServer
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
enum ServerType m_Type;
|
2010-05-29 07:25:38 +00:00
|
|
|
NETADDR m_Address;
|
|
|
|
NETADDR m_AltAddress;
|
|
|
|
int m_TryCount;
|
|
|
|
int64 m_TryTime;
|
|
|
|
};
|
2007-07-21 21:28:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static CCheckServer m_aCheckServers[MAX_SERVERS];
|
|
|
|
static int m_NumCheckServers = 0;
|
2008-11-15 13:29:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
struct CServerEntry
|
2008-11-15 13:29:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
enum ServerType m_Type;
|
2010-05-29 07:25:38 +00:00
|
|
|
NETADDR m_Address;
|
|
|
|
int64 m_Expire;
|
|
|
|
};
|
|
|
|
|
|
|
|
static CServerEntry m_aServers[MAX_SERVERS];
|
|
|
|
static int m_NumServers = 0;
|
2008-11-15 13:29:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
struct CPacketData
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_Size;
|
2008-11-15 13:29:56 +00:00
|
|
|
struct {
|
2010-05-29 07:25:38 +00:00
|
|
|
unsigned char m_aHeader[sizeof(SERVERBROWSE_LIST)];
|
2011-03-30 10:08:33 +00:00
|
|
|
CMastersrvAddr m_aServers[MAX_SERVERS_PER_PACKET];
|
2010-05-29 07:25:38 +00:00
|
|
|
} m_Data;
|
|
|
|
};
|
2008-02-10 21:54:52 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CPacketData m_aPackets[MAX_PACKETS];
|
|
|
|
static int m_NumPackets = 0;
|
|
|
|
|
2011-04-01 23:56:16 +00:00
|
|
|
// legacy code
|
|
|
|
struct CPacketDataLegacy
|
|
|
|
{
|
|
|
|
int m_Size;
|
|
|
|
struct {
|
|
|
|
unsigned char m_aHeader[sizeof(SERVERBROWSE_LIST_LEGACY)];
|
|
|
|
CMastersrvAddrLegacy m_aServers[MAX_SERVERS_PER_PACKET];
|
|
|
|
} m_Data;
|
|
|
|
};
|
|
|
|
|
|
|
|
CPacketDataLegacy m_aPacketsLegacy[MAX_PACKETS];
|
|
|
|
static int m_NumPacketsLegacy = 0;
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
struct CCountPacketData
|
2008-02-10 21:54:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
unsigned char m_Header[sizeof(SERVERBROWSE_COUNT)];
|
|
|
|
unsigned char m_High;
|
|
|
|
unsigned char m_Low;
|
|
|
|
};
|
|
|
|
|
|
|
|
static CCountPacketData m_CountData;
|
2011-04-01 23:56:16 +00:00
|
|
|
static CCountPacketData m_CountDataLegacy;
|
2008-02-10 21:54:52 +00:00
|
|
|
|
2011-01-22 18:54:05 +00:00
|
|
|
|
|
|
|
struct CBanEntry
|
|
|
|
{
|
|
|
|
NETADDR m_Address;
|
|
|
|
int64 m_Expire;
|
|
|
|
};
|
|
|
|
|
|
|
|
static CBanEntry m_aBans[MAX_BANS];
|
|
|
|
static int m_NumBans = 0;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static CNetClient m_NetChecker; // NAT/FW checker
|
|
|
|
static CNetClient m_NetOp; // main
|
2007-07-21 21:28:56 +00:00
|
|
|
|
2011-01-22 18:54:05 +00:00
|
|
|
IConsole *m_pConsole;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void BuildPackets()
|
2008-11-15 13:29:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CServerEntry *pCurrent = &m_aServers[0];
|
|
|
|
int ServersLeft = m_NumServers;
|
|
|
|
m_NumPackets = 0;
|
2011-04-01 23:56:16 +00:00
|
|
|
m_NumPacketsLegacy = 0;
|
|
|
|
int PacketIndex = 0;
|
|
|
|
int PacketIndexLegacy = 0;
|
|
|
|
while(ServersLeft-- && (m_NumPackets + m_NumPacketsLegacy) < MAX_PACKETS)
|
2008-11-15 13:29:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
if(pCurrent->m_Type == SERVERTYPE_NORMAL)
|
2008-11-15 13:29:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
if(PacketIndex % MAX_SERVERS_PER_PACKET == 0)
|
2011-04-01 23:56:16 +00:00
|
|
|
{
|
|
|
|
PacketIndex = 0;
|
|
|
|
m_NumPackets++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy header
|
2011-04-02 14:14:09 +00:00
|
|
|
mem_copy(m_aPackets[m_NumPackets-1].m_Data.m_aHeader, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
|
2011-04-01 23:56:16 +00:00
|
|
|
|
|
|
|
// copy server addresses
|
2011-04-08 21:56:15 +00:00
|
|
|
if(pCurrent->m_Address.type == NETTYPE_IPV6)
|
|
|
|
{
|
|
|
|
mem_copy(m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp, pCurrent->m_Address.ip,
|
|
|
|
sizeof(m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static char IPV4Mapping[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
|
|
|
|
|
|
|
|
mem_copy(m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp, IPV4Mapping, sizeof(IPV4Mapping));
|
|
|
|
m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp[12] = pCurrent->m_Address.ip[0];
|
|
|
|
m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp[13] = pCurrent->m_Address.ip[1];
|
|
|
|
m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp[14] = pCurrent->m_Address.ip[2];
|
|
|
|
m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aIp[15] = pCurrent->m_Address.ip[3];
|
|
|
|
}
|
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aPort[0] = (pCurrent->m_Address.port>>8)&0xff;
|
|
|
|
m_aPackets[m_NumPackets-1].m_Data.m_aServers[PacketIndex].m_aPort[1] = pCurrent->m_Address.port&0xff;
|
2011-04-01 23:56:16 +00:00
|
|
|
|
|
|
|
PacketIndex++;
|
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
m_aPackets[m_NumPackets-1].m_Size = sizeof(SERVERBROWSE_LIST) + sizeof(CMastersrvAddr)*PacketIndex;
|
|
|
|
|
|
|
|
pCurrent++;
|
2008-11-15 13:29:56 +00:00
|
|
|
}
|
2011-04-02 14:14:09 +00:00
|
|
|
else if(pCurrent->m_Type == SERVERTYPE_LEGACY)
|
2011-04-01 23:56:16 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
if(PacketIndexLegacy % MAX_SERVERS_PER_PACKET == 0)
|
2011-04-01 23:56:16 +00:00
|
|
|
{
|
|
|
|
PacketIndexLegacy = 0;
|
|
|
|
m_NumPacketsLegacy++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy header
|
2011-04-02 14:14:09 +00:00
|
|
|
mem_copy(m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aHeader, SERVERBROWSE_LIST_LEGACY, sizeof(SERVERBROWSE_LIST_LEGACY));
|
2011-04-01 23:56:16 +00:00
|
|
|
|
|
|
|
// copy server addresses
|
2011-04-02 14:14:09 +00:00
|
|
|
mem_copy(m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aServers[PacketIndexLegacy].m_aIp, pCurrent->m_Address.ip,
|
|
|
|
sizeof(m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aServers[PacketIndexLegacy].m_aIp));
|
2011-04-01 23:56:16 +00:00
|
|
|
// 0.5 has the port in little endian on the network
|
2011-04-02 14:14:09 +00:00
|
|
|
m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aServers[PacketIndexLegacy].m_aPort[0] = pCurrent->m_Address.port&0xff;
|
|
|
|
m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aServers[PacketIndexLegacy].m_aPort[1] = (pCurrent->m_Address.port>>8)&0xff;
|
2011-04-01 23:56:16 +00:00
|
|
|
|
|
|
|
PacketIndexLegacy++;
|
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Size = sizeof(SERVERBROWSE_LIST_LEGACY) + sizeof(CMastersrvAddrLegacy)*PacketIndexLegacy;
|
2011-04-01 23:56:16 +00:00
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
pCurrent++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pCurrent = m_aServers[m_NumServers-1];
|
|
|
|
m_NumServers--;
|
|
|
|
dbg_msg("mastersrv", "error: server of invalid type, dropping it");
|
|
|
|
}
|
2008-11-15 13:29:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void SendOk(NETADDR *pAddr)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = *pAddr;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
p.m_DataSize = sizeof(SERVERBROWSE_FWOK);
|
|
|
|
p.m_pData = SERVERBROWSE_FWOK;
|
2008-02-10 21:54:52 +00:00
|
|
|
|
|
|
|
// send on both to be sure
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NetChecker.Send(&p);
|
|
|
|
m_NetOp.Send(&p);
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void SendError(NETADDR *pAddr)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = *pAddr;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
p.m_DataSize = sizeof(SERVERBROWSE_FWERROR);
|
|
|
|
p.m_pData = SERVERBROWSE_FWERROR;
|
|
|
|
m_NetOp.Send(&p);
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void SendCheck(NETADDR *pAddr)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = *pAddr;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
p.m_DataSize = sizeof(SERVERBROWSE_FWCHECK);
|
|
|
|
p.m_pData = SERVERBROWSE_FWCHECK;
|
|
|
|
m_NetChecker.Send(&p);
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
|
|
|
// add server
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_NumCheckServers == MAX_SERVERS)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "error: mastersrv is full");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-30 10:08:33 +00:00
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr));
|
|
|
|
char aAltAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(pAlt, aAltAddrStr, sizeof(aAltAddrStr));
|
|
|
|
dbg_msg("mastersrv", "checking: %s (%s)", aAddrStr, aAltAddrStr);
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aCheckServers[m_NumCheckServers].m_Address = *pInfo;
|
|
|
|
m_aCheckServers[m_NumCheckServers].m_AltAddress = *pAlt;
|
|
|
|
m_aCheckServers[m_NumCheckServers].m_TryCount = 0;
|
|
|
|
m_aCheckServers[m_NumCheckServers].m_TryTime = 0;
|
2011-04-02 14:14:09 +00:00
|
|
|
m_aCheckServers[m_NumCheckServers].m_Type = Type;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NumCheckServers++;
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
2007-07-21 18:07:27 +00:00
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
void AddServer(NETADDR *pInfo, ServerType Type)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
|
|
|
// see if server already exists in list
|
2011-03-30 10:08:33 +00:00
|
|
|
for(int i = 0; i < m_NumServers; i++)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2011-03-30 10:08:33 +00:00
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr));
|
|
|
|
dbg_msg("mastersrv", "updated: %s", aAddrStr);
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aServers[i].m_Expire = time_get()+time_freq()*EXPIRE_TIME;
|
2007-07-21 18:07:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add server
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_NumServers == MAX_SERVERS)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "error: mastersrv is full");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-30 10:08:33 +00:00
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr));
|
|
|
|
dbg_msg("mastersrv", "added: %s", aAddrStr);
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aServers[m_NumServers].m_Address = *pInfo;
|
|
|
|
m_aServers[m_NumServers].m_Expire = time_get()+time_freq()*EXPIRE_TIME;
|
2011-04-02 14:14:09 +00:00
|
|
|
m_aServers[m_NumServers].m_Type = Type;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NumServers++;
|
2007-07-21 18:07:27 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void UpdateServers()
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int64 Now = time_get();
|
|
|
|
int64 Freq = time_freq();
|
|
|
|
for(int i = 0; i < m_NumCheckServers; i++)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Now > m_aCheckServers[i].m_TryTime+Freq)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_aCheckServers[i].m_TryCount == 10)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2011-03-30 10:08:33 +00:00
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(&m_aCheckServers[i].m_Address, aAddrStr, sizeof(aAddrStr));
|
|
|
|
char aAltAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(&m_aCheckServers[i].m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr));
|
|
|
|
dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr);
|
2007-07-21 21:28:56 +00:00
|
|
|
|
|
|
|
// FAIL!!
|
2010-05-29 07:25:38 +00:00
|
|
|
SendError(&m_aCheckServers[i].m_Address);
|
|
|
|
m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers-1];
|
|
|
|
m_NumCheckServers--;
|
2007-07-21 21:28:56 +00:00
|
|
|
i--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aCheckServers[i].m_TryCount++;
|
|
|
|
m_aCheckServers[i].m_TryTime = Now;
|
|
|
|
if(m_aCheckServers[i].m_TryCount&1)
|
|
|
|
SendCheck(&m_aCheckServers[i].m_Address);
|
2007-12-13 20:08:08 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
SendCheck(&m_aCheckServers[i].m_AltAddress);
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void PurgeServers()
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int64 Now = time_get();
|
2007-07-21 18:07:27 +00:00
|
|
|
int i = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
while(i < m_NumServers)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_aServers[i].m_Expire < Now)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
|
|
|
// remove server
|
2011-03-30 10:08:33 +00:00
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
|
|
net_addr_str(&m_aServers[i].m_Address, aAddrStr, sizeof(aAddrStr));
|
|
|
|
dbg_msg("mastersrv", "expired: %s", aAddrStr);
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aServers[i] = m_aServers[m_NumServers-1];
|
|
|
|
m_NumServers--;
|
2007-07-21 18:07:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-22 21:50:19 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-01-22 18:54:05 +00:00
|
|
|
void ConAddBan(IConsole::IResult *pResult, void *pUser)
|
|
|
|
{
|
|
|
|
if(m_NumBans == MAX_BANS)
|
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "error: banlist is full");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-30 10:08:33 +00:00
|
|
|
if(net_addr_from_str(&m_aBans[m_NumBans].m_Address, pResult->GetString(0)) != 0)
|
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "error: invalid address");
|
|
|
|
return;
|
|
|
|
}
|
2011-01-22 18:54:05 +00:00
|
|
|
|
2011-01-22 21:50:19 +00:00
|
|
|
if(CheckBan(m_aBans[m_NumBans].m_Address))
|
2011-01-22 18:54:05 +00:00
|
|
|
{
|
2011-03-30 10:08:33 +00:00
|
|
|
dbg_msg("mastersrv", "duplicate ban: %s", pResult->GetString(0));
|
2011-01-22 21:50:19 +00:00
|
|
|
return;
|
2011-01-22 18:54:05 +00:00
|
|
|
}
|
|
|
|
|
2011-03-30 10:08:33 +00:00
|
|
|
dbg_msg("mastersrv", "ban added: %s", pResult->GetString(0));
|
2011-01-22 18:54:05 +00:00
|
|
|
m_NumBans++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReloadBans()
|
|
|
|
{
|
|
|
|
m_NumBans = 0;
|
|
|
|
m_pConsole->ExecuteFile("master.cfg");
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, const char **argv) // ignore_convention
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2011-01-22 18:54:05 +00:00
|
|
|
int64 LastBuild = 0, LastBanReload = 0;
|
2011-04-02 14:14:09 +00:00
|
|
|
ServerType Type = SERVERTYPE_INVALID;
|
2010-05-29 07:25:38 +00:00
|
|
|
NETADDR BindAddr;
|
2008-10-01 18:34:43 +00:00
|
|
|
|
|
|
|
dbg_logger_stdout();
|
|
|
|
net_init();
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_zero(&BindAddr, sizeof(BindAddr));
|
2011-03-30 10:08:33 +00:00
|
|
|
BindAddr.type = NETTYPE_ALL;
|
2010-05-29 07:25:38 +00:00
|
|
|
BindAddr.port = MASTERSERVER_PORT;
|
|
|
|
|
2011-03-30 10:08:33 +00:00
|
|
|
if(!m_NetOp.Open(BindAddr, 0))
|
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "couldn't start network (op)");
|
|
|
|
return -1;
|
|
|
|
}
|
2007-08-05 14:19:13 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
BindAddr.port = MASTERSERVER_PORT+1;
|
2011-03-30 10:08:33 +00:00
|
|
|
if(!m_NetChecker.Open(BindAddr, 0))
|
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "couldn't start network (checker)");
|
|
|
|
return -1;
|
|
|
|
}
|
2007-07-21 18:07:27 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
|
2011-04-01 23:56:16 +00:00
|
|
|
mem_copy(m_CountDataLegacy.m_Header, SERVERBROWSE_COUNT_LEGACY, sizeof(SERVERBROWSE_COUNT_LEGACY));
|
2011-01-22 18:54:05 +00:00
|
|
|
|
|
|
|
IKernel *pKernel = IKernel::Create();
|
|
|
|
IStorage *pStorage = CreateStorage("Teeworlds", argc, argv);
|
|
|
|
|
|
|
|
m_pConsole = CreateConsole(CFGFLAG_MASTER);
|
|
|
|
m_pConsole->Register("ban", "s", CFGFLAG_MASTER, ConAddBan, 0, "Ban IP from mastersrv");
|
|
|
|
|
|
|
|
bool RegisterFail = !pKernel->RegisterInterface(pStorage);
|
|
|
|
RegisterFail |= !pKernel->RegisterInterface(m_pConsole);
|
|
|
|
|
|
|
|
if(RegisterFail)
|
|
|
|
return -1;
|
2008-02-10 21:54:52 +00:00
|
|
|
|
2007-07-21 18:07:27 +00:00
|
|
|
dbg_msg("mastersrv", "started");
|
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NetOp.Update();
|
|
|
|
m_NetChecker.Update();
|
2007-07-21 18:07:27 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// process m_aPackets
|
|
|
|
CNetChunk Packet;
|
|
|
|
while(m_NetOp.Recv(&Packet))
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2011-01-22 18:54:05 +00:00
|
|
|
// check if the server is banned
|
|
|
|
if(CheckBan(Packet.m_Address)) continue;
|
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0)
|
|
|
|
{
|
|
|
|
NETADDR Alt;
|
|
|
|
unsigned char *d = (unsigned char *)Packet.m_pData;
|
|
|
|
Alt = Packet.m_Address;
|
|
|
|
Alt.port =
|
|
|
|
(d[sizeof(SERVERBROWSE_HEARTBEAT)]<<8) |
|
|
|
|
d[sizeof(SERVERBROWSE_HEARTBEAT)+1];
|
|
|
|
|
|
|
|
// add it
|
|
|
|
AddCheckserver(&Packet.m_Address, &Alt, SERVERTYPE_NORMAL);
|
|
|
|
}
|
|
|
|
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT_LEGACY)+2 &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT_LEGACY, sizeof(SERVERBROWSE_HEARTBEAT_LEGACY)) == 0)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETADDR Alt;
|
|
|
|
unsigned char *d = (unsigned char *)Packet.m_pData;
|
|
|
|
Alt = Packet.m_Address;
|
|
|
|
Alt.port =
|
2007-12-13 20:07:23 +00:00
|
|
|
(d[sizeof(SERVERBROWSE_HEARTBEAT)]<<8) |
|
|
|
|
d[sizeof(SERVERBROWSE_HEARTBEAT)+1];
|
|
|
|
|
2007-07-21 18:07:27 +00:00
|
|
|
// add it
|
2011-04-02 14:14:09 +00:00
|
|
|
AddCheckserver(&Packet.m_Address, &Alt, SERVERTYPE_LEGACY);
|
2007-07-21 18:07:27 +00:00
|
|
|
}
|
2011-04-02 14:14:09 +00:00
|
|
|
|
|
|
|
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETCOUNT) &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_GETCOUNT, sizeof(SERVERBROWSE_GETCOUNT)) == 0)
|
|
|
|
{
|
|
|
|
dbg_msg("mastersrv", "count requested, responding with %d", m_NumServers);
|
|
|
|
|
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = Packet.m_Address;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
p.m_DataSize = sizeof(m_CountData);
|
|
|
|
p.m_pData = &m_CountData;
|
|
|
|
m_CountData.m_High = (m_NumServers>>8)&0xff;
|
|
|
|
m_CountData.m_Low = m_NumServers&0xff;
|
|
|
|
m_NetOp.Send(&p);
|
|
|
|
}
|
|
|
|
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETCOUNT_LEGACY) &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_GETCOUNT_LEGACY, sizeof(SERVERBROWSE_GETCOUNT_LEGACY)) == 0)
|
2008-02-10 21:54:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
dbg_msg("mastersrv", "count requested, responding with %d", m_NumServers);
|
2008-02-10 21:54:52 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = Packet.m_Address;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
p.m_DataSize = sizeof(m_CountData);
|
2011-04-02 14:14:09 +00:00
|
|
|
p.m_pData = &m_CountDataLegacy;
|
|
|
|
m_CountDataLegacy.m_High = (m_NumServers>>8)&0xff;
|
|
|
|
m_CountDataLegacy.m_Low = m_NumServers&0xff;
|
|
|
|
m_NetOp.Send(&p);
|
|
|
|
}
|
|
|
|
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETLIST) &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0)
|
|
|
|
{
|
|
|
|
// someone requested the list
|
|
|
|
dbg_msg("mastersrv", "requested, responding with %d m_aServers", m_NumServers);
|
|
|
|
|
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = Packet.m_Address;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
|
|
|
|
for(int i = 0; i < m_NumPackets; i++)
|
2011-04-01 23:56:16 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
p.m_DataSize = m_aPackets[i].m_Size;
|
|
|
|
p.m_pData = &m_aPackets[i].m_Data;
|
|
|
|
m_NetOp.Send(&p);
|
2011-04-01 23:56:16 +00:00
|
|
|
}
|
2008-02-10 21:54:52 +00:00
|
|
|
}
|
2011-04-02 14:14:09 +00:00
|
|
|
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETLIST_LEGACY) &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_GETLIST_LEGACY, sizeof(SERVERBROWSE_GETLIST_LEGACY)) == 0)
|
2007-07-21 18:07:27 +00:00
|
|
|
{
|
|
|
|
// someone requested the list
|
2010-05-29 07:25:38 +00:00
|
|
|
dbg_msg("mastersrv", "requested, responding with %d m_aServers", m_NumServers);
|
2011-04-01 23:56:16 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetChunk p;
|
|
|
|
p.m_ClientID = -1;
|
|
|
|
p.m_Address = Packet.m_Address;
|
|
|
|
p.m_Flags = NETSENDFLAG_CONNLESS;
|
2008-11-15 13:29:56 +00:00
|
|
|
|
2011-04-02 14:14:09 +00:00
|
|
|
for(int i = 0; i < m_NumPacketsLegacy; i++)
|
2008-11-15 13:29:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
p.m_DataSize = m_aPacketsLegacy[i].m_Size;
|
|
|
|
p.m_pData = &m_aPacketsLegacy[i].m_Data;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NetOp.Send(&p);
|
2008-11-15 13:29:56 +00:00
|
|
|
}
|
2007-07-21 18:07:27 +00:00
|
|
|
}
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
2007-07-21 18:07:27 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// process m_aPackets
|
|
|
|
while(m_NetChecker.Recv(&Packet))
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2011-01-22 18:54:05 +00:00
|
|
|
// check if the server is banned
|
|
|
|
if(CheckBan(Packet.m_Address)) continue;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) &&
|
|
|
|
mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
Type = SERVERTYPE_INVALID;
|
2007-07-21 21:28:56 +00:00
|
|
|
// remove it from checking
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_NumCheckServers; i++)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(net_addr_comp(&m_aCheckServers[i].m_Address, &Packet.m_Address) == 0 ||
|
|
|
|
net_addr_comp(&m_aCheckServers[i].m_AltAddress, &Packet.m_Address) == 0)
|
2007-07-21 21:28:56 +00:00
|
|
|
{
|
2011-04-02 14:14:09 +00:00
|
|
|
Type = m_aCheckServers[i].m_Type;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NumCheckServers--;
|
|
|
|
m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers];
|
2007-07-21 21:28:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-04-02 14:14:09 +00:00
|
|
|
|
|
|
|
// drops servers that were not in the CheckServers list
|
|
|
|
if(Type == SERVERTYPE_INVALID)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
AddServer(&Packet.m_Address, Type);
|
2010-05-29 07:25:38 +00:00
|
|
|
SendOk(&Packet.m_Address);
|
2007-07-21 21:28:56 +00:00
|
|
|
}
|
2007-07-21 18:07:27 +00:00
|
|
|
}
|
|
|
|
|
2011-01-22 18:54:05 +00:00
|
|
|
if(time_get()-LastBanReload > time_freq()*300)
|
|
|
|
{
|
|
|
|
LastBanReload = time_get();
|
|
|
|
|
|
|
|
ReloadBans();
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(time_get()-LastBuild > time_freq()*5)
|
2008-11-15 13:29:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
LastBuild = time_get();
|
2008-11-15 13:29:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
PurgeServers();
|
|
|
|
UpdateServers();
|
|
|
|
BuildPackets();
|
2008-11-15 13:29:56 +00:00
|
|
|
}
|
2007-07-21 18:07:27 +00:00
|
|
|
|
|
|
|
// be nice to the CPU
|
|
|
|
thread_sleep(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|