diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index d4c30778f..f0cd1d99a 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -105,4 +105,7 @@ MACRO_CONFIG_INT(DbgGraphs, dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance gr MACRO_CONFIG_INT(DbgHitch, dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings") MACRO_CONFIG_STR(DbgStressServer, dbg_stress_server, 32, "localhost", CFGFLAG_CLIENT, "Server to stress") MACRO_CONFIG_INT(DbgResizable, dbg_resizable, 0, 0, 0, CFGFLAG_CLIENT, "Enables window resizing") + +MACRO_CONFIG_STR(MsServices, ms_services, 8, "567", CFGFLAG_MASTER, "Specifies the services to start. Accepted values: 567v") + #endif diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 8ed24d5bc..fb591ffa2 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -110,8 +110,7 @@ private: IConsole *m_pConsole; CNetBan m_NetBan; - CNetClient m_NetOp; - CNetClient m_NetChecker; + CNetClient m_aNets[NUM_SOCKETS]; int64 m_BanRefreshTime; int64 m_PacketRefreshTime; @@ -181,30 +180,51 @@ int CMastersrv::Init() m_NetBan.Init(m_pConsole, Kernel()->RequestInterface()); + int Services = 0; + if(str_find(g_Config.m_MsServices, "5")) + Services |= 1<ProcessMessage(SOCKET_OP, &Packet, Token, Version) != 0) - break; - } - } - - // process packets - while(m_NetChecker.Recv(&Packet, &Token, &Version)) - { - // check if the server is banned - if(m_NetBan.IsBanned(&Packet.m_Address, 0, 0)) - continue; - - for(int s = 0; s < NUM_MASTERSRV; s++) - if(m_aSlaves[s].m_pSlave) - if(m_aSlaves[s].m_pSlave->ProcessMessage(SOCKET_CHECKER, &Packet, Token, Version) != 0) - break; + for(int s = 0; s < NUM_MASTERSRV; s++) + if(m_aSlaves[s].m_pSlave) + { + if(m_aSlaves[s].m_pSlave->ProcessMessage(i, &Packet, Token, Version) != 0) + break; + } + } } int64 Now = time_get(); @@ -328,6 +343,8 @@ void CMastersrv::UpdateServers() void CMastersrv::BuildPackets() { bool aPreparePacket[NUM_MASTERSRV]; + int BytesWritten; + for(int s = 0; s < NUM_MASTERSRV; s++) { m_aSlaves[s].m_NumPackets = 0; @@ -344,14 +361,13 @@ void CMastersrv::BuildPackets() CMastersrvSlave::CPacket *pPacket = &pSlaveData->m_aPackets[pSlaveData->m_NumPackets - 1]; dbg_assert(pSlave != 0, "attempting to access uninitalised slave"); - int BytesWritten; - 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]; @@ -380,12 +396,15 @@ void CMastersrv::BuildPackets() { 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]; - dbg_assert(pSlave->BuildPacketFinalize(&pPacket->m_aData[pPacket->m_Size], NET_MAX_PAYLOAD - pPacket->m_Size) >= 0, "final build packet finalisation failed"); + 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; } } @@ -471,13 +490,7 @@ int CMastersrv::Send(int Socket, const CNetChunk *pPacket, TOKEN PacketToken, in { dbg_assert(Socket >= 0 && Socket < NUM_SOCKETS, "attempting to send via non-existant socket"); - CNetClient *pNet = 0; - if(Socket == SOCKET_OP) - pNet = &m_NetOp; - else if(Socket == SOCKET_CHECKER) - pNet = &m_NetChecker; - - pNet->Send((CNetChunk *)pPacket, PacketToken, PacketVersion); + m_aNets[Socket].Send((CNetChunk *)pPacket, PacketToken, PacketVersion); return 0; } diff --git a/src/mastersrv/mastersrv.h b/src/mastersrv/mastersrv.h index 8b63cd2ac..ff7dfbb43 100644 --- a/src/mastersrv/mastersrv.h +++ b/src/mastersrv/mastersrv.h @@ -35,6 +35,8 @@ class IMastersrv; enum { MASTERSERVER_PORT=8300, + MASTERSERVER_CHECKER_PORT=MASTERSERVER_PORT+1, + VERSIONSERVER_PORT=8302, }; class IMastersrv : public IInterface @@ -46,10 +48,12 @@ public: MASTERSRV_0_7=0, MASTERSRV_0_6, MASTERSRV_0_5, + MASTERSRV_VER, NUM_MASTERSRV, SOCKET_OP=0, SOCKET_CHECKER, + SOCKET_VERSION, NUM_SOCKETS, }; @@ -139,6 +143,7 @@ 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 diff --git a/src/mastersrv/mastersrv5.cpp b/src/mastersrv/mastersrv5.cpp index 1f556af13..17a95b56c 100644 --- a/src/mastersrv/mastersrv5.cpp +++ b/src/mastersrv/mastersrv5.cpp @@ -61,6 +61,8 @@ CMastersrvSlave_0_5::CMastersrvSlave_0_5(IMastersrv *pOwner) 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) diff --git a/src/mastersrv/mastersrv6.cpp b/src/mastersrv/mastersrv6.cpp index bf4f07c1d..aaa0f4f4e 100644 --- a/src/mastersrv/mastersrv6.cpp +++ b/src/mastersrv/mastersrv6.cpp @@ -45,6 +45,8 @@ CMastersrvSlave_0_6::CMastersrvSlave_0_6(IMastersrv *pOwner) 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) diff --git a/src/mastersrv/mastersrv7.cpp b/src/mastersrv/mastersrv7.cpp index d749421f2..c2fb424da 100644 --- a/src/mastersrv/mastersrv7.cpp +++ b/src/mastersrv/mastersrv7.cpp @@ -45,6 +45,8 @@ CMastersrvSlave_0_7::CMastersrvSlave_0_7(IMastersrv *pOwner) 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) diff --git a/src/mastersrv/versionsrv.cpp b/src/mastersrv/versionsrv.cpp new file mode 100644 index 000000000..58166a703 --- /dev/null +++ b/src/mastersrv/versionsrv.cpp @@ -0,0 +1,155 @@ +/* (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); +} +