From 3f49c695226055df017e300b5acf009acf009de6 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 20 Sep 2015 12:46:06 +0200 Subject: [PATCH] restored master server --- src/engine/shared/network.cpp | 3 +- src/engine/shared/network.h | 5 +- src/mastersrv/mastersrv.cpp | 1719 +++++++++++---------------------- src/mastersrv/mastersrv.h | 201 +--- src/mastersrv/mastersrv5.cpp | 155 --- src/mastersrv/mastersrv6.cpp | 130 --- src/mastersrv/mastersrv7.cpp | 134 --- src/mastersrv/versionsrv.cpp | 155 --- 8 files changed, 600 insertions(+), 1902 deletions(-) delete mode 100644 src/mastersrv/mastersrv5.cpp delete mode 100644 src/mastersrv/mastersrv6.cpp delete mode 100644 src/mastersrv/mastersrv7.cpp delete mode 100644 src/mastersrv/versionsrv.cpp diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 956535163..2782fa529 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -7,7 +7,8 @@ #include "network.h" #include "huffman.h" -void CNetRecvUnpacker::Clear() { +void CNetRecvUnpacker::Clear() +{ m_Valid = false; } diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 17f268846..50945a99c 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -1,4 +1,5 @@ -/* (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. */ +/* (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. */ #ifndef ENGINE_SHARED_NETWORK_H #define ENGINE_SHARED_NETWORK_H @@ -393,7 +394,7 @@ public: bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags); int Close(); - // the token and version parameter are only used for connless packets + // the token parameter is only used for connless packets int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0); int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE); int Update(); diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index fb591ffa2..088fec0f9 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -1,1176 +1,543 @@ -/* (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 - -#include -#include -#include -#include - -#include -#include -#include - -#include "mastersrv.h" - -int main(int argc, const char **argv) // ignore_convention -{ - dbg_logger_stdout(); - net_init(); - - IKernel *pKernel = IKernel::Create(); - IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); - IConfig *pConfig = CreateConfig(); - IConsole *pConsole = CreateConsole(CFGFLAG_MASTER); - IMastersrv *pMastersrv = CreateMastersrv(); - - bool RegisterFail = !pKernel->RegisterInterface(pStorage); - RegisterFail |= !pKernel->RegisterInterface(pConsole); - RegisterFail |= !pKernel->RegisterInterface(pConfig); - RegisterFail |= !pKernel->RegisterInterface(pMastersrv); - - if(RegisterFail) - return -1; - - pConfig->Init(); - if(argc > 1) // ignore_convention - pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention - - int Result; - - if((Result = pMastersrv->Init()) != 0) - { - dbg_msg("mastersrv", "initialisation failed (%d)", Result); - return Result; - } - - Result = pMastersrv->Run(); - - delete pMastersrv; - delete pConsole; - delete pConfig; - delete pStorage; - delete pKernel; - - return Result; -} - -void IMastersrvSlave::NetaddrToMastersrv(CMastersrvAddr *pOut, const NETADDR *pIn) -{ - dbg_assert(pIn->type == NETTYPE_IPV6 || pIn->type == NETTYPE_IPV4, "nettype not supported"); - - if(pIn->type == NETTYPE_IPV6) - { - mem_copy(pOut->m_aIp, pIn->ip, sizeof(pOut->m_aIp)); - } - else if(pIn->type == NETTYPE_IPV4) - { - static const char aIPV4Mapping[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; - mem_copy(pOut->m_aIp, aIPV4Mapping, sizeof(aIPV4Mapping)); - mem_copy(pOut->m_aIp + 12, pIn->ip, 4); - } - - pOut->m_aPort[0] = (pIn->port>>8)&0xff; // big endian - pOut->m_aPort[1] = (pIn->port>>0)&0xff; -} - -class CMastersrv : public IMastersrv -{ -public: - enum - { - MAX_SERVERS=1200, - MAX_CHECKSERVERS=MAX_SERVERS, - MAX_PACKETS=16, - - EXPIRE_TIME=90, - BAN_REFRESH_TIME=300, - PACKET_REFRESH_TIME=5, - }; - CMastersrv(); - ~CMastersrv(); - - virtual int Init(); - virtual int Run(); - - virtual void AddServer(const NETADDR *pAddr, void *pUserData, int Version); - virtual void AddCheckserver(const NETADDR *pAddr, const NETADDR *pAltAddr, void *pUserData, int Version); - virtual void SendList(const NETADDR *pAddr, void *pUserData, int Version); - virtual int GetCount() const; - - virtual int Send(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion); - - void PurgeServers(); - void UpdateServers(); - void BuildPackets(); - - void ReloadBans(); - -private: - IConsole *m_pConsole; - - CNetBan m_NetBan; - CNetClient m_aNets[NUM_SOCKETS]; - - int64 m_BanRefreshTime; - int64 m_PacketRefreshTime; - - struct CServerEntry - { - NETADDR m_Address; - void *m_pSlaveUserData; - - int m_Version; - int64 m_Expire; - }; - - struct CCheckServer - { - NETADDR m_Address; - NETADDR m_AltAddress; - void *m_pSlaveUserData; - - int m_TryCount; - int64 m_TryTime; - - int m_Version; - }; - - CServerEntry m_aServers[MAX_SERVERS]; - int m_NumServers; - CCheckServer m_aCheckServers[MAX_CHECKSERVERS]; - int m_NumCheckServers; - - struct CMastersrvSlave - { - struct CPacket - { - char m_aData[NET_MAX_PAYLOAD]; - int m_Size; - } m_aPackets[MAX_PACKETS]; - int m_NumPackets; - - IMastersrvSlave *m_pSlave; - }; - - CMastersrvSlave m_aSlaves[NUM_MASTERSRV]; -}; - -IMastersrv *CreateMastersrv() -{ - return new CMastersrv(); -} - -CMastersrv::CMastersrv() -{ - for(int s = 0; s < NUM_MASTERSRV; s++) - m_aSlaves[s].m_pSlave = 0; -} - -CMastersrv::~CMastersrv() -{ - for(int s = 0; s < NUM_MASTERSRV; s++) - if(m_aSlaves[s].m_pSlave) - delete m_aSlaves[s].m_pSlave; -} - -int CMastersrv::Init() -{ - m_pConsole = Kernel()->RequestInterface(); - - m_NetBan.Init(m_pConsole, Kernel()->RequestInterface()); - - int Services = 0; - if(str_find(g_Config.m_MsServices, "5")) - Services |= 1<StoreCommands(false); - - for(int s = 0; s < NUM_MASTERSRV; s++) - m_aSlaves[s].m_NumPackets = 0; - - if(Services&(1<ProcessMessage(i, &Packet, Token, Version) != 0) - break; - } - } - } - - int64 Now = time_get(); - int64 Freq = time_freq(); - if(m_BanRefreshTime < Now) - { - m_BanRefreshTime = Now + Freq * BAN_REFRESH_TIME; - ReloadBans(); - } - - if(m_PacketRefreshTime < Now) - { - m_PacketRefreshTime = Now + Freq * PACKET_REFRESH_TIME; - - PurgeServers(); - UpdateServers(); - BuildPackets(); - } - - // be nice to the CPU - thread_sleep(1); - } - - return 0; -} - -void CMastersrv::UpdateServers() -{ - int64 Now = time_get(); - int64 Freq = time_freq(); - for(int i = 0; i < m_NumCheckServers; i++) - { - CCheckServer *pCheck = &m_aCheckServers[i]; - - if(pCheck->m_TryTime + Freq < Now) - { - IMastersrvSlave *pSlave = m_aSlaves[pCheck->m_Version].m_pSlave; - dbg_assert(pSlave != 0, "attempting to access uninitalised slave"); - - if(pCheck->m_TryCount == 10) - { - char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&pCheck->m_Address, aAddrStr, sizeof(aAddrStr), true); - char aAltAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&pCheck->m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr), true); - dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr); - - // FAIL!! - pSlave->SendError(&pCheck->m_Address, pCheck->m_pSlaveUserData); - *pCheck = m_aCheckServers[m_NumCheckServers-1]; - m_NumCheckServers--; - i--; - } - else - { - pCheck->m_TryCount++; - pCheck->m_TryTime = Now; - - if(pCheck->m_TryCount&1) - pSlave->SendCheck(&pCheck->m_Address, pCheck->m_pSlaveUserData); - else - pSlave->SendCheck(&pCheck->m_AltAddress, pCheck->m_pSlaveUserData); - } - } - } -} - -void CMastersrv::BuildPackets() -{ - bool aPreparePacket[NUM_MASTERSRV]; - int BytesWritten; - - for(int s = 0; s < NUM_MASTERSRV; s++) - { - m_aSlaves[s].m_NumPackets = 0; - aPreparePacket[s] = true; - for(int i = 0; i < MAX_PACKETS; i++) - m_aSlaves[s].m_aPackets[i].m_Size = 0; - } - - for(int i = 0; i < m_NumServers; i++) - { - CServerEntry *pServer = &m_aServers[i]; - CMastersrvSlave *pSlaveData = &m_aSlaves[pServer->m_Version]; - IMastersrvSlave *pSlave = pSlaveData->m_pSlave; - CMastersrvSlave::CPacket *pPacket = &pSlaveData->m_aPackets[pSlaveData->m_NumPackets - 1]; - dbg_assert(pSlave != 0, "attempting to access uninitalised slave"); - - if(aPreparePacket[pServer->m_Version]) - { - if(pSlaveData->m_NumPackets != 0) - { - BytesWritten = pSlave->BuildPacketFinalize(&pPacket->m_aData[pPacket->m_Size], NET_MAX_PAYLOAD - pPacket->m_Size); - dbg_assert(BytesWritten >= 0, "build packet finalisation failed"); - pPacket->m_Size += BytesWritten; - } - - pPacket = &pSlaveData->m_aPackets[pSlaveData->m_NumPackets]; - pSlaveData->m_NumPackets++; - - BytesWritten = pSlave->BuildPacketStart(&pPacket->m_aData[0], NET_MAX_PAYLOAD); - - dbg_assert(BytesWritten >= 0, "build packet initialisation failed"); - pPacket->m_Size += BytesWritten; - - aPreparePacket[pServer->m_Version] = false; - } - - BytesWritten = pSlave->BuildPacketAdd(&pPacket->m_aData[pPacket->m_Size], NET_MAX_PAYLOAD - pPacket->m_Size, - &pServer->m_Address, pServer->m_pSlaveUserData); - if(BytesWritten < 0) - { - aPreparePacket[pServer->m_Version] = true; - i--; - continue; - } - pPacket->m_Size += BytesWritten; - } - - for(int s = 0; s < NUM_MASTERSRV; s++) - { - CMastersrvSlave *pSlaveData = &m_aSlaves[s]; - IMastersrvSlave *pSlave = pSlaveData->m_pSlave; - - if(m_aSlaves[s].m_NumPackets > 0) - { - dbg_assert(pSlave != 0, "attempting to finalise packet for non-existant slave"); - - CMastersrvSlave::CPacket *pPacket = &pSlaveData->m_aPackets[pSlaveData->m_NumPackets - 1]; - BytesWritten = pSlave->BuildPacketFinalize(&pPacket->m_aData[pPacket->m_Size], NET_MAX_PAYLOAD - pPacket->m_Size); - dbg_assert(BytesWritten >= 0, "final build packet finalisation failed"); - pPacket->m_Size += BytesWritten; - } - } - -/* 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, 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]; - } - - 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"); - } - } -*/ -} - -int CMastersrv::Send(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) -{ - dbg_assert(Socket >= 0 && Socket < NUM_SOCKETS, "attempting to send via non-existant socket"); - - m_aNets[Socket].Send((CNetChunk *)pPacket, PacketToken, PacketVersion); - - return 0; -} - -void CMastersrv::AddServer(const NETADDR *pAddr, void *pUserData, int Version) -{ - dbg_assert(Version >= 0 && Version < NUM_MASTERSRV, "version out of range"); - - bool Found = false; - for(int i = 0; i < m_NumCheckServers && !Found; i++) - { - if((net_addr_comp(&m_aCheckServers[i].m_Address, pAddr) == 0 - || net_addr_comp(&m_aCheckServers[i].m_AltAddress, pAddr) == 0) - && m_aCheckServers[i].m_Version == Version) - - { - m_NumCheckServers--; - m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers]; - Found = true; - } - } - - if(!Found) // only allow this for servers which are actually being checked - return; - - char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(pAddr, aAddrStr, sizeof(aAddrStr), true); - - // see if server already exists in list - for(int i = 0; i < m_NumServers; i++) - { - if(net_addr_comp(&m_aServers[i].m_Address, pAddr) == 0 && m_aServers[i].m_Version == Version) - { - dbg_msg("mastersrv", "updated: %s", aAddrStr); - m_aServers[i].m_pSlaveUserData = pUserData; - 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: %s", aAddrStr); - return; - } - - dbg_msg("mastersrv", "added: %s", aAddrStr); - m_aServers[m_NumServers].m_Address = *pAddr; - m_aServers[m_NumServers].m_pSlaveUserData = pUserData; - m_aServers[m_NumServers].m_Expire = time_get() + time_freq() * EXPIRE_TIME; - m_aServers[m_NumServers].m_Version = Version; - m_NumServers++; - - IMastersrvSlave *pSlave = m_aSlaves[Version].m_pSlave; - dbg_assert(pSlave != 0, "attempting to access uninitalised slave"); - pSlave->SendOk(pAddr, pUserData); -} - -void CMastersrv::AddCheckserver(const NETADDR *pAddr, const NETADDR *pAltAddr, void *pUserData, int Version) -{ - dbg_assert(Version >= 0 && Version < NUM_MASTERSRV, "version out of range"); - - char aAddrStr[2 * NETADDR_MAXSTRSIZE + 3]; // 3 == sizeof(' ()') - char aTmp1[NETADDR_MAXSTRSIZE], aTmp2[NETADDR_MAXSTRSIZE]; - - net_addr_str(pAddr, aTmp1, sizeof(aTmp1), true); - net_addr_str(pAltAddr, aTmp2, sizeof(aTmp2), true); - - str_format(aAddrStr, sizeof(aAddrStr), "%s (%s)", aTmp1, aTmp2); - - // see if server already exists in list - for(int i = 0; i < m_NumCheckServers; i++) - { - if(net_addr_comp(&m_aCheckServers[i].m_Address, pAddr) == 0 - && m_aCheckServers[i].m_Version == Version) - { - dbg_msg("mastersrv/check", "warning: updated: %s", aAddrStr); - m_aCheckServers[i].m_AltAddress = *pAltAddr; - m_aCheckServers[i].m_Version = Version; - m_aCheckServers[i].m_pSlaveUserData = pUserData; - m_aCheckServers[i].m_TryCount = 0; - m_aCheckServers[i].m_TryTime = 0; - return; - } - } - - // add server - if(m_NumCheckServers == MAX_CHECKSERVERS) - { - dbg_msg("mastersrv/check", "error: mastersrv is full: %s", aAddrStr); - return; - } - - dbg_msg("mastersrv/check", "added: %s", aAddrStr); - m_aCheckServers[m_NumCheckServers].m_Address = *pAddr; - m_aCheckServers[m_NumCheckServers].m_AltAddress = *pAltAddr; - m_aCheckServers[m_NumCheckServers].m_Version = Version; - m_aCheckServers[m_NumCheckServers].m_pSlaveUserData = pUserData; - m_aCheckServers[m_NumCheckServers].m_TryCount = 0; - m_aCheckServers[m_NumCheckServers].m_TryTime = 0; - m_NumCheckServers++; -} - -void CMastersrv::SendList(const NETADDR *pAddr, void *pUserData, int Version) -{ - dbg_assert(Version >= 0 && Version < NUM_MASTERSRV, "version out of range"); - IMastersrvSlave *pSlave = m_aSlaves[Version].m_pSlave; - dbg_assert(pSlave != 0, "attempting to access uninitalised slave"); - - dbg_msg("mastersrv", "requested, responding with %d packets", m_aSlaves[Version].m_NumPackets); - - for(int i = 0; i < m_aSlaves[Version].m_NumPackets; i++) - { - CMastersrvSlave::CPacket *pPacket = &m_aSlaves[Version].m_aPackets[i]; - pSlave->SendList(pAddr, pPacket->m_aData, pPacket->m_Size, pUserData); - } -} - -int CMastersrv::GetCount() const -{ - dbg_msg("mastersrv", "requesting count, responding with %d", m_NumServers); - return m_NumServers; -} - -void CMastersrv::PurgeServers() -{ - int64 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 CMastersrv::ReloadBans() -{ - m_NetBan.UnbanAll(); - m_pConsole->ExecuteFile("master.cfg"); -} - -/*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 m_TryTime; - TOKEN m_Token; -}; - -static CCheckServer m_aCheckServers[MAX_SERVERS]; -static int m_NumCheckServers = 0; - -struct CServerEntry -{ - enum ServerType m_Type; - NETADDR m_Address; - int64 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 unsigned char s_aIPV4Mapping[] = {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, s_aIPV4Mapping, sizeof(s_aIPV4Mapping)); - 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, TOKEN Token) -{ - 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, Token); - m_NetOp.Send(&p, Token); -} - -void SendError(NETADDR *pAddr, TOKEN Token) -{ - 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, Token); -} - -void SendCheck(NETADDR *pAddr, TOKEN Token) -{ - 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, Token); -} - -void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type, TOKEN Token) -{ - // 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_aCheckServers[m_NumCheckServers].m_Token = Token; - 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 Now = time_get(); - int64 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_Token); - 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, m_aCheckServers[i].m_Token); - else - SendCheck(&m_aCheckServers[i].m_AltAddress, m_aCheckServers[i].m_Token); - } - } - } -} - -void PurgeServers() -{ - int64 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"); -} - -int main(int argc, const char **argv) // ignore_convention -{ - int64 LastBuild = 0, LastBanReload = 0; - ServerType Type = SERVERTYPE_INVALID; - NETADDR BindAddr; - - 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)); - - int FlagMask = CFGFLAG_MASTER; - IKernel *pKernel = IKernel::Create(); - IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); - IConfig *pConfig = CreateConfig(); - m_pConsole = CreateConsole(FlagMask); - - bool RegisterFail = !pKernel->RegisterInterface(pStorage); - RegisterFail |= !pKernel->RegisterInterface(m_pConsole); - RegisterFail |= !pKernel->RegisterInterface(pConfig); - - if(RegisterFail) - return -1; - - pConfig->Init(FlagMask); - m_NetBan.Init(m_pConsole, pStorage); - if(argc > 1) // ignore_convention - m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention - - 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, NETFLAG_ALLOWSTATELESS)) - { - dbg_msg("mastersrv", "couldn't start network (op)"); - return -1; - } - BindAddr.port = MASTERSERVER_PORT+1; - if(!m_NetChecker.Open(BindAddr, NETFLAG_ALLOWSTATELESS)) - { - dbg_msg("mastersrv", "couldn't start network (checker)"); - return -1; - } - - // process pending commands - m_pConsole->StoreCommands(false); - - dbg_msg("mastersrv", "started"); - - while(1) - { - m_NetOp.Update(); - m_NetChecker.Update(); - - // process m_aPackets - CNetChunk Packet; - TOKEN Token; - while(m_NetOp.Recv(&Packet, &Token)) - { - // 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, Token); - } - 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, Token); - } - 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, Token); - } - } - 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, &Token)) - { - // 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, Token); - } - } - - 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(1); - } - - return 0; -} -*/ - +/* (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 + +#include +#include +#include +#include + +#include +#include +#include + +#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 m_TryTime; +}; + +static CCheckServer m_aCheckServers[MAX_SERVERS]; +static int m_NumCheckServers = 0; + +struct CServerEntry +{ + enum ServerType m_Type; + NETADDR m_Address; + int64 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 unsigned char s_aIPV4Mapping[] = {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, s_aIPV4Mapping, sizeof(s_aIPV4Mapping)); + 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 Now = time_get(); + int64 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 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"); +} + +int main(int argc, const char **argv) // ignore_convention +{ + int64 LastBuild = 0, LastBanReload = 0; + ServerType Type = SERVERTYPE_INVALID; + NETADDR BindAddr; + + 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)); + + int FlagMask = CFGFLAG_MASTER; + IKernel *pKernel = IKernel::Create(); + IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); + IConfig *pConfig = CreateConfig(); + m_pConsole = CreateConsole(FlagMask); + + bool RegisterFail = !pKernel->RegisterInterface(pStorage); + RegisterFail |= !pKernel->RegisterInterface(m_pConsole); + RegisterFail |= !pKernel->RegisterInterface(pConfig); + + if(RegisterFail) + return -1; + + pConfig->Init(FlagMask); + m_NetBan.Init(m_pConsole, pStorage); + if(argc > 1) // ignore_convention + m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention + + 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, 0)) + { + dbg_msg("mastersrv", "couldn't start network (op)"); + return -1; + } + BindAddr.port = MASTERSERVER_PORT+1; + if(!m_NetChecker.Open(BindAddr, 0)) + { + dbg_msg("mastersrv", "couldn't start network (checker)"); + return -1; + } + + // process pending commands + m_pConsole->StoreCommands(false); + + dbg_msg("mastersrv", "started"); + + while(1) + { + 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(1); + } + + return 0; +} diff --git a/src/mastersrv/mastersrv.h b/src/mastersrv/mastersrv.h index ff7dfbb43..be0ecf03f 100644 --- a/src/mastersrv/mastersrv.h +++ b/src/mastersrv/mastersrv.h @@ -1,149 +1,52 @@ -/* (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. */ -#ifndef MASTERSRV_MASTERSRV_H -#define MASTERSRV_MASTERSRV_H - -#include -#include - -struct CMastersrvAddr -{ - unsigned char m_aIp[16]; - unsigned char m_aPort[2]; -}; - - -static const unsigned char SERVERBROWSE_HEARTBEAT[] = {255, 255, 255, 255, 'b', 'e', 'a', '2'}; - -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'}; - -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'}; - -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'}; - -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'}; - -class CNetChunk; -class IMastersrv; - -enum -{ - MASTERSERVER_PORT=8300, - MASTERSERVER_CHECKER_PORT=MASTERSERVER_PORT+1, - VERSIONSERVER_PORT=8302, -}; - -class IMastersrv : public IInterface -{ - MACRO_INTERFACE("mastersrv", 0) -public: - enum - { - MASTERSRV_0_7=0, - MASTERSRV_0_6, - MASTERSRV_0_5, - MASTERSRV_VER, - NUM_MASTERSRV, - - SOCKET_OP=0, - SOCKET_CHECKER, - SOCKET_VERSION, - NUM_SOCKETS, - }; - - IMastersrv() {} - virtual ~IMastersrv() {} - - virtual int Init() = 0; - virtual int Run() = 0; - - virtual void AddServer(const NETADDR *pAddr, void *pUserData, int Version) = 0; - virtual void AddCheckserver(const NETADDR *pAddr, const NETADDR *pAltAddr, void *pUserData, int Version) = 0; - virtual void SendList(const NETADDR *pAddr, void *pUserData, int Version) = 0; - virtual int GetCount() const = 0; - - virtual int Send(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) = 0; -}; - -class IMastersrvSlave -{ -public: - IMastersrvSlave(IMastersrv *pOwner, int Version) : m_pOwner(pOwner), m_Version(Version) {} - virtual ~IMastersrvSlave() {} - - // hooks - void AddServer(const NETADDR *pAddr, void *pUserData) { m_pOwner->AddServer(pAddr, pUserData, m_Version); } - void AddCheckserver(const NETADDR *pAddr, const NETADDR *pAltAddr, void *pUserData) { m_pOwner->AddCheckserver(pAddr, pAltAddr, pUserData, m_Version); } - void SendList(const NETADDR *pAddr, void *pUserData) { m_pOwner->SendList(pAddr, pUserData, m_Version); } - - // interface for packet building - // these functions return number of bytes written - // if that number smaller than 0, an error is assumed - virtual int BuildPacketStart(void *pData, int MaxLength) { return 0; }; - virtual int BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData) = 0; - virtual int BuildPacketFinalize(void *pData, int MaxLength) { return 0; }; - - // interface for packet receiving - // this function shall return 0 if the packet should be furtherly processed - virtual int ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) = 0; - - // interface for network - virtual void SendCheck(const NETADDR *pAddr, void *pUserData) = 0; - virtual void SendOk(const NETADDR *pAddr, void *pUserData) = 0; - virtual void SendError(const NETADDR *pAddr, void *pUserData) = 0; - virtual void SendList(const NETADDR *pAddr, const void *pData, int DataSize, void *pUserData) = 0; - - static void NetaddrToMastersrv(CMastersrvAddr *pOut, const NETADDR *pIn); - -protected: - IMastersrv *m_pOwner; - const int m_Version; -}; - -class IMastersrvSlaveAdv : public IMastersrvSlave -{ -public: - IMastersrvSlaveAdv(IMastersrv *pOwner, int Version) : IMastersrvSlave(pOwner, Version) {} - virtual ~IMastersrvSlaveAdv() {} - - virtual void SendCount(const NETADDR *pAddr, void *pUserData) { SendPacket(PACKET_COUNT, pAddr, pUserData); } - virtual void SendCheck(const NETADDR *pAddr, void *pUserData) { SendPacket(PACKET_CHECK, pAddr, pUserData); } - virtual void SendOk(const NETADDR *pAddr, void *pUserData) { SendPacket(PACKET_OK, pAddr, pUserData); } - virtual void SendError(const NETADDR *pAddr, void *pUserData) { SendPacket(PACKET_ERROR, pAddr, pUserData); } - virtual void SendList(const NETADDR *pAddr, const void *pData, int DataSize, void *pUserData) - { - m_aPackets[PACKET_LIST].m_DataSize = DataSize; - m_aPackets[PACKET_LIST].m_pData = pData; - SendPacket(PACKET_LIST, pAddr, pUserData); - } - -protected: - virtual void SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData) = 0; - - enum - { - PACKET_COUNT=0, - PACKET_CHECK, - PACKET_OK, - PACKET_ERROR, - PACKET_LIST, - NUM_PACKETS, - }; - CNetChunk m_aPackets[NUM_PACKETS]; -}; - -IMastersrv *CreateMastersrv(); - -IMastersrvSlave *CreateSlave_0_5(IMastersrv *pOwner); -IMastersrvSlave *CreateSlave_0_6(IMastersrv *pOwner); -IMastersrvSlave *CreateSlave_0_7(IMastersrv *pOwner); -IMastersrvSlave *CreateSlave_Ver(IMastersrv *pOwner); - - -#endif +/* (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. */ +#ifndef MASTERSRV_MASTERSRV_H +#define MASTERSRV_MASTERSRV_H +static const int MASTERSERVER_PORT = 8300; + +enum ServerType +{ + SERVERTYPE_INVALID = -1, + SERVERTYPE_NORMAL, + SERVERTYPE_LEGACY +}; + +struct CMastersrvAddr +{ + unsigned char m_aIp[16]; + unsigned char m_aPort[2]; +}; + +static const unsigned char SERVERBROWSE_HEARTBEAT[] = {255, 255, 255, 255, 'b', 'e', 'a', '2'}; + +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'}; + +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'}; + +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'}; + +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'}; + + +// packet headers for the 0.5 branch + +struct CMastersrvAddrLegacy +{ + unsigned char m_aIp[4]; + unsigned char m_aPort[2]; +}; + +static const unsigned char SERVERBROWSE_HEARTBEAT_LEGACY[] = {255, 255, 255, 255, 'b', 'e', 'a', 't'}; + +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'}; + +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'}; +#endif diff --git a/src/mastersrv/mastersrv5.cpp b/src/mastersrv/mastersrv5.cpp deleted file mode 100644 index 17a95b56c..000000000 --- a/src/mastersrv/mastersrv5.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* (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 "mastersrv.h" - -static const unsigned char SERVERBROWSE_HEARTBEAT_LEGACY[] = {255, 255, 255, 255, 'b', 'e', 'a', 't'}; - -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'}; - -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'}; - -class CMastersrvSlave_0_5 : public IMastersrvSlaveAdv -{ -public: - CMastersrvSlave_0_5(IMastersrv *pOwner); - virtual ~CMastersrvSlave_0_5() {} - - virtual int BuildPacketStart(void *pData, int MaxLength); - virtual int BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData); - virtual int ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion); - - virtual void SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData); - - struct CCountPacketData - { - unsigned char m_Header[sizeof(SERVERBROWSE_COUNT_LEGACY)]; - unsigned char m_High; - unsigned char m_Low; - } m_CountData; - - struct CMastersrvAddrLegacy - { - unsigned char m_aIp[4]; - unsigned char m_aPort[2]; - }; - - static void NetaddrToMastersrv(CMastersrvAddrLegacy *pOut, const NETADDR *pIn); -}; - -CMastersrvSlave_0_5::CMastersrvSlave_0_5(IMastersrv *pOwner) - : IMastersrvSlaveAdv(pOwner, IMastersrv::MASTERSRV_0_5) -{ - mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT_LEGACY, sizeof(m_CountData.m_Header)); - - for(int i = 0; i < NUM_PACKETS; i++) - { - m_aPackets[i].m_ClientID = -1; - m_aPackets[i].m_Flags = NETSENDFLAG_CONNLESS|NETSENDFLAG_STATELESS; - } - - m_aPackets[PACKET_COUNT].m_DataSize = sizeof(m_CountData); - m_aPackets[PACKET_COUNT].m_pData = &m_CountData; - - m_aPackets[PACKET_CHECK].m_DataSize = sizeof(SERVERBROWSE_FWCHECK); - m_aPackets[PACKET_CHECK].m_pData = SERVERBROWSE_FWCHECK; - - m_aPackets[PACKET_OK].m_DataSize = sizeof(SERVERBROWSE_FWOK); - m_aPackets[PACKET_OK].m_pData = SERVERBROWSE_FWOK; - - m_aPackets[PACKET_ERROR].m_DataSize = sizeof(SERVERBROWSE_FWERROR); - m_aPackets[PACKET_ERROR].m_pData = SERVERBROWSE_FWERROR; - - dbg_msg("mastersrv", "started mastersrv 0.5"); -} - -int CMastersrvSlave_0_5::BuildPacketStart(void *pData, int MaxLength) -{ - if(MaxLength < sizeof(SERVERBROWSE_LIST_LEGACY)) - return -1; - mem_copy(pData, SERVERBROWSE_LIST_LEGACY, sizeof(SERVERBROWSE_LIST_LEGACY)); - return sizeof(SERVERBROWSE_LIST_LEGACY); -} - -int CMastersrvSlave_0_5::BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData) -{ - if(MaxLength < sizeof(CMastersrvAddrLegacy)) - return -1; - NetaddrToMastersrv((CMastersrvAddrLegacy *)pData, pAddr); - return sizeof(CMastersrvAddrLegacy); -} - -int CMastersrvSlave_0_5::ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) -{ - if(PacketVersion != NET_PACKETVERSION_LEGACY || !(pPacket->m_Flags&NETSENDFLAG_CONNLESS)) - return 0; - - if(Socket == IMastersrv::SOCKET_OP) - { - if(pPacket->m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT_LEGACY)+2 && - mem_comp(pPacket->m_pData, SERVERBROWSE_HEARTBEAT_LEGACY, sizeof(SERVERBROWSE_HEARTBEAT_LEGACY)) == 0) - { - NETADDR Alt; - unsigned char *d = (unsigned char *)pPacket->m_pData; - Alt = pPacket->m_Address; - Alt.port = (d[sizeof(SERVERBROWSE_HEARTBEAT_LEGACY)]<<8) - | d[sizeof(SERVERBROWSE_HEARTBEAT_LEGACY)+1]; - AddCheckserver(&pPacket->m_Address, &Alt, 0); - return 1; - } - else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_GETCOUNT_LEGACY) && - mem_comp(pPacket->m_pData, SERVERBROWSE_GETCOUNT_LEGACY, sizeof(SERVERBROWSE_GETCOUNT_LEGACY)) == 0) - { - int Count = m_pOwner->GetCount(); - m_CountData.m_High = (Count>>8)&0xff; - m_CountData.m_Low = Count&0xff; - SendPacket(PACKET_COUNT, &pPacket->m_Address, 0); - return 1; - } - else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_GETLIST_LEGACY) && - mem_comp(pPacket->m_pData, SERVERBROWSE_GETLIST_LEGACY, sizeof(SERVERBROWSE_GETLIST_LEGACY)) == 0) - { - IMastersrvSlave::SendList(&pPacket->m_Address, 0); - return 1; - } - } - else if(Socket == IMastersrv::SOCKET_CHECKER) - { - if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && - mem_comp(pPacket->m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) - { - AddServer(&pPacket->m_Address, 0); - return 0; // for 0.6 compatiblity - } - } - else - dbg_assert(0, "invalid socket type"); - - return 0; -} - -void CMastersrvSlave_0_5::SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData) -{ - dbg_assert(PacketType >= 0 && PacketType < NUM_PACKETS, "invalid packet type"); - - m_aPackets[PacketType].m_Address = *pAddr; - m_pOwner->Send((PacketType != PACKET_CHECK) ? IMastersrv::SOCKET_OP : IMastersrv::SOCKET_CHECKER, - &m_aPackets[PacketType], NET_TOKEN_NONE, NET_PACKETVERSION_LEGACY); -} - -void CMastersrvSlave_0_5::NetaddrToMastersrv(CMastersrvAddrLegacy *pOut, const NETADDR *pIn) -{ - dbg_assert(pIn->type == NETTYPE_IPV4, "legacy mastersrv addresses only support ipv4"); - - mem_copy(pOut->m_aIp, pIn->ip, 4); - pOut->m_aPort[0] = (pIn->port>>0)&0xff; // little endian - pOut->m_aPort[1] = (pIn->port>>8)&0xff; -} - -IMastersrvSlave *CreateSlave_0_5(IMastersrv *pOwner) -{ - return new CMastersrvSlave_0_5(pOwner); -} - diff --git a/src/mastersrv/mastersrv6.cpp b/src/mastersrv/mastersrv6.cpp deleted file mode 100644 index aaa0f4f4e..000000000 --- a/src/mastersrv/mastersrv6.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* (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 "mastersrv.h" - -class CMastersrvSlave_0_6 : public IMastersrvSlaveAdv -{ -public: - CMastersrvSlave_0_6(IMastersrv *pOwner); - virtual ~CMastersrvSlave_0_6() {} - - virtual int BuildPacketStart(void *pData, int MaxLength); - virtual int BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData); - virtual int ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion); - - virtual void SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData); - - struct CCountPacketData - { - unsigned char m_Header[sizeof(SERVERBROWSE_COUNT)]; - unsigned char m_High; - unsigned char m_Low; - } m_CountData; -}; - -CMastersrvSlave_0_6::CMastersrvSlave_0_6(IMastersrv *pOwner) - : IMastersrvSlaveAdv(pOwner, IMastersrv::MASTERSRV_0_6) -{ - mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(m_CountData.m_Header)); - - for(int i = 0; i < NUM_PACKETS; i++) - { - m_aPackets[i].m_ClientID = -1; - m_aPackets[i].m_Flags = NETSENDFLAG_CONNLESS|NETSENDFLAG_STATELESS; - } - - m_aPackets[PACKET_COUNT].m_DataSize = sizeof(m_CountData); - m_aPackets[PACKET_COUNT].m_pData = &m_CountData; - - m_aPackets[PACKET_CHECK].m_DataSize = sizeof(SERVERBROWSE_FWCHECK); - m_aPackets[PACKET_CHECK].m_pData = SERVERBROWSE_FWCHECK; - - m_aPackets[PACKET_OK].m_DataSize = sizeof(SERVERBROWSE_FWOK); - m_aPackets[PACKET_OK].m_pData = SERVERBROWSE_FWOK; - - m_aPackets[PACKET_ERROR].m_DataSize = sizeof(SERVERBROWSE_FWERROR); - m_aPackets[PACKET_ERROR].m_pData = SERVERBROWSE_FWERROR; - - dbg_msg("mastersrv", "started mastersrv 0.6"); -} - -int CMastersrvSlave_0_6::BuildPacketStart(void *pData, int MaxLength) -{ - if(MaxLength < sizeof(SERVERBROWSE_LIST)) - return -1; - mem_copy(pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)); - return sizeof(SERVERBROWSE_LIST); -} - -int CMastersrvSlave_0_6::BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData) -{ - if(MaxLength < sizeof(CMastersrvAddr)) - return -1; - NetaddrToMastersrv((CMastersrvAddr *)pData, pAddr); - return sizeof(CMastersrvAddr); -} - -int CMastersrvSlave_0_6::ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) -{ - if(PacketVersion != NET_PACKETVERSION_LEGACY || !(pPacket->m_Flags&NETSENDFLAG_CONNLESS)) - return 0; - - if(Socket == IMastersrv::SOCKET_OP) - { - if(pPacket->m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 && - mem_comp(pPacket->m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0) - { - NETADDR Alt; - unsigned char *d = (unsigned char *)pPacket->m_pData; - Alt = pPacket->m_Address; - Alt.port = (d[sizeof(SERVERBROWSE_HEARTBEAT)]<<8) - | d[sizeof(SERVERBROWSE_HEARTBEAT)+1]; - AddCheckserver(&pPacket->m_Address, &Alt, 0); - return 1; - } - else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_GETCOUNT) && - mem_comp(pPacket->m_pData, SERVERBROWSE_GETCOUNT, sizeof(SERVERBROWSE_GETCOUNT)) == 0) - { - int Count = m_pOwner->GetCount(); - m_CountData.m_High = (Count>>8)&0xff; - m_CountData.m_Low = Count&0xff; - SendPacket(PACKET_COUNT, &pPacket->m_Address, 0); - return 1; - } - else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_GETLIST) && - mem_comp(pPacket->m_pData, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0) - { - IMastersrvSlave::SendList(&pPacket->m_Address, 0); - return 1; - } - } - else if(Socket == IMastersrv::SOCKET_CHECKER) - { - if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && - mem_comp(pPacket->m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) - { - AddServer(&pPacket->m_Address, 0); - return 0; // for 0.5 compatiblity - } - } - else - dbg_assert(0, "invalid socket type"); - - return 0; -} - -void CMastersrvSlave_0_6::SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData) -{ - dbg_assert(PacketType >= 0 && PacketType < NUM_PACKETS, "invalid packet type"); - - m_aPackets[PacketType].m_Address = *pAddr; - m_pOwner->Send((PacketType != PACKET_CHECK) ? IMastersrv::SOCKET_OP : IMastersrv::SOCKET_CHECKER, - &m_aPackets[PacketType], NET_TOKEN_NONE, NET_PACKETVERSION_LEGACY); -} - -IMastersrvSlave *CreateSlave_0_6(IMastersrv *pOwner) -{ - return new CMastersrvSlave_0_6(pOwner); -} - diff --git a/src/mastersrv/mastersrv7.cpp b/src/mastersrv/mastersrv7.cpp deleted file mode 100644 index c2fb424da..000000000 --- a/src/mastersrv/mastersrv7.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* (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 "mastersrv.h" - -class CMastersrvSlave_0_7 : public IMastersrvSlaveAdv -{ -public: - CMastersrvSlave_0_7(IMastersrv *pOwner); - virtual ~CMastersrvSlave_0_7() {} - - virtual int BuildPacketStart(void *pData, int MaxLength); - virtual int BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData); - virtual int ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion); - - virtual void SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData); - - struct CCountPacketData - { - unsigned char m_Header[sizeof(SERVERBROWSE_COUNT)]; - unsigned char m_High; - unsigned char m_Low; - } m_CountData; -}; - -CMastersrvSlave_0_7::CMastersrvSlave_0_7(IMastersrv *pOwner) - : IMastersrvSlaveAdv(pOwner, IMastersrv::MASTERSRV_0_7) -{ - mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(m_CountData.m_Header)); - - for(int i = 0; i < NUM_PACKETS; i++) - { - m_aPackets[i].m_ClientID = -1; - m_aPackets[i].m_Flags = NETSENDFLAG_CONNLESS; - } - - m_aPackets[PACKET_COUNT].m_DataSize = sizeof(m_CountData); - m_aPackets[PACKET_COUNT].m_pData = &m_CountData; - - m_aPackets[PACKET_CHECK].m_DataSize = sizeof(SERVERBROWSE_FWCHECK); - m_aPackets[PACKET_CHECK].m_pData = SERVERBROWSE_FWCHECK; - - m_aPackets[PACKET_OK].m_DataSize = sizeof(SERVERBROWSE_FWOK); - m_aPackets[PACKET_OK].m_pData = SERVERBROWSE_FWOK; - - m_aPackets[PACKET_ERROR].m_DataSize = sizeof(SERVERBROWSE_FWERROR); - m_aPackets[PACKET_ERROR].m_pData = SERVERBROWSE_FWERROR; - - dbg_msg("mastersrv", "started mastersrv 0.7"); -} - -int CMastersrvSlave_0_7::BuildPacketStart(void *pData, int MaxLength) -{ - if(MaxLength < sizeof(SERVERBROWSE_LIST)) - return -1; - mem_copy(pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)); - return sizeof(SERVERBROWSE_LIST); -} - -int CMastersrvSlave_0_7::BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData) -{ - if(MaxLength < sizeof(CMastersrvAddr)) - return -1; - NetaddrToMastersrv((CMastersrvAddr *)pData, pAddr); - return sizeof(CMastersrvAddr); -} - -int CMastersrvSlave_0_7::ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) -{ - if(PacketVersion != NET_PACKETVERSION || !(pPacket->m_Flags&NETSENDFLAG_CONNLESS)) - return 0; - - if(Socket == IMastersrv::SOCKET_OP) - { - if(pPacket->m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 && - mem_comp(pPacket->m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0) - { - if(pPacket->m_Flags&NETSENDFLAG_STATELESS) - return -1; - NETADDR Alt; - unsigned char *d = (unsigned char *)pPacket->m_pData; - Alt = pPacket->m_Address; - Alt.port = (d[sizeof(SERVERBROWSE_HEARTBEAT)]<<8) - | d[sizeof(SERVERBROWSE_HEARTBEAT)+1]; - AddCheckserver(&pPacket->m_Address, &Alt, (void *)PacketToken); - return 1; - } - else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_GETCOUNT) && - mem_comp(pPacket->m_pData, SERVERBROWSE_GETCOUNT, sizeof(SERVERBROWSE_GETCOUNT)) == 0) - { - int Count = m_pOwner->GetCount(); - m_CountData.m_High = (Count>>8)&0xff; - m_CountData.m_Low = Count&0xff; - SendPacket(PACKET_COUNT, &pPacket->m_Address, (void *)PacketToken); - return 1; - } - else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_GETLIST) && - mem_comp(pPacket->m_pData, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0) - { - if(pPacket->m_Flags&NETSENDFLAG_STATELESS) - return -1; - IMastersrvSlave::SendList(&pPacket->m_Address, (void *)PacketToken); - return 1; - } - } - else if(Socket == IMastersrv::SOCKET_CHECKER) - { - if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && - mem_comp(pPacket->m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) - { - AddServer(&pPacket->m_Address, (void *)PacketToken); - return 1; - } - } - else - dbg_assert(0, "invalid socket type"); - - return 0; -} - -void CMastersrvSlave_0_7::SendPacket(int PacketType, const NETADDR *pAddr, void *pUserData) -{ - dbg_assert(PacketType >= 0 && PacketType < NUM_PACKETS, "invalid packet type"); - - m_aPackets[PacketType].m_Address = *pAddr; - m_pOwner->Send((PacketType != PACKET_CHECK) ? IMastersrv::SOCKET_OP : IMastersrv::SOCKET_CHECKER, - &m_aPackets[PacketType], (TOKEN) (long int) pUserData, NET_PACKETVERSION); -} - -IMastersrvSlave *CreateSlave_0_7(IMastersrv *pOwner) -{ - return new CMastersrvSlave_0_7(pOwner); -} - diff --git a/src/mastersrv/versionsrv.cpp b/src/mastersrv/versionsrv.cpp deleted file mode 100644 index 58166a703..000000000 --- a/src/mastersrv/versionsrv.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* (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 "mastersrv.h" - -#include - -struct CMapVersion -{ - char m_aName[8]; - unsigned char m_aCrc[4]; - unsigned char m_aSize[4]; -}; - -static CMapVersion s_aMapVersionList[] = { - {"ctf1", {0x06, 0xb5, 0xf1, 0x17}, {0x00, 0x00, 0x12, 0x38}}, - {"ctf2", {0x27, 0xbc, 0x5e, 0xac}, {0x00, 0x00, 0x64, 0x1a}}, - {"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}}, - {"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}}, - {"ctf5", {0xd9, 0x21, 0x29, 0xa0}, {0x00, 0x00, 0x2f, 0x4c}}, - {"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}}, - {"ctf7", {0x1d, 0x35, 0x98, 0x72}, {0x00, 0x00, 0x15, 0x87}}, - {"dm1", {0xf2, 0x15, 0x9e, 0x6e}, {0x00, 0x00, 0x16, 0xad}}, - {"dm2", {0x71, 0x83, 0x98, 0x78}, {0x00, 0x00, 0x21, 0xdf}}, - {"dm6", {0x47, 0x4d, 0xa2, 0x35}, {0x00, 0x00, 0x1e, 0x95}}, - {"dm7", {0x42, 0x6d, 0xa1, 0x67}, {0x00, 0x00, 0x27, 0x2a}}, - {"dm8", {0x85, 0xf1, 0x1e, 0xd6}, {0x00, 0x00, 0x9e, 0xbd}}, - {"dm9", {0x42, 0xd4, 0x77, 0x7e}, {0x00, 0x00, 0x20, 0x11}}, -}; - -static const int s_NumMapVersionItems = sizeof(s_aMapVersionList)/sizeof(CMapVersion); - -static const unsigned char VERSIONSRV_GETVERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 'g'}; -static const unsigned char VERSIONSRV_VERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 's'}; - -static const unsigned char VERSIONSRV_GETMAPLIST[] = {255, 255, 255, 255, 'v', 'm', 'l', 'g'}; -static const unsigned char VERSIONSRV_MAPLIST[] = {255, 255, 255, 255, 'v', 'm', 'l', 's'}; - -class CMastersrvSlave_Ver : public IMastersrvSlave -{ -public: - struct CNetConnData - { - TOKEN m_Token; - int m_Version; - }; - - CMastersrvSlave_Ver(IMastersrv *pOwner); - virtual ~CMastersrvSlave_Ver() {} - - virtual int BuildPacketStart(void *pData, int MaxLength); - virtual int BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData); - virtual int ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion); - - virtual void SendList(const NETADDR *pAddr, const void *pData, int DataSize, void *pUserData); - virtual void SendVersion(const NETADDR *pAddr, TOKEN PacketToken, int PacketVersion); - - // stubs, not needed - virtual void SendCheck(const NETADDR *pAddr, void *pUserData) { dbg_assert(0, "stub"); } - virtual void SendOk(const NETADDR *pAddr, void *pUserData) { dbg_assert(0, "stub"); } - virtual void SendError(const NETADDR *pAddr, void *pUserData) { dbg_assert(0, "stub"); } - - static NETADDR s_NullAddr; - - char m_aVersionPacket[sizeof(VERSIONSRV_VERSION) + sizeof(GAME_RELEASE_VERSION)]; -}; - -NETADDR CMastersrvSlave_Ver::s_NullAddr = { 0 }; - -CMastersrvSlave_Ver::CMastersrvSlave_Ver(IMastersrv *pOwner) - : IMastersrvSlave(pOwner, IMastersrv::MASTERSRV_VER) -{ - for(int i = 0; i < s_NumMapVersionItems; i++) - AddServer(&s_NullAddr, &s_aMapVersionList[i]); - mem_copy(m_aVersionPacket, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)); - mem_copy(m_aVersionPacket + sizeof(VERSIONSRV_VERSION), - GAME_RELEASE_VERSION, sizeof(GAME_RELEASE_VERSION)); - - dbg_msg("mastersrv", "started versionsrv"); -} - -void CMastersrvSlave_Ver::SendVersion(const NETADDR *pAddr, TOKEN PacketToken, int PacketVersion) -{ - CNetChunk Packet; - Packet.m_ClientID = -1; - Packet.m_Address = *pAddr; - Packet.m_Flags = NETSENDFLAG_CONNLESS; - if(PacketVersion == NET_PACKETVERSION_LEGACY) - Packet.m_Flags |= NETSENDFLAG_STATELESS; - Packet.m_pData = m_aVersionPacket; - Packet.m_DataSize = sizeof(m_aVersionPacket); - m_pOwner->Send(IMastersrv::SOCKET_VERSION, &Packet, PacketToken, PacketVersion); -} - -void CMastersrvSlave_Ver::SendList(const NETADDR *pAddr, const void *pData, int DataSize, void *pUserData) -{ - CNetConnData *pConn = (CNetConnData *)pUserData; - CNetChunk Packet; - Packet.m_ClientID = -1; - Packet.m_Address = *pAddr; - Packet.m_Flags = NETSENDFLAG_CONNLESS; - if(pConn->m_Version == NET_PACKETVERSION_LEGACY) - Packet.m_Flags |= NETSENDFLAG_STATELESS; - Packet.m_pData = pData; - Packet.m_DataSize = DataSize; - m_pOwner->Send(IMastersrv::SOCKET_VERSION, &Packet, pConn->m_Token, pConn->m_Version); -} - -int CMastersrvSlave_Ver::BuildPacketStart(void *pData, int MaxLength) -{ - if(MaxLength < sizeof(VERSIONSRV_MAPLIST)) - return -1; - mem_copy(pData, VERSIONSRV_MAPLIST, sizeof(VERSIONSRV_MAPLIST)); - return sizeof(VERSIONSRV_MAPLIST); -} - -int CMastersrvSlave_Ver::BuildPacketAdd(void *pData, int MaxLength, const NETADDR *pAddr, void *pUserData) -{ - if(MaxLength < sizeof(CMapVersion)) - return -1; - mem_copy(pData, pUserData, sizeof(CMapVersion)); - return sizeof(CMapVersion); -} - -int CMastersrvSlave_Ver::ProcessMessage(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, int PacketVersion) -{ - if(Socket != IMastersrv::SOCKET_VERSION) - return 0; - - if(pPacket->m_DataSize == sizeof(VERSIONSRV_GETVERSION) && - mem_comp(pPacket->m_pData, VERSIONSRV_GETVERSION, sizeof(VERSIONSRV_GETVERSION)) == 0) - { - SendVersion(&pPacket->m_Address, PacketToken, PacketVersion); - return 1; - } - else if(pPacket->m_DataSize == sizeof(VERSIONSRV_GETMAPLIST) && - mem_comp(pPacket->m_pData, VERSIONSRV_GETMAPLIST, sizeof(VERSIONSRV_GETMAPLIST)) == 0) - { - if(PacketVersion == NET_PACKETVERSION && - (pPacket->m_Flags&NETSENDFLAG_STATELESS)) - return 1; // new-style packet without token -> drop - CNetConnData Data; - Data.m_Token = PacketToken; - Data.m_Version = PacketVersion; - IMastersrvSlave::SendList(&pPacket->m_Address, &Data); - return 1; - } - return 0; -} - -IMastersrvSlave *CreateSlave_Ver(IMastersrv *pOwner) -{ - return new CMastersrvSlave_Ver(pOwner); -} -