about summary refs log tree commit diff
diff options
context:
space:
mode:
authoroy <Tom_Adams@web.de>2011-03-17 17:41:57 +0100
committeroy <Tom_Adams@web.de>2011-03-17 17:41:57 +0100
commitb939d3822882c5061f5e3ddfb3fc3b13b116fe24 (patch)
tree0729cf0246d629861d3905ba76327e5bfab48857
parentb4bec5335960f78a0ad6ac6f0c491cb76375bd56 (diff)
downloadzcatch-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.cpp792
-rw-r--r--src/engine/client/client.h12
-rw-r--r--src/engine/client/srvbrowse.cpp2
-rw-r--r--src/versionsrv/versionsrv.h2
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'};