diff options
| author | oy <Tom_Adams@web.de> | 2011-03-17 17:41:57 +0100 |
|---|---|---|
| committer | oy <Tom_Adams@web.de> | 2011-03-17 17:41:57 +0100 |
| commit | b939d3822882c5061f5e3ddfb3fc3b13b116fe24 (patch) | |
| tree | 0729cf0246d629861d3905ba76327e5bfab48857 | |
| parent | b4bec5335960f78a0ad6ac6f0c491cb76375bd56 (diff) | |
| download | zcatch-b939d3822882c5061f5e3ddfb3fc3b13b116fe24.tar.gz zcatch-b939d3822882c5061f5e3ddfb3fc3b13b116fe24.zip | |
made the client check for valid address on connectionless packets from master/version server
| -rw-r--r-- | src/engine/client/client.cpp | 792 | ||||
| -rw-r--r-- | src/engine/client/client.h | 12 | ||||
| -rw-r--r-- | src/engine/client/srvbrowse.cpp | 2 | ||||
| -rw-r--r-- | src/versionsrv/versionsrv.h | 2 |
4 files changed, 415 insertions, 393 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 6d228811..49abd2e9 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -468,7 +468,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD mem_zero(m_aSnapshots, sizeof(m_aSnapshots)); m_RecivedSnapshots = 0; - m_VersionInfo.m_State = 0; + m_VersionInfo.m_State = CVersionInfo::STATE_INIT; } // ----- send functions ----- @@ -1027,225 +1027,181 @@ int CClient::PlayerScoreComp(const void *a, const void *b) return -1; } -void CClient::ProcessPacket(CNetChunk *pPacket) +void CClient::ProcessConnlessPacket(CNetChunk *pPacket) { - if(pPacket->m_ClientID == -1) + // version info + if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) && + mem_comp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0 && + m_VersionInfo.m_State == CVersionInfo::STATE_READY && net_addr_comp(&pPacket->m_Address, &m_VersionInfo.m_VersionServeraddr.m_Addr) == 0) { - // connectionlesss - if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) && - mem_comp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0) - { - unsigned char *pVersionData = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION); - int VersionMatch = !mem_comp(pVersionData, VERSION_DATA, sizeof(VERSION_DATA)); + unsigned char *pVersionData = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION); + int VersionMatch = !mem_comp(pVersionData, VERSION_DATA, sizeof(VERSION_DATA)); - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "version does %s (%d.%d.%d)", - VersionMatch ? "match" : "NOT match", - pVersionData[1], pVersionData[2], pVersionData[3]); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/version", aBuf); + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "version does %s (%d.%d.%d)", + VersionMatch ? "match" : "NOT match", + pVersionData[1], pVersionData[2], pVersionData[3]); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/version", aBuf); - // assume version is out of date when version-data doesn't match - if (!VersionMatch) - { - str_format(m_aVersionStr, sizeof(m_aVersionStr), "%d.%d.%d", pVersionData[1], pVersionData[2], pVersionData[3]); - } + // assume version is out of date when version-data doesn't match + if (!VersionMatch) + { + str_format(m_aVersionStr, sizeof(m_aVersionStr), "%d.%d.%d", pVersionData[1], pVersionData[2], pVersionData[3]); } + } - if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_LIST) && - mem_comp(pPacket->m_pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0) + // server list from master server + if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_LIST) && + mem_comp(pPacket->m_pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0) + { + // check for valid master server address + bool Valid = false; + for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; ++i) { - int Size = pPacket->m_DataSize-sizeof(SERVERBROWSE_LIST); - int Num = Size/sizeof(MASTERSRV_ADDR); - MASTERSRV_ADDR *pAddrs = (MASTERSRV_ADDR *)((char*)pPacket->m_pData+sizeof(SERVERBROWSE_LIST)); - int i; - - for(i = 0; i < Num; i++) + NETADDR Addr = m_pMasterServer->GetAddr(i); + if(net_addr_comp(&pPacket->m_Address, &Addr) == 0) { - NETADDR Addr; - - // convert address - mem_zero(&Addr, sizeof(Addr)); - Addr.type = NETTYPE_IPV4; - Addr.ip[0] = pAddrs[i].m_aIp[0]; - Addr.ip[1] = pAddrs[i].m_aIp[1]; - Addr.ip[2] = pAddrs[i].m_aIp[2]; - Addr.ip[3] = pAddrs[i].m_aIp[3]; - Addr.port = (pAddrs[i].m_aPort[1]<<8) | pAddrs[i].m_aPort[0]; - - m_ServerBrowser.Set(Addr, IServerBrowser::SET_MASTER_ADD, -1, 0x0); + Valid = true; + break; } } + if(!Valid) + return; - { - int PacketType = 0; - if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && mem_comp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0) - PacketType = 3; - - if(PacketType) - { - // we got ze info - CUnpacker Up; - CServerInfo Info = {0}; - - Up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO)); - int Token = str_toint(Up.GetString()); - str_copy(Info.m_aVersion, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aVersion)); - str_copy(Info.m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aName)); - str_copy(Info.m_aMap, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aMap)); - str_copy(Info.m_aGameType, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aGameType)); - Info.m_Flags = str_toint(Up.GetString()); - Info.m_NumPlayers = str_toint(Up.GetString()); - Info.m_MaxPlayers = str_toint(Up.GetString()); - - // don't add invalid info to the server browser list - if(Info.m_NumPlayers < 0 || Info.m_NumPlayers > MAX_CLIENTS || Info.m_MaxPlayers < 0 || Info.m_MaxPlayers > MAX_CLIENTS) - return; - - str_format(Info.m_aAddress, sizeof(Info.m_aAddress), "%d.%d.%d.%d:%d", - pPacket->m_Address.ip[0], pPacket->m_Address.ip[1], pPacket->m_Address.ip[2], - pPacket->m_Address.ip[3], pPacket->m_Address.port); - - for(int i = 0; i < Info.m_NumPlayers; i++) - { - str_copy(Info.m_aPlayers[i].m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aPlayers[i].m_aName)); - str_copy(Info.m_aPlayers[i].m_aClan, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aPlayers[i].m_aClan)); - Info.m_aPlayers[i].m_Country = str_toint(Up.GetString()); - Info.m_aPlayers[i].m_Score = str_toint(Up.GetString()); - } - - if(!Up.Error()) - { - // sort players - qsort(Info.m_aPlayers, Info.m_NumPlayers, sizeof(*Info.m_aPlayers), PlayerScoreComp); + int Size = pPacket->m_DataSize-sizeof(SERVERBROWSE_LIST); + int Num = Size/sizeof(MASTERSRV_ADDR); + MASTERSRV_ADDR *pAddrs = (MASTERSRV_ADDR *)((char*)pPacket->m_pData+sizeof(SERVERBROWSE_LIST)); + int i; - if(net_addr_comp(&m_ServerAddress, &pPacket->m_Address) == 0) - { - mem_copy(&m_CurrentServerInfo, &Info, sizeof(m_CurrentServerInfo)); - m_CurrentServerInfo.m_NetAddr = m_ServerAddress; - m_CurrentServerInfoRequestTime = -1; - } - else - m_ServerBrowser.Set(pPacket->m_Address, IServerBrowser::SET_TOKEN, Token, &Info); - } - } + for(i = 0; i < Num; i++) + { + NETADDR Addr; + + // convert address + mem_zero(&Addr, sizeof(Addr)); + Addr.type = NETTYPE_IPV4; + Addr.ip[0] = pAddrs[i].m_aIp[0]; + Addr.ip[1] = pAddrs[i].m_aIp[1]; + Addr.ip[2] = pAddrs[i].m_aIp[2]; + Addr.ip[3] = pAddrs[i].m_aIp[3]; + Addr.port = (pAddrs[i].m_aPort[1]<<8) | pAddrs[i].m_aPort[0]; + + m_ServerBrowser.Set(Addr, IServerBrowser::SET_MASTER_ADD, -1, 0x0); } } - else - { - CUnpacker Unpacker; - Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize); - // unpack msgid and system flag - int Msg = Unpacker.GetInt(); - int Sys = Msg&1; - Msg >>= 1; - - if(Unpacker.Error()) + // server info + if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && mem_comp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0) + { + // we got ze info + CUnpacker Up; + CServerInfo Info = {0}; + + Up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO)); + int Token = str_toint(Up.GetString()); + str_copy(Info.m_aVersion, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aVersion)); + str_copy(Info.m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aName)); + str_copy(Info.m_aMap, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aMap)); + str_copy(Info.m_aGameType, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aGameType)); + Info.m_Flags = str_toint(Up.GetString()); + Info.m_NumPlayers = str_toint(Up.GetString()); + Info.m_MaxPlayers = str_toint(Up.GetString()); + + // don't add invalid info to the server browser list + if(Info.m_NumPlayers < 0 || Info.m_NumPlayers > MAX_CLIENTS || Info.m_MaxPlayers < 0 || Info.m_MaxPlayers > MAX_CLIENTS) return; - if(Sys) - { - // system message - if(Msg == NETMSG_MAP_CHANGE) - { - const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES); - int MapCrc = Unpacker.GetInt(); - int MapSize = Unpacker.GetInt(); - const char *pError = 0; + str_format(Info.m_aAddress, sizeof(Info.m_aAddress), "%d.%d.%d.%d:%d", + pPacket->m_Address.ip[0], pPacket->m_Address.ip[1], pPacket->m_Address.ip[2], + pPacket->m_Address.ip[3], pPacket->m_Address.port); - if(Unpacker.Error()) - return; + for(int i = 0; i < Info.m_NumPlayers; i++) + { + str_copy(Info.m_aPlayers[i].m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aPlayers[i].m_aName)); + str_copy(Info.m_aPlayers[i].m_aClan, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aPlayers[i].m_aClan)); + Info.m_aPlayers[i].m_Country = str_toint(Up.GetString()); + Info.m_aPlayers[i].m_Score = str_toint(Up.GetString()); + } - for(int i = 0; pMap[i]; i++) // protect the player from nasty map names - { - if(pMap[i] == '/' || pMap[i] == '\\') - pError = "strange character in map name"; - } + if(!Up.Error()) + { + // sort players + qsort(Info.m_aPlayers, Info.m_NumPlayers, sizeof(*Info.m_aPlayers), PlayerScoreComp); - if(MapSize < 0) - pError = "invalid map size"; + if(net_addr_comp(&m_ServerAddress, &pPacket->m_Address) == 0) + { + mem_copy(&m_CurrentServerInfo, &Info, sizeof(m_CurrentServerInfo)); + m_CurrentServerInfo.m_NetAddr = m_ServerAddress; + m_CurrentServerInfoRequestTime = -1; + } + else + m_ServerBrowser.Set(pPacket->m_Address, IServerBrowser::SET_TOKEN, Token, &Info); + } + } +} - if(pError) - DisconnectWithReason(pError); - else - { - pError = LoadMapSearch(pMap, MapCrc); +void CClient::ProcessServerPacket(CNetChunk *pPacket) +{ + CUnpacker Unpacker; + Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize); - if(!pError) - { - m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done"); - SendReady(); - } - else - { - str_format(m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename), "downloadedmaps/%s_%08x.map", pMap, MapCrc); + // unpack msgid and system flag + int Msg = Unpacker.GetInt(); + int Sys = Msg&1; + Msg >>= 1; - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilename); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf); + if(Unpacker.Error()) + return; - m_MapdownloadChunk = 0; - str_copy(m_aMapdownloadName, pMap, sizeof(m_aMapdownloadName)); - if(m_MapdownloadFile) - io_close(m_MapdownloadFile); - m_MapdownloadFile = Storage()->OpenFile(m_aMapdownloadFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); - m_MapdownloadCrc = MapCrc; - m_MapdownloadTotalsize = MapSize; - m_MapdownloadAmount = 0; + if(Sys) + { + // system message + if(Msg == NETMSG_MAP_CHANGE) + { + const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES); + int MapCrc = Unpacker.GetInt(); + int MapSize = Unpacker.GetInt(); + const char *pError = 0; - CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA); - Msg.AddInt(m_MapdownloadChunk); - SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); + if(Unpacker.Error()) + return; - if(g_Config.m_Debug) - { - str_format(aBuf, sizeof(aBuf), "requested chunk %d", m_MapdownloadChunk); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", aBuf); - } - } - } - } - else if(Msg == NETMSG_MAP_DATA) + for(int i = 0; pMap[i]; i++) // protect the player from nasty map names { - int Last = Unpacker.GetInt(); - int MapCRC = Unpacker.GetInt(); - int Chunk = Unpacker.GetInt(); - int Size = Unpacker.GetInt(); - const unsigned char *pData = Unpacker.GetRaw(Size); - - // check fior errors - if(Unpacker.Error() || Size <= 0 || MapCRC != m_MapdownloadCrc || Chunk != m_MapdownloadChunk || !m_MapdownloadFile) - return; + if(pMap[i] == '/' || pMap[i] == '\\') + pError = "strange character in map name"; + } - io_write(m_MapdownloadFile, pData, Size); + if(MapSize < 0) + pError = "invalid map size"; - m_MapdownloadAmount += Size; + if(pError) + DisconnectWithReason(pError); + else + { + pError = LoadMapSearch(pMap, MapCrc); - if(Last) + if(!pError) { - const char *pError; - m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map"); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done"); + SendReady(); + } + else + { + str_format(m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename), "downloadedmaps/%s_%08x.map", pMap, MapCrc); + + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilename); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf); + m_MapdownloadChunk = 0; + str_copy(m_aMapdownloadName, pMap, sizeof(m_aMapdownloadName)); if(m_MapdownloadFile) io_close(m_MapdownloadFile); - m_MapdownloadFile = 0; + m_MapdownloadFile = Storage()->OpenFile(m_aMapdownloadFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); + m_MapdownloadCrc = MapCrc; + m_MapdownloadTotalsize = MapSize; m_MapdownloadAmount = 0; - m_MapdownloadTotalsize = -1; - - // load map - pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, m_MapdownloadCrc); - if(!pError) - { - m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done"); - SendReady(); - } - else - DisconnectWithReason(pError); - } - else - { - // request new chunk - m_MapdownloadChunk++; CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA); Msg.AddInt(m_MapdownloadChunk); @@ -1253,256 +1209,309 @@ void CClient::ProcessPacket(CNetChunk *pPacket) if(g_Config.m_Debug) { - char aBuf[256]; str_format(aBuf, sizeof(aBuf), "requested chunk %d", m_MapdownloadChunk); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", aBuf); } } } - else if(Msg == NETMSG_CON_READY) + } + else if(Msg == NETMSG_MAP_DATA) + { + int Last = Unpacker.GetInt(); + int MapCRC = Unpacker.GetInt(); + int Chunk = Unpacker.GetInt(); + int Size = Unpacker.GetInt(); + const unsigned char *pData = Unpacker.GetRaw(Size); + + // check fior errors + if(Unpacker.Error() || Size <= 0 || MapCRC != m_MapdownloadCrc || Chunk != m_MapdownloadChunk || !m_MapdownloadFile) + return; + + io_write(m_MapdownloadFile, pData, Size); + + m_MapdownloadAmount += Size; + + if(Last) { - GameClient()->OnConnected(); + const char *pError; + m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map"); + + if(m_MapdownloadFile) + io_close(m_MapdownloadFile); + m_MapdownloadFile = 0; + m_MapdownloadAmount = 0; + m_MapdownloadTotalsize = -1; + + // load map + pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, m_MapdownloadCrc); + if(!pError) + { + m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done"); + SendReady(); + } + else + DisconnectWithReason(pError); } - else if(Msg == NETMSG_PING) + else { - CMsgPacker Msg(NETMSG_PING_REPLY); - SendMsgEx(&Msg, 0); + // request new chunk + m_MapdownloadChunk++; + + CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA); + Msg.AddInt(m_MapdownloadChunk); + SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); + + if(g_Config.m_Debug) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "requested chunk %d", m_MapdownloadChunk); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", aBuf); + } } - else if(Msg == NETMSG_RCON_AUTH_STATUS) + } + else if(Msg == NETMSG_CON_READY) + { + GameClient()->OnConnected(); + } + else if(Msg == NETMSG_PING) + { + CMsgPacker Msg(NETMSG_PING_REPLY); + SendMsgEx(&Msg, 0); + } + else if(Msg == NETMSG_RCON_AUTH_STATUS) + { + int Result = Unpacker.GetInt(); + if(Unpacker.Error() == 0) + m_RconAuthed = Result; + } + else if(Msg == NETMSG_RCON_LINE) + { + const char *pLine = Unpacker.GetString(); + if(Unpacker.Error() == 0) + GameClient()->OnRconLine(pLine); + } + else if(Msg == NETMSG_PING_REPLY) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "latency %.2f", (time_get() - m_PingStartTime)*1000 / (float)time_freq()); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client/network", aBuf); + } + else if(Msg == NETMSG_INPUTTIMING) + { + int InputPredTick = Unpacker.GetInt(); + int TimeLeft = Unpacker.GetInt(); + + // adjust our prediction time + int64 Target = 0; + for(int k = 0; k < 200; k++) { - int Result = Unpacker.GetInt(); - if(Unpacker.Error() == 0) - m_RconAuthed = Result; + if(m_aInputs[k].m_Tick == InputPredTick) + { + Target = m_aInputs[k].m_PredictedTime + (time_get() - m_aInputs[k].m_Time); + Target = Target - (int64)(((TimeLeft-PREDICTION_MARGIN)/1000.0f)*time_freq()); + break; + } } - else if(Msg == NETMSG_RCON_LINE) + + if(Target) + m_PredictedTime.Update(&m_InputtimeMarginGraph, Target, TimeLeft, 1); + } + else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY) + { + int NumParts = 1; + int Part = 0; + int GameTick = Unpacker.GetInt(); + int DeltaTick = GameTick-Unpacker.GetInt(); + int PartSize = 0; + int Crc = 0; + int CompleteSize = 0; + const char *pData = 0; + + // we are not allowed to process snapshot yet + if(State() < IClient::STATE_LOADING) + return; + + if(Msg == NETMSG_SNAP) { - const char *pLine = Unpacker.GetString(); - if(Unpacker.Error() == 0) - GameClient()->OnRconLine(pLine); + NumParts = Unpacker.GetInt(); + Part = Unpacker.GetInt(); } - else if(Msg == NETMSG_PING_REPLY) + + if(Msg != NETMSG_SNAPEMPTY) { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "latency %.2f", (time_get() - m_PingStartTime)*1000 / (float)time_freq()); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client/network", aBuf); + Crc = Unpacker.GetInt(); + PartSize = Unpacker.GetInt(); } - else if(Msg == NETMSG_INPUTTIMING) - { - int InputPredTick = Unpacker.GetInt(); - int TimeLeft = Unpacker.GetInt(); - // adjust our prediction time - int64 Target = 0; - for(int k = 0; k < 200; k++) - { - if(m_aInputs[k].m_Tick == InputPredTick) - { - Target = m_aInputs[k].m_PredictedTime + (time_get() - m_aInputs[k].m_Time); - Target = Target - (int64)(((TimeLeft-PREDICTION_MARGIN)/1000.0f)*time_freq()); - break; - } - } + pData = (const char *)Unpacker.GetRaw(PartSize); - if(Target) - m_PredictedTime.Update(&m_InputtimeMarginGraph, Target, TimeLeft, 1); - } - else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY) - { - int NumParts = 1; - int Part = 0; - int GameTick = Unpacker.GetInt(); - int DeltaTick = GameTick-Unpacker.GetInt(); - int PartSize = 0; - int Crc = 0; - int CompleteSize = 0; - const char *pData = 0; - - // we are not allowed to process snapshot yet - if(State() < IClient::STATE_LOADING) - return; - - if(Msg == NETMSG_SNAP) - { - NumParts = Unpacker.GetInt(); - Part = Unpacker.GetInt(); - } + if(Unpacker.Error()) + return; - if(Msg != NETMSG_SNAPEMPTY) + if(GameTick >= m_CurrentRecvTick) + { + if(GameTick != m_CurrentRecvTick) { - Crc = Unpacker.GetInt(); - PartSize = Unpacker.GetInt(); + m_SnapshotParts = 0; + m_CurrentRecvTick = GameTick; } - pData = (const char *)Unpacker.GetRaw(PartSize); + // TODO: clean this up abit + mem_copy((char*)m_aSnapshotIncommingData + Part*MAX_SNAPSHOT_PACKSIZE, pData, PartSize); + m_SnapshotParts |= 1<<Part; - if(Unpacker.Error()) - return; - - if(GameTick >= m_CurrentRecvTick) + if(m_SnapshotParts == (unsigned)((1<<NumParts)-1)) { - if(GameTick != m_CurrentRecvTick) + static CSnapshot Emptysnap; + CSnapshot *pDeltaShot = &Emptysnap; + int PurgeTick; + void *pDeltaData; + int DeltaSize; + unsigned char aTmpBuffer2[CSnapshot::MAX_SIZE]; + unsigned char aTmpBuffer3[CSnapshot::MAX_SIZE]; + CSnapshot *pTmpBuffer3 = (CSnapshot*)aTmpBuffer3; // Fix compiler warning for strict-aliasing + int SnapSize; + + CompleteSize = (NumParts-1) * MAX_SNAPSHOT_PACKSIZE + PartSize; + + // reset snapshoting + m_SnapshotParts = 0; + + // find snapshot that we should use as delta + Emptysnap.Clear(); + + // find delta + if(DeltaTick >= 0) { - m_SnapshotParts = 0; - m_CurrentRecvTick = GameTick; - } - - // TODO: clean this up abit - mem_copy((char*)m_aSnapshotIncommingData + Part*MAX_SNAPSHOT_PACKSIZE, pData, PartSize); - m_SnapshotParts |= 1<<Part; - - if(m_SnapshotParts == (unsigned)((1<<NumParts)-1)) - { - static CSnapshot Emptysnap; - CSnapshot *pDeltaShot = &Emptysnap; - int PurgeTick; - void *pDeltaData; - int DeltaSize; - unsigned char aTmpBuffer2[CSnapshot::MAX_SIZE]; - unsigned char aTmpBuffer3[CSnapshot::MAX_SIZE]; - CSnapshot *pTmpBuffer3 = (CSnapshot*)aTmpBuffer3; // Fix compiler warning for strict-aliasing - int SnapSize; - - CompleteSize = (NumParts-1) * MAX_SNAPSHOT_PACKSIZE + PartSize; - - // reset snapshoting - m_SnapshotParts = 0; - - // find snapshot that we should use as delta - Emptysnap.Clear(); - - // find delta - if(DeltaTick >= 0) - { - int DeltashotSize = m_SnapshotStorage.Get(DeltaTick, 0, &pDeltaShot, 0); - - if(DeltashotSize < 0) - { - // couldn't find the delta snapshots that the server used - // to compress this snapshot. force the server to resync - if(g_Config.m_Debug) - { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "error, couldn't find the delta snapshot"); - m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf); - } - - // ack snapshot - // TODO: combine this with the input message - m_AckGameTick = -1; - return; - } - } - - // decompress snapshot - pDeltaData = m_SnapshotDelta.EmptyDelta(); - DeltaSize = sizeof(int)*3; - - if(CompleteSize) - { - int IntSize = CVariableInt::Decompress(m_aSnapshotIncommingData, CompleteSize, aTmpBuffer2); - - if(IntSize < 0) // failure during decompression, bail - return; + int DeltashotSize = m_SnapshotStorage.Get(DeltaTick, 0, &pDeltaShot, 0); - pDeltaData = aTmpBuffer2; - DeltaSize = IntSize; - } - - // unpack delta - PurgeTick = DeltaTick; - SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize); - if(SnapSize < 0) - { - m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "delta unpack failed!"); - return; - } - - if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc) + if(DeltashotSize < 0) { + // couldn't find the delta snapshots that the server used + // to compress this snapshot. force the server to resync if(g_Config.m_Debug) { char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d", - m_SnapCrcErrors, GameTick, Crc, pTmpBuffer3->Crc(), CompleteSize, DeltaTick); + str_format(aBuf, sizeof(aBuf), "error, couldn't find the delta snapshot"); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf); } - m_SnapCrcErrors++; - if(m_SnapCrcErrors > 10) - { - // to many errors, send reset - m_AckGameTick = -1; - SendInput(); - m_SnapCrcErrors = 0; - } + // ack snapshot + // TODO: combine this with the input message + m_AckGameTick = -1; return; } - else - { - if(m_SnapCrcErrors) - m_SnapCrcErrors--; - } + } - // purge old snapshots - PurgeTick = DeltaTick; - if(m_aSnapshots[SNAP_PREV] && m_aSnapshots[SNAP_PREV]->m_Tick < PurgeTick) - PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick; - if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_CURRENT]->m_Tick < PurgeTick) - PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick; - m_SnapshotStorage.PurgeUntil(PurgeTick); + // decompress snapshot + pDeltaData = m_SnapshotDelta.EmptyDelta(); + DeltaSize = sizeof(int)*3; - // add new - m_SnapshotStorage.Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1); + if(CompleteSize) + { + int IntSize = CVariableInt::Decompress(m_aSnapshotIncommingData, CompleteSize, aTmpBuffer2); - // add snapshot to demo - if(m_DemoRecorder.IsRecording()) - { - // write snapshot - m_DemoRecorder.RecordSnapshot(GameTick, pTmpBuffer3, SnapSize); - } + if(IntSize < 0) // failure during decompression, bail + return; - // apply snapshot, cycle pointers - m_RecivedSnapshots++; + pDeltaData = aTmpBuffer2; + DeltaSize = IntSize; + } - m_CurrentRecvTick = GameTick; + // unpack delta + PurgeTick = DeltaTick; + SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize); + if(SnapSize < 0) + { + m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "delta unpack failed!"); + return; + } - // we got two snapshots until we see us self as connected - if(m_RecivedSnapshots == 2) + if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc) + { + if(g_Config.m_Debug) { - // start at 200ms and work from there - m_PredictedTime.Init(GameTick*time_freq()/50); - m_PredictedTime.SetAdjustSpeed(1, 1000.0f); - m_GameTime.Init((GameTick-1)*time_freq()/50); - m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst; - m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast; - m_LocalStartTime = time_get(); - SetState(IClient::STATE_ONLINE); - DemoRecorder_HandleAutoStart(); + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d", + m_SnapCrcErrors, GameTick, Crc, pTmpBuffer3->Crc(), CompleteSize, DeltaTick); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf); } - // adjust game time - if(m_RecivedSnapshots > 2) + m_SnapCrcErrors++; + if(m_SnapCrcErrors > 10) { - int64 Now = m_GameTime.Get(time_get()); - int64 TickStart = GameTick*time_freq()/50; - int64 TimeLeft = (TickStart-Now)*1000 / time_freq(); - m_GameTime.Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0); + // to many errors, send reset + m_AckGameTick = -1; + SendInput(); + m_SnapCrcErrors = 0; } + return; + } + else + { + if(m_SnapCrcErrors) + m_SnapCrcErrors--; + } - // ack snapshot - m_AckGameTick = GameTick; + // purge old snapshots + PurgeTick = DeltaTick; + if(m_aSnapshots[SNAP_PREV] && m_aSnapshots[SNAP_PREV]->m_Tick < PurgeTick) + PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick; + if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_CURRENT]->m_Tick < PurgeTick) + PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick; + m_SnapshotStorage.PurgeUntil(PurgeTick); + + // add new + m_SnapshotStorage.Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1); + + // add snapshot to demo + if(m_DemoRecorder.IsRecording()) + { + // write snapshot + m_DemoRecorder.RecordSnapshot(GameTick, pTmpBuffer3, SnapSize); + } + + // apply snapshot, cycle pointers + m_RecivedSnapshots++; + + m_CurrentRecvTick = GameTick; + + // we got two snapshots until we see us self as connected + if(m_RecivedSnapshots == 2) + { + // start at 200ms and work from there + m_PredictedTime.Init(GameTick*time_freq()/50); + m_PredictedTime.SetAdjustSpeed(1, 1000.0f); + m_GameTime.Init((GameTick-1)*time_freq()/50); + m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst; + m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast; + m_LocalStartTime = time_get(); + SetState(IClient::STATE_ONLINE); + DemoRecorder_HandleAutoStart(); + } + + // adjust game time + if(m_RecivedSnapshots > 2) + { + int64 Now = m_GameTime.Get(time_get()); + int64 TickStart = GameTick*time_freq()/50; + int64 TimeLeft = (TickStart-Now)*1000 / time_freq(); + m_GameTime.Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0); } + + // ack snapshot + m_AckGameTick = GameTick; } } } - else - { - // game message - if(m_DemoRecorder.IsRecording()) - m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize); + } + else + { + // game message + if(m_DemoRecorder.IsRecording()) + m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize); - GameClient()->OnMessage(Msg, &Unpacker); - } + GameClient()->OnMessage(Msg, &Unpacker); } } @@ -1535,7 +1544,12 @@ void CClient::PumpNetwork() // process packets CNetChunk Packet; while(m_NetClient.Recv(&Packet)) - ProcessPacket(&Packet); + { + if(Packet.m_ClientID == -1) + ProcessConnlessPacket(&Packet); + else + ProcessServerPacket(&Packet); + } } void CClient::OnDemoPlayerSnapshot(void *pData, int Size) @@ -1751,12 +1765,12 @@ void CClient::Update() void CClient::VersionUpdate() { - if(m_VersionInfo.m_State == 0) + if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT) { Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer); - m_VersionInfo.m_State++; + m_VersionInfo.m_State = CVersionInfo::STATE_START; } - else if(m_VersionInfo.m_State == 1) + else if(m_VersionInfo.m_State == CVersionInfo::STATE_START) { if(m_VersionInfo.m_VersionServeraddr.m_Job.Status() == CJob::STATE_DONE) { @@ -1773,7 +1787,7 @@ void CClient::VersionUpdate() Packet.m_Flags = NETSENDFLAG_CONNLESS; m_NetClient.Send(&Packet); - m_VersionInfo.m_State++; + m_VersionInfo.m_State = CVersionInfo::STATE_READY; } } } diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 2c0f5f86..e0cd17a2 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -185,8 +185,15 @@ class CClient : public IClient, public CDemoPlayer::IListner int64 m_CurrentServerInfoRequestTime; // >= 0 should request, == -1 got info // version info - struct + struct CVersionInfo { + enum + { + STATE_INIT=0, + STATE_START, + STATE_READY, + }; + int m_State; class CHostLookup m_VersionServeraddr; } m_VersionInfo; @@ -266,7 +273,8 @@ public: static int PlayerScoreComp(const void *a, const void *b); - void ProcessPacket(CNetChunk *pPacket); + void ProcessConnlessPacket(CNetChunk *pPacket); + void ProcessServerPacket(CNetChunk *pPacket); virtual int MapDownloadAmount() { return m_MapdownloadAmount; } virtual int MapDownloadTotalsize() { return m_MapdownloadTotalsize; } diff --git a/src/engine/client/srvbrowse.cpp b/src/engine/client/srvbrowse.cpp index b718e50a..68d3bca3 100644 --- a/src/engine/client/srvbrowse.cpp +++ b/src/engine/client/srvbrowse.cpp @@ -533,7 +533,7 @@ void CServerBrowser::Request(const NETADDR &Addr) const void CServerBrowser::Update() { - int64 Timeout = time_freq()/2; // TODO: increase this again + int64 Timeout = time_freq()/2; // TODO 0.6: increase this again int64 Now = time_get(); int Count; CServerEntry *pEntry, *pNext; diff --git a/src/versionsrv/versionsrv.h b/src/versionsrv/versionsrv.h index f3b9bc57..68ba04ca 100644 --- a/src/versionsrv/versionsrv.h +++ b/src/versionsrv/versionsrv.h @@ -4,7 +4,7 @@ #define VERSIONSRV_VERSIONSRV_H static const int VERSIONSRV_PORT = 8302; -static const unsigned char VERSION_DATA[] = {0x00, 0, 5, 1}; +static const unsigned char VERSION_DATA[] = {0x00, 0, 5, 1}; // TODO 0.6: fix me 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'}; |