Added external linkage instead of static const

This commit is contained in:
Chairn 2022-03-21 09:01:56 +01:00
parent 04f51a55bb
commit 21e64cbdcb
20 changed files with 25879 additions and 25820 deletions

View file

@ -1764,7 +1764,10 @@ set(GAME_GENERATED_SHARED
src/game/generated/protocol7.h
src/game/generated/protocolglue.h
)
set_src(MASTERSRV_SHARED GLOB src/mastersrv
mastersrv.cpp
mastersrv.h
)
set(DEPS ${DEP_JSON} ${DEP_MD5} ${ZLIB_DEP})
# Libraries
@ -1782,7 +1785,8 @@ set(LIBS
# Targets
add_library(engine-shared EXCLUDE_FROM_ALL OBJECT ${ENGINE_INTERFACE} ${ENGINE_SHARED} ${ENGINE_UUID_SHARED} ${BASE})
add_library(game-shared EXCLUDE_FROM_ALL OBJECT ${GAME_SHARED} ${GAME_GENERATED_SHARED})
list(APPEND TARGETS_OWN engine-shared game-shared)
add_library(mastersrv-shared EXCLUDE_FROM_ALL OBJECT ${MASTERSRV_SHARED})
list(APPEND TARGETS_OWN engine-shared game-shared mastersrv-shared)
if(DISCORD AND NOT DISCORD_DYNAMIC)
add_library(discord-shared SHARED IMPORTED)
@ -2064,6 +2068,7 @@ if(CLIENT)
${DEPS_CLIENT}
$<TARGET_OBJECTS:engine-shared>
$<TARGET_OBJECTS:game-shared>
$<TARGET_OBJECTS:mastersrv-shared>
)
else()
add_executable(${TARGET_CLIENT} WIN32
@ -2073,6 +2078,7 @@ if(CLIENT)
${DEPS_CLIENT}
$<TARGET_OBJECTS:engine-shared>
$<TARGET_OBJECTS:game-shared>
$<TARGET_OBJECTS:mastersrv-shared>
)
endif()
target_link_libraries(${TARGET_CLIENT} ${LIBS_CLIENT})
@ -2260,6 +2266,7 @@ if(SERVER)
${SERVER_ICON}
$<TARGET_OBJECTS:engine-shared>
$<TARGET_OBJECTS:game-shared>
$<TARGET_OBJECTS:mastersrv-shared>
)
target_link_libraries(${TARGET_SERVER} ${LIBS_SERVER})
list(APPEND TARGETS_OWN ${TARGET_SERVER})
@ -2280,13 +2287,14 @@ endif()
########################################################################
if(TOOLS)
set_src(MASTERSRV_SRC GLOB src/mastersrv mastersrv.cpp mastersrv.h)
set_src(MASTERSRV_SRC GLOB src/mastersrv main_mastersrv.cpp)
set_src(TWPING_SRC GLOB src/twping twping.cpp)
set(TARGET_MASTERSRV mastersrv)
set(TARGET_TWPING twping)
add_executable(${TARGET_MASTERSRV} EXCLUDE_FROM_ALL ${MASTERSRV_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
add_executable(${TARGET_MASTERSRV} EXCLUDE_FROM_ALL ${MASTERSRV_SRC} $<TARGET_OBJECTS:engine-shared> $<TARGET_OBJECTS:mastersrv-shared> ${DEPS})
add_executable(${TARGET_TWPING} EXCLUDE_FROM_ALL ${TWPING_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
target_link_libraries(${TARGET_MASTERSRV} ${LIBS})

View file

@ -3,6 +3,8 @@
#include "system.h"
const SHA256_DIGEST SHA256_ZEROED = {{0}};
static void digest_str(const unsigned char *digest, size_t digest_len, char *str, size_t max_len)
{
unsigned i;

View file

@ -31,8 +31,7 @@ void md5_str(MD5_DIGEST digest, char *str, size_t max_len);
int md5_from_str(MD5_DIGEST *out, const char *str);
int md5_comp(MD5_DIGEST digest1, MD5_DIGEST digest2);
static const SHA256_DIGEST SHA256_ZEROED = {{0}};
static const MD5_DIGEST MD5_ZEROED = {{0}};
extern const SHA256_DIGEST SHA256_ZEROED;
inline bool operator==(const SHA256_DIGEST &that, const SHA256_DIGEST &other)
{

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -13,16 +13,15 @@ enum
MAX_TIMELINE_MARKERS = 64
};
const double g_aSpeeds[] = {0.1, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 16.0, 20.0, 24.0, 28.0, 32.0, 40.0, 48.0, 56.0, 64.0};
constexpr int g_DemoSpeeds = 22;
extern const double g_aSpeeds[g_DemoSpeeds];
typedef bool (*DEMOFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
// TODO: Properly extend demo format using uuids
// "6be6da4a-cebd-380c-9b5b-1289c842d780"
// "demoitem-sha256@ddnet.tw"
static const CUuid SHA256_EXTENSION =
{{0x6b, 0xe6, 0xda, 0x4a, 0xce, 0xbd, 0x38, 0x0c,
0x9b, 0x5b, 0x12, 0x89, 0xc8, 0x42, 0xd7, 0x80}};
extern const CUuid SHA256_EXTENSION;
struct CDemoHeader
{

View file

@ -20,6 +20,11 @@
#include "network.h"
#include "snapshot.h"
const double g_aSpeeds[g_DemoSpeeds] = {0.1, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 16.0, 20.0, 24.0, 28.0, 32.0, 40.0, 48.0, 56.0, 64.0};
const CUuid SHA256_EXTENSION =
{{0x6b, 0xe6, 0xda, 0x4a, 0xce, 0xbd, 0x38, 0x0c,
0x9b, 0x5b, 0x12, 0x89, 0xc8, 0x42, 0xd7, 0x80}};
static const unsigned char s_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0};
static const unsigned char s_CurVersion = 6;
static const unsigned char s_OldVersion = 3;

View file

@ -6,6 +6,8 @@
#include "huffman.h"
#include "network.h"
const unsigned char SECURITY_TOKEN_MAGIC[4] = {'T', 'K', 'E', 'N'};
void CNetRecvUnpacker::Clear()
{
m_Valid = false;

View file

@ -96,7 +96,7 @@ typedef int SECURITY_TOKEN;
SECURITY_TOKEN ToSecurityToken(unsigned char *pData);
static const unsigned char SECURITY_TOKEN_MAGIC[] = {'T', 'K', 'E', 'N'};
extern const unsigned char SECURITY_TOKEN_MAGIC[4];
enum
{

View file

@ -14,6 +14,16 @@
#include <game/client/gameclient.h>
const char *const gs_aModEntitiesNames[] = {
"ddnet",
"ddrace",
"race",
"blockworlds",
"fng",
"vanilla",
"f-ddrace",
};
CMapImages::CMapImages() :
CMapImages(100)
{

View file

@ -29,14 +29,7 @@ enum EMapImageModType
MAP_IMAGE_MOD_TYPE_COUNT,
};
static const char *const gs_aModEntitiesNames[] = {
"ddnet",
"ddrace",
"race",
"blockworlds",
"fng",
"vanilla",
"f-ddrace"};
extern const char *const gs_aModEntitiesNames[];
class CMapImages : public CComponent
{

View file

@ -2077,9 +2077,9 @@ int CMenus::Render()
UI()->DoLabel(&Part, aBuffer, 12.8f, TEXTALIGN_LEFT);
if(IncDemoSpeed)
m_Speed = clamp(m_Speed + 1, 0, (int)(std::size(g_aSpeeds) - 1));
m_Speed = clamp(m_Speed + 1, 0, (int)(g_DemoSpeeds - 1));
else if(DecDemoSpeed)
m_Speed = clamp(m_Speed - 1, 0, (int)(std::size(g_aSpeeds) - 1));
m_Speed = clamp(m_Speed - 1, 0, (int)(g_DemoSpeeds - 1));
Part.VSplitLeft(207.0f, 0, &Part);
if(DoButton_CheckBox(&g_Config.m_ClVideoShowhud, Localize("Show ingame HUD"), g_Config.m_ClVideoShowhud, &Part))

View file

@ -5,8 +5,6 @@
#include <game/client/prediction/entity.h>
const int PickupPhysSize = 14;
class CPickup : public CEntity
{
public:

View file

@ -10,6 +10,8 @@
#include "character.h"
static constexpr int PickupPhysSize = 14;
CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int Number) :
CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP, vec2(0, 0), PickupPhysSize)
{

View file

@ -5,8 +5,6 @@
#include <game/server/entity.h>
const int PickupPhysSize = 14;
class CPickup : public CEntity
{
public:

View file

@ -0,0 +1,545 @@
/* (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/config.h>
#include <engine/console.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,
EXPIRE_TIME = 90
};
struct CCheckServer
{
enum ServerType m_Type;
NETADDR m_Address;
NETADDR m_AltAddress;
int m_TryCount;
int64_t m_TryTime;
};
static CCheckServer m_aCheckServers[MAX_SERVERS];
static int m_NumCheckServers = 0;
struct CServerEntry
{
enum ServerType m_Type;
NETADDR m_Address;
int64_t m_Expire;
};
static CServerEntry m_aServers[MAX_SERVERS];
static int m_NumServers = 0;
struct CPacketData
{
int m_Size;
struct
{
unsigned char m_aHeader[sizeof(SERVERBROWSE_LIST)];
CMastersrvAddr m_aServers[MAX_SERVERS_PER_PACKET];
} m_Data;
};
CPacketData m_aPackets[MAX_PACKETS];
static int m_NumPackets = 0;
// 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;
struct CCountPacketData
{
unsigned char m_Header[sizeof(SERVERBROWSE_COUNT)];
unsigned char m_High;
unsigned char m_Low;
};
static CCountPacketData m_CountData;
static CCountPacketData m_CountDataLegacy;
CNetBan m_NetBan;
static CNetClient m_NetChecker; // NAT/FW checker
static CNetClient m_NetOp; // main
IConsole *m_pConsole;
void BuildPackets()
{
CServerEntry *pCurrent = &m_aServers[0];
int ServersLeft = m_NumServers;
m_NumPackets = 0;
m_NumPacketsLegacy = 0;
int PacketIndex = 0;
int PacketIndexLegacy = 0;
while(ServersLeft-- && (m_NumPackets + m_NumPacketsLegacy) < MAX_PACKETS)
{
if(pCurrent->m_Type == SERVERTYPE_NORMAL)
{
if(PacketIndex % MAX_SERVERS_PER_PACKET == 0)
{
PacketIndex = 0;
m_NumPackets++;
}
// copy header
mem_copy(m_aPackets[m_NumPackets - 1].m_Data.m_aHeader, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
// copy server addresses
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, (char)0xFF, (char)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];
}
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;
PacketIndex++;
m_aPackets[m_NumPackets - 1].m_Size = sizeof(SERVERBROWSE_LIST) + sizeof(CMastersrvAddr) * PacketIndex;
pCurrent++;
}
else if(pCurrent->m_Type == SERVERTYPE_LEGACY)
{
if(PacketIndexLegacy % MAX_SERVERS_PER_PACKET == 0)
{
PacketIndexLegacy = 0;
m_NumPacketsLegacy++;
}
// copy header
mem_copy(m_aPacketsLegacy[m_NumPacketsLegacy - 1].m_Data.m_aHeader, SERVERBROWSE_LIST_LEGACY, sizeof(SERVERBROWSE_LIST_LEGACY));
// copy server addresses
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));
// 0.5 has the port in little endian on the network
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;
PacketIndexLegacy++;
m_aPacketsLegacy[m_NumPacketsLegacy - 1].m_Size = sizeof(SERVERBROWSE_LIST_LEGACY) + sizeof(CMastersrvAddrLegacy) * PacketIndexLegacy;
pCurrent++;
}
else
{
*pCurrent = m_aServers[m_NumServers - 1];
m_NumServers--;
dbg_msg("mastersrv", "ERROR: server of invalid type, dropping it");
}
}
}
void SendOk(NETADDR *pAddr)
{
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;
// send on both to be sure
m_NetChecker.Send(&p);
m_NetOp.Send(&p);
}
void SendError(NETADDR *pAddr)
{
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);
}
void SendCheck(NETADDR *pAddr)
{
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);
}
void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type)
{
// add server
if(m_NumCheckServers == MAX_SERVERS)
{
dbg_msg("mastersrv", "ERROR: mastersrv is full");
return;
}
char aAddrStr[NETADDR_MAXSTRSIZE];
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true);
char aAltAddrStr[NETADDR_MAXSTRSIZE];
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;
m_aCheckServers[m_NumCheckServers].m_TryCount = 0;
m_aCheckServers[m_NumCheckServers].m_TryTime = 0;
m_aCheckServers[m_NumCheckServers].m_Type = Type;
m_NumCheckServers++;
}
void AddServer(NETADDR *pInfo, ServerType Type)
{
// see if server already exists in list
for(int i = 0; i < m_NumServers; i++)
{
if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0)
{
char aAddrStr[NETADDR_MAXSTRSIZE];
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;
}
}
// add server
if(m_NumServers == MAX_SERVERS)
{
dbg_msg("mastersrv", "ERROR: mastersrv is full");
return;
}
char aAddrStr[NETADDR_MAXSTRSIZE];
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;
m_aServers[m_NumServers].m_Type = Type;
m_NumServers++;
}
void UpdateServers()
{
int64_t Now = time_get();
int64_t Freq = time_freq();
for(int i = 0; i < m_NumCheckServers; i++)
{
if(Now > m_aCheckServers[i].m_TryTime + Freq)
{
if(m_aCheckServers[i].m_TryCount == 10)
{
char aAddrStr[NETADDR_MAXSTRSIZE];
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), true);
dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr);
// FAIL!!
SendError(&m_aCheckServers[i].m_Address);
m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers - 1];
m_NumCheckServers--;
i--;
}
else
{
m_aCheckServers[i].m_TryCount++;
m_aCheckServers[i].m_TryTime = Now;
if(m_aCheckServers[i].m_TryCount & 1)
SendCheck(&m_aCheckServers[i].m_Address);
else
SendCheck(&m_aCheckServers[i].m_AltAddress);
}
}
}
}
void PurgeServers()
{
int64_t Now = time_get();
int i = 0;
while(i < m_NumServers)
{
if(m_aServers[i].m_Expire < Now)
{
// remove server
char aAddrStr[NETADDR_MAXSTRSIZE];
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--;
}
else
i++;
}
}
void ReloadBans()
{
m_NetBan.UnbanAll();
m_pConsole->ExecuteFile("master.cfg", -1, true);
}
int main(int argc, const char **argv)
{
int64_t LastBuild = 0, LastBanReload = 0;
ServerType Type = SERVERTYPE_INVALID;
NETADDR BindAddr;
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
net_init();
mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
mem_copy(m_CountDataLegacy.m_Header, SERVERBROWSE_COUNT_LEGACY, sizeof(SERVERBROWSE_COUNT_LEGACY));
IKernel *pKernel = IKernel::Create();
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
IConfigManager *pConfigManager = CreateConfigManager();
m_pConsole = CreateConsole(CFGFLAG_MASTER);
bool RegisterFail = !pKernel->RegisterInterface(pStorage);
RegisterFail |= !pKernel->RegisterInterface(m_pConsole);
RegisterFail |= !pKernel->RegisterInterface(pConfigManager);
if(RegisterFail)
return -1;
pConfigManager->Init();
m_pConsole->Init();
m_NetBan.Init(m_pConsole, pStorage);
if(argc > 1)
m_pConsole->ParseArguments(argc - 1, &argv[1]);
if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
BindAddr.type = NETTYPE_ALL;
BindAddr.port = MASTERSERVER_PORT;
}
else
{
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
BindAddr.port = MASTERSERVER_PORT;
}
if(!m_NetOp.Open(BindAddr))
{
dbg_msg("mastersrv", "couldn't start network (op)");
return -1;
}
BindAddr.port = MASTERSERVER_PORT + 1;
if(!m_NetChecker.Open(BindAddr))
{
dbg_msg("mastersrv", "couldn't start network (checker)");
return -1;
}
// process pending commands
m_pConsole->StoreCommands(false);
dbg_msg("mastersrv", "started");
while(true)
{
m_NetOp.Update();
m_NetChecker.Update();
// process m_aPackets
CNetChunk Packet;
while(m_NetOp.Recv(&Packet))
{
// check if the server is banned
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)
{
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)
{
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_LEGACY);
}
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)
{
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_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++)
{
p.m_DataSize = m_aPackets[i].m_Size;
p.m_pData = &m_aPackets[i].m_Data;
m_NetOp.Send(&p);
}
}
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETLIST_LEGACY) &&
mem_comp(Packet.m_pData, SERVERBROWSE_GETLIST_LEGACY, sizeof(SERVERBROWSE_GETLIST_LEGACY)) == 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_NumPacketsLegacy; i++)
{
p.m_DataSize = m_aPacketsLegacy[i].m_Size;
p.m_pData = &m_aPacketsLegacy[i].m_Data;
m_NetOp.Send(&p);
}
}
}
// process m_aPackets
while(m_NetChecker.Recv(&Packet))
{
// check if the server is banned
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)
{
Type = SERVERTYPE_INVALID;
// remove it from checking
for(int i = 0; i < m_NumCheckServers; i++)
{
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)
{
Type = m_aCheckServers[i].m_Type;
m_NumCheckServers--;
m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers];
break;
}
}
// drops servers that were not in the CheckServers list
if(Type == SERVERTYPE_INVALID)
continue;
AddServer(&Packet.m_Address, Type);
SendOk(&Packet.m_Address);
}
}
if(time_get() - LastBanReload > time_freq() * 300)
{
LastBanReload = time_get();
ReloadBans();
}
if(time_get() - LastBuild > time_freq() * 5)
{
LastBuild = time_get();
PurgeServers();
UpdateServers();
BuildPackets();
}
// be nice to the CPU
thread_sleep(1000);
}
return 0;
}

View file

@ -1,545 +1,34 @@
/* (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/config.h>
#include <engine/console.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,
EXPIRE_TIME = 90
};
const int MASTERSERVER_PORT = 8300;
struct CCheckServer
{
enum ServerType m_Type;
NETADDR m_Address;
NETADDR m_AltAddress;
int m_TryCount;
int64_t m_TryTime;
};
const unsigned char SERVERBROWSE_HEARTBEAT[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'b', 'e', 'a', '2'};
static CCheckServer m_aCheckServers[MAX_SERVERS];
static int m_NumCheckServers = 0;
const unsigned char SERVERBROWSE_GETLIST[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'r', 'e', 'q', '2'};
const unsigned char SERVERBROWSE_LIST[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'l', 'i', 's', '2'};
struct CServerEntry
{
enum ServerType m_Type;
NETADDR m_Address;
int64_t m_Expire;
};
const unsigned char SERVERBROWSE_GETCOUNT[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'c', 'o', 'u', '2'};
const unsigned char SERVERBROWSE_COUNT[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 's', 'i', 'z', '2'};
static CServerEntry m_aServers[MAX_SERVERS];
static int m_NumServers = 0;
const unsigned char SERVERBROWSE_GETINFO[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'g', 'i', 'e', '3'};
const unsigned char SERVERBROWSE_INFO[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'i', 'n', 'f', '3'};
struct CPacketData
{
int m_Size;
struct
{
unsigned char m_aHeader[sizeof(SERVERBROWSE_LIST)];
CMastersrvAddr m_aServers[MAX_SERVERS_PER_PACKET];
} m_Data;
};
const unsigned char SERVERBROWSE_GETINFO_64_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'f', 's', 't', 'd'};
const unsigned char SERVERBROWSE_INFO_64_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'd', 't', 's', 'f'};
CPacketData m_aPackets[MAX_PACKETS];
static int m_NumPackets = 0;
const unsigned char SERVERBROWSE_INFO_EXTENDED[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'i', 'e', 'x', 't'};
const unsigned char SERVERBROWSE_INFO_EXTENDED_MORE[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'i', 'e', 'x', '+'};
// 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;
};
const unsigned char SERVERBROWSE_FWCHECK[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'f', 'w', '?', '?'};
const unsigned char SERVERBROWSE_FWRESPONSE[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'f', 'w', '!', '!'};
const unsigned char SERVERBROWSE_FWOK[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'f', 'w', 'o', 'k'};
const unsigned char SERVERBROWSE_FWERROR[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'f', 'w', 'e', 'r'};
CPacketDataLegacy m_aPacketsLegacy[MAX_PACKETS];
static int m_NumPacketsLegacy = 0;
const unsigned char SERVERBROWSE_HEARTBEAT_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'b', 'e', 'a', 't'};
struct CCountPacketData
{
unsigned char m_Header[sizeof(SERVERBROWSE_COUNT)];
unsigned char m_High;
unsigned char m_Low;
};
const unsigned char SERVERBROWSE_GETLIST_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'r', 'e', 'q', 't'};
const unsigned char SERVERBROWSE_LIST_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'l', 'i', 's', 't'};
static CCountPacketData m_CountData;
static CCountPacketData m_CountDataLegacy;
const unsigned char SERVERBROWSE_GETCOUNT_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 'c', 'o', 'u', 'n'};
const unsigned char SERVERBROWSE_COUNT_LEGACY[SERVERBROWSE_SIZE] = {255, 255, 255, 255, 's', 'i', 'z', 'e'};
CNetBan m_NetBan;
static CNetClient m_NetChecker; // NAT/FW checker
static CNetClient m_NetOp; // main
IConsole *m_pConsole;
void BuildPackets()
{
CServerEntry *pCurrent = &m_aServers[0];
int ServersLeft = m_NumServers;
m_NumPackets = 0;
m_NumPacketsLegacy = 0;
int PacketIndex = 0;
int PacketIndexLegacy = 0;
while(ServersLeft-- && (m_NumPackets + m_NumPacketsLegacy) < MAX_PACKETS)
{
if(pCurrent->m_Type == SERVERTYPE_NORMAL)
{
if(PacketIndex % MAX_SERVERS_PER_PACKET == 0)
{
PacketIndex = 0;
m_NumPackets++;
}
// copy header
mem_copy(m_aPackets[m_NumPackets - 1].m_Data.m_aHeader, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
// copy server addresses
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, (char)0xFF, (char)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];
}
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;
PacketIndex++;
m_aPackets[m_NumPackets - 1].m_Size = sizeof(SERVERBROWSE_LIST) + sizeof(CMastersrvAddr) * PacketIndex;
pCurrent++;
}
else if(pCurrent->m_Type == SERVERTYPE_LEGACY)
{
if(PacketIndexLegacy % MAX_SERVERS_PER_PACKET == 0)
{
PacketIndexLegacy = 0;
m_NumPacketsLegacy++;
}
// copy header
mem_copy(m_aPacketsLegacy[m_NumPacketsLegacy - 1].m_Data.m_aHeader, SERVERBROWSE_LIST_LEGACY, sizeof(SERVERBROWSE_LIST_LEGACY));
// copy server addresses
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));
// 0.5 has the port in little endian on the network
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;
PacketIndexLegacy++;
m_aPacketsLegacy[m_NumPacketsLegacy - 1].m_Size = sizeof(SERVERBROWSE_LIST_LEGACY) + sizeof(CMastersrvAddrLegacy) * PacketIndexLegacy;
pCurrent++;
}
else
{
*pCurrent = m_aServers[m_NumServers - 1];
m_NumServers--;
dbg_msg("mastersrv", "ERROR: server of invalid type, dropping it");
}
}
}
void SendOk(NETADDR *pAddr)
{
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;
// send on both to be sure
m_NetChecker.Send(&p);
m_NetOp.Send(&p);
}
void SendError(NETADDR *pAddr)
{
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);
}
void SendCheck(NETADDR *pAddr)
{
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);
}
void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type)
{
// add server
if(m_NumCheckServers == MAX_SERVERS)
{
dbg_msg("mastersrv", "ERROR: mastersrv is full");
return;
}
char aAddrStr[NETADDR_MAXSTRSIZE];
net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true);
char aAltAddrStr[NETADDR_MAXSTRSIZE];
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;
m_aCheckServers[m_NumCheckServers].m_TryCount = 0;
m_aCheckServers[m_NumCheckServers].m_TryTime = 0;
m_aCheckServers[m_NumCheckServers].m_Type = Type;
m_NumCheckServers++;
}
void AddServer(NETADDR *pInfo, ServerType Type)
{
// see if server already exists in list
for(int i = 0; i < m_NumServers; i++)
{
if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0)
{
char aAddrStr[NETADDR_MAXSTRSIZE];
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;
}
}
// add server
if(m_NumServers == MAX_SERVERS)
{
dbg_msg("mastersrv", "ERROR: mastersrv is full");
return;
}
char aAddrStr[NETADDR_MAXSTRSIZE];
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;
m_aServers[m_NumServers].m_Type = Type;
m_NumServers++;
}
void UpdateServers()
{
int64_t Now = time_get();
int64_t Freq = time_freq();
for(int i = 0; i < m_NumCheckServers; i++)
{
if(Now > m_aCheckServers[i].m_TryTime + Freq)
{
if(m_aCheckServers[i].m_TryCount == 10)
{
char aAddrStr[NETADDR_MAXSTRSIZE];
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), true);
dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr);
// FAIL!!
SendError(&m_aCheckServers[i].m_Address);
m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers - 1];
m_NumCheckServers--;
i--;
}
else
{
m_aCheckServers[i].m_TryCount++;
m_aCheckServers[i].m_TryTime = Now;
if(m_aCheckServers[i].m_TryCount & 1)
SendCheck(&m_aCheckServers[i].m_Address);
else
SendCheck(&m_aCheckServers[i].m_AltAddress);
}
}
}
}
void PurgeServers()
{
int64_t Now = time_get();
int i = 0;
while(i < m_NumServers)
{
if(m_aServers[i].m_Expire < Now)
{
// remove server
char aAddrStr[NETADDR_MAXSTRSIZE];
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--;
}
else
i++;
}
}
void ReloadBans()
{
m_NetBan.UnbanAll();
m_pConsole->ExecuteFile("master.cfg", -1, true);
}
int main(int argc, const char **argv)
{
int64_t LastBuild = 0, LastBanReload = 0;
ServerType Type = SERVERTYPE_INVALID;
NETADDR BindAddr;
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
net_init();
mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
mem_copy(m_CountDataLegacy.m_Header, SERVERBROWSE_COUNT_LEGACY, sizeof(SERVERBROWSE_COUNT_LEGACY));
IKernel *pKernel = IKernel::Create();
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
IConfigManager *pConfigManager = CreateConfigManager();
m_pConsole = CreateConsole(CFGFLAG_MASTER);
bool RegisterFail = !pKernel->RegisterInterface(pStorage);
RegisterFail |= !pKernel->RegisterInterface(m_pConsole);
RegisterFail |= !pKernel->RegisterInterface(pConfigManager);
if(RegisterFail)
return -1;
pConfigManager->Init();
m_pConsole->Init();
m_NetBan.Init(m_pConsole, pStorage);
if(argc > 1)
m_pConsole->ParseArguments(argc - 1, &argv[1]);
if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
BindAddr.type = NETTYPE_ALL;
BindAddr.port = MASTERSERVER_PORT;
}
else
{
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
BindAddr.port = MASTERSERVER_PORT;
}
if(!m_NetOp.Open(BindAddr))
{
dbg_msg("mastersrv", "couldn't start network (op)");
return -1;
}
BindAddr.port = MASTERSERVER_PORT + 1;
if(!m_NetChecker.Open(BindAddr))
{
dbg_msg("mastersrv", "couldn't start network (checker)");
return -1;
}
// process pending commands
m_pConsole->StoreCommands(false);
dbg_msg("mastersrv", "started");
while(true)
{
m_NetOp.Update();
m_NetChecker.Update();
// process m_aPackets
CNetChunk Packet;
while(m_NetOp.Recv(&Packet))
{
// check if the server is banned
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)
{
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)
{
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_LEGACY);
}
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)
{
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_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++)
{
p.m_DataSize = m_aPackets[i].m_Size;
p.m_pData = &m_aPackets[i].m_Data;
m_NetOp.Send(&p);
}
}
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETLIST_LEGACY) &&
mem_comp(Packet.m_pData, SERVERBROWSE_GETLIST_LEGACY, sizeof(SERVERBROWSE_GETLIST_LEGACY)) == 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_NumPacketsLegacy; i++)
{
p.m_DataSize = m_aPacketsLegacy[i].m_Size;
p.m_pData = &m_aPacketsLegacy[i].m_Data;
m_NetOp.Send(&p);
}
}
}
// process m_aPackets
while(m_NetChecker.Recv(&Packet))
{
// check if the server is banned
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)
{
Type = SERVERTYPE_INVALID;
// remove it from checking
for(int i = 0; i < m_NumCheckServers; i++)
{
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)
{
Type = m_aCheckServers[i].m_Type;
m_NumCheckServers--;
m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers];
break;
}
}
// drops servers that were not in the CheckServers list
if(Type == SERVERTYPE_INVALID)
continue;
AddServer(&Packet.m_Address, Type);
SendOk(&Packet.m_Address);
}
}
if(time_get() - LastBanReload > time_freq() * 300)
{
LastBanReload = time_get();
ReloadBans();
}
if(time_get() - LastBuild > time_freq() * 5)
{
LastBuild = time_get();
PurgeServers();
UpdateServers();
BuildPackets();
}
// be nice to the CPU
thread_sleep(1000);
}
return 0;
}

View file

@ -2,7 +2,7 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#ifndef MASTERSRV_MASTERSRV_H
#define MASTERSRV_MASTERSRV_H
static const int MASTERSERVER_PORT = 8300;
extern const int MASTERSERVER_PORT;
enum ServerType
{
@ -17,27 +17,28 @@ struct CMastersrvAddr
unsigned char m_aPort[2];
};
static const unsigned char SERVERBROWSE_HEARTBEAT[] = {255, 255, 255, 255, 'b', 'e', 'a', '2'};
#define SERVERBROWSE_SIZE 8
extern const unsigned char SERVERBROWSE_HEARTBEAT[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_GETLIST[] = {255, 255, 255, 255, 'r', 'e', 'q', '2'};
static const unsigned char SERVERBROWSE_LIST[] = {255, 255, 255, 255, 'l', 'i', 's', '2'};
extern const unsigned char SERVERBROWSE_GETLIST[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_LIST[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_GETCOUNT[] = {255, 255, 255, 255, 'c', 'o', 'u', '2'};
static const unsigned char SERVERBROWSE_COUNT[] = {255, 255, 255, 255, 's', 'i', 'z', '2'};
extern const unsigned char SERVERBROWSE_GETCOUNT[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_COUNT[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_GETINFO[] = {255, 255, 255, 255, 'g', 'i', 'e', '3'};
static const unsigned char SERVERBROWSE_INFO[] = {255, 255, 255, 255, 'i', 'n', 'f', '3'};
extern const unsigned char SERVERBROWSE_GETINFO[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_INFO[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_GETINFO_64_LEGACY[] = {255, 255, 255, 255, 'f', 's', 't', 'd'};
static const unsigned char SERVERBROWSE_INFO_64_LEGACY[] = {255, 255, 255, 255, 'd', 't', 's', 'f'};
extern const unsigned char SERVERBROWSE_GETINFO_64_LEGACY[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_INFO_64_LEGACY[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_INFO_EXTENDED[] = {255, 255, 255, 255, 'i', 'e', 'x', 't'};
static const unsigned char SERVERBROWSE_INFO_EXTENDED_MORE[] = {255, 255, 255, 255, 'i', 'e', 'x', '+'};
extern const unsigned char SERVERBROWSE_INFO_EXTENDED[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_INFO_EXTENDED_MORE[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_FWCHECK[] = {255, 255, 255, 255, 'f', 'w', '?', '?'};
static const unsigned char SERVERBROWSE_FWRESPONSE[] = {255, 255, 255, 255, 'f', 'w', '!', '!'};
static const unsigned char SERVERBROWSE_FWOK[] = {255, 255, 255, 255, 'f', 'w', 'o', 'k'};
static const unsigned char SERVERBROWSE_FWERROR[] = {255, 255, 255, 255, 'f', 'w', 'e', 'r'};
extern const unsigned char SERVERBROWSE_FWCHECK[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_FWRESPONSE[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_FWOK[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_FWERROR[SERVERBROWSE_SIZE];
// packet headers for the 0.5 branch
@ -47,13 +48,13 @@ struct CMastersrvAddrLegacy
unsigned char m_aPort[2];
};
static const unsigned char SERVERBROWSE_HEARTBEAT_LEGACY[] = {255, 255, 255, 255, 'b', 'e', 'a', 't'};
extern const unsigned char SERVERBROWSE_HEARTBEAT_LEGACY[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_GETLIST_LEGACY[] = {255, 255, 255, 255, 'r', 'e', 'q', 't'};
static const unsigned char SERVERBROWSE_LIST_LEGACY[] = {255, 255, 255, 255, 'l', 'i', 's', 't'};
extern const unsigned char SERVERBROWSE_GETLIST_LEGACY[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_LIST_LEGACY[SERVERBROWSE_SIZE];
static const unsigned char SERVERBROWSE_GETCOUNT_LEGACY[] = {255, 255, 255, 255, 'c', 'o', 'u', 'n'};
static const unsigned char SERVERBROWSE_COUNT_LEGACY[] = {255, 255, 255, 255, 's', 'i', 'z', 'e'};
extern const unsigned char SERVERBROWSE_GETCOUNT_LEGACY[SERVERBROWSE_SIZE];
extern const unsigned char SERVERBROWSE_COUNT_LEGACY[SERVERBROWSE_SIZE];
enum
{