diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b4d6122ed..df753f2bc 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -57,6 +57,8 @@ #include "autoupdate.h" #include "client.h" +#include + #if defined(CONF_FAMILY_WINDOWS) #define _WIN32_WINNT 0x0501 #define WIN32_LEAN_AND_MEAN @@ -336,6 +338,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD if (g_Config.m_ClDummy == 0) m_LastDummyConnectTime = 0; + + m_DDNetSrvListTokenSet = false; } // ----- send functions ----- @@ -1184,18 +1188,33 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) } // ddnet server list - if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_DDNETLIST) + 4 + DDNETLIST_SIZE) && + // Packet: VERSIONSRV_DDNETLIST + char[4] Token + int16 comp_length + int16 plain_length + char[comp_length] + if(pPacket->m_DataSize >= (int)(sizeof(VERSIONSRV_DDNETLIST) + 8) && mem_comp(pPacket->m_pData, VERSIONSRV_DDNETLIST, sizeof(VERSIONSRV_DDNETLIST)) == 0 && mem_comp((char*)pPacket->m_pData+sizeof(VERSIONSRV_DDNETLIST), m_aDDNetSrvListToken, 4) == 0) { - char aBuf[DDNETLIST_SIZE]; - mem_copy(aBuf, (char*)pPacket->m_pData + sizeof(VERSIONSRV_DDNETLIST) + 4, DDNETLIST_SIZE); + // reset random token + m_DDNetSrvListTokenSet = false; + int CompLength = *(short*)((char*)pPacket->m_pData+(sizeof(VERSIONSRV_DDNETLIST)+4)); + int PlainLength = *(short*)((char*)pPacket->m_pData+(sizeof(VERSIONSRV_DDNETLIST)+6)); - IOHANDLE File = m_pStorage->OpenFile("ddnet-servers.json", IOFLAG_WRITE, IStorage::TYPE_SAVE); - if (File) + if (pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_DDNETLIST) + 8 + CompLength)) { - io_write(File, aBuf, sizeof(aBuf)); - io_close(File); + char aBuf[PlainLength]; + uLongf DstLen = PlainLength; + const char *pComp = (char*)pPacket->m_pData+sizeof(VERSIONSRV_DDNETLIST)+8; + + // do decompression of serverlist + if (uncompress((Bytef*)aBuf, &DstLen, (Bytef*)pComp, CompLength) == Z_OK && (int)DstLen == PlainLength) + { + // decompression successful, write plain file + IOHANDLE File = m_pStorage->OpenFile("ddnet-servers.json", IOFLAG_WRITE, IStorage::TYPE_SAVE); + if (File) + { + io_write(File, aBuf, PlainLength); + io_close(File); + } + } } } @@ -3214,6 +3233,7 @@ void CClient::RequestDDNetSrvList() // generate new token for (int i = 0; i < 4; i++) m_aDDNetSrvListToken[i] = rand()&0xff; + m_DDNetSrvListTokenSet = true; char aData[sizeof(VERSIONSRV_GETDDNETLIST)+4]; mem_copy(aData, VERSIONSRV_GETDDNETLIST, sizeof(VERSIONSRV_GETDDNETLIST)); diff --git a/src/engine/client/client.h b/src/engine/client/client.h index de6cfc1ac..e7fc28c0a 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -195,6 +195,7 @@ class CClient : public IClient, public CDemoPlayer::IListner vec3 GetColorV3(int v); char m_aDDNetSrvListToken[4]; + bool m_DDNetSrvListTokenSet; public: IEngine *Engine() { return m_pEngine; } diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 65647a4d6..9f75e9366 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -881,7 +881,7 @@ void CServerBrowser::LoadDDNet() // parse JSON json_value *pCountries = json_parse(aBuf); - if (pCountries->type == json_array) + if (pCountries && pCountries->type == json_array) { for (int i = 0; i < json_array_length(pCountries) && m_NumDDNetCountries < MAX_DDNET_COUNTRIES; i++) { diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp index a911d60a7..853cdb410 100644 --- a/src/versionsrv/versionsrv.cpp +++ b/src/versionsrv/versionsrv.cpp @@ -9,6 +9,8 @@ #include "versionsrv.h" #include "mapversions.h" +#include + enum { MAX_MAPS_PER_PACKET=48, MAX_PACKETS=16, @@ -27,7 +29,11 @@ struct CPacketData CPacketData m_aPackets[MAX_PACKETS]; static int m_NumPackets = 0; unsigned char m_aNews[NEWS_SIZE]; + unsigned char m_aServerList[DDNETLIST_SIZE]; +int m_ServerListPlainLength = 0; +int m_ServerListCompLength = 0; +bool m_ServerListLoaded = false; static CNetClient g_NetOp; // main @@ -72,13 +78,27 @@ void ReadNews() void ReadServerList() { + mem_zero(m_aServerList, sizeof(m_aServerList)); + IOHANDLE File = io_open("serverlist.json", IOFLAG_READ); if (!File) return; - io_read(File, m_aServerList, DDNETLIST_SIZE); + int PlainLength = io_length(File); + char aPlain[PlainLength]; + io_read(File, aPlain, PlainLength); io_close(File); + + // compress + uLongf DstLen = DDNETLIST_SIZE; + + if (compress((Bytef*)m_aServerList, &DstLen, (Bytef*)aPlain, PlainLength) == Z_OK) + { + m_ServerListLoaded = true; + m_ServerListPlainLength = PlainLength; + m_ServerListCompLength = DstLen; + } } void SendVer(NETADDR *pAddr) @@ -115,14 +135,20 @@ void SendNews(NETADDR *pAddr) g_NetOp.Send(&p); } +// Packet: VERSIONSRV_DDNETLIST + char[4] Token + int16 comp_length + int16 plain_length + char[comp_length] void SendServerList(NETADDR *pAddr, const char *Token) { CNetChunk p; - unsigned char aData[DDNETLIST_SIZE + sizeof(VERSIONSRV_DDNETLIST) + 4]; + unsigned char aData[sizeof(VERSIONSRV_DDNETLIST) + 4 + 2 + 2 + m_ServerListCompLength]; + short WordCompLength = m_ServerListCompLength; + short WordPlainLength = m_ServerListPlainLength; mem_copy(aData, VERSIONSRV_DDNETLIST, sizeof(VERSIONSRV_DDNETLIST)); - mem_copy(aData + sizeof(VERSIONSRV_NEWS), Token, 4); // send back token - mem_copy(aData + sizeof(VERSIONSRV_NEWS) + 4, m_aServerList, DDNETLIST_SIZE); + mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST), Token, 4); // send back token + mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST)+4, &WordCompLength, 2); // compressed length + mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST)+6, &WordPlainLength, 2); // plain length + + mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST) + 8, m_aServerList, m_ServerListCompLength); p.m_ClientID = -1; p.m_Address = *pAddr; @@ -204,7 +230,8 @@ int main(int argc, char **argv) // ignore_convention } } - if(Packet.m_DataSize == sizeof(VERSIONSRV_GETDDNETLIST) + 4 && + if(m_ServerListLoaded && + Packet.m_DataSize == sizeof(VERSIONSRV_GETDDNETLIST) + 4 && mem_comp(Packet.m_pData, VERSIONSRV_GETDDNETLIST, sizeof(VERSIONSRV_GETDDNETLIST)) == 0) { char aToken[4];