void CServer::SendMap(int ClientId) { CMsgPacker Msg(NETMSG_MAP_CHANGE); Msg.AddString(GetMapName(), 0); Msg.AddInt(m_CurrentMapCrc); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId, true); }
void CServer::SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID) { CMsgPacker Msg(NETMSG_RCON_CMD_ADD); Msg.AddString(pCommandInfo->m_pName, IConsole::TEMPCMD_NAME_LENGTH); Msg.AddString(pCommandInfo->m_pHelp, IConsole::TEMPCMD_HELP_LENGTH); Msg.AddString(pCommandInfo->m_pParams, IConsole::TEMPCMD_PARAMS_LENGTH); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); }
void CServer::SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID) { CMsgPacker Msg(NETMSG_RCON_CMD_ADD); Msg.AddString(pCommandInfo->m_pName, 32); Msg.AddString(pCommandInfo->m_pHelp, 64); Msg.AddString(pCommandInfo->m_pParams, 16); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); }
void CServer::SendMap(int ClientID) { lastsent[ClientID] = 0; lastask[ClientID] = 0; lastasktick[ClientID] = Tick(); CMsgPacker Msg(NETMSG_MAP_CHANGE); Msg.AddString(GetMapName(), 0); Msg.AddInt(m_CurrentMapCrc); Msg.AddInt(m_CurrentMapSize); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true); }
void CServer::SendMap(int ClientId) { //get the name of the map without his path char * pMapShortName = &g_Config.m_SvMap[0]; for(int i = 0; i < 127; i++) { if(g_Config.m_SvMap[i] == '/' || g_Config.m_SvMap[i] == '\\') pMapShortName = &g_Config.m_SvMap[i+1]; } CMsgPacker Msg(NETMSG_MAP_CHANGE); Msg.AddString(pMapShortName, 0); Msg.AddInt(m_CurrentMapCrc); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId, true); }
void CServer::ProcessClientPacket(CNetChunk *pPacket) { int ClientID = pPacket->m_ClientID; 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()) return; if(Sys) { // system message if(Msg == NETMSG_INFO) { if(m_aClients[ClientID].m_State == CClient::STATE_AUTH) { char aVersion[64]; str_copy(aVersion, Unpacker.GetString(CUnpacker::SANITIZE_CC), 64); bool CustClt = str_comp(aVersion, GameServer()->NetVersionCust()) == 0; dbg_msg("es", "%s client connected!", CustClt?"cust":"vanilla"); if(!CustClt && str_comp(aVersion, GameServer()->NetVersion()) != 0) { // wrong version char aReason[256]; str_format(aReason, sizeof(aReason), "Wrong version. Server is running '%s' and client '%s'", GameServer()->NetVersion(), aVersion); m_NetServer.Drop(ClientID, aReason); return; } const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0) { // wrong password m_NetServer.Drop(ClientID, "Wrong password"); return; } m_aClients[ClientID].m_State = CClient::STATE_CONNECTING; m_aClients[ClientID].m_CustClt = CustClt; SendMap(ClientID); } } else if(Msg == NETMSG_REQUEST_MAP_DATA) { int Chunk = Unpacker.GetInt(); int ChunkSize = 1024-128; int Offset = Chunk * ChunkSize; int Last = 0; // drop faulty map data requests if(Chunk < 0 || Offset > m_CurrentMapSize) return; if(Offset+ChunkSize >= m_CurrentMapSize) { ChunkSize = m_CurrentMapSize-Offset; if(ChunkSize < 0) ChunkSize = 0; Last = 1; } CMsgPacker Msg(NETMSG_MAP_DATA); Msg.AddInt(Last); Msg.AddInt(m_CurrentMapCrc); Msg.AddInt(Chunk); Msg.AddInt(ChunkSize); Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true); if(g_Config.m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); } } else if(Msg == NETMSG_READY) { if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); m_aClients[ClientID].m_State = CClient::STATE_READY; GameServer()->OnClientConnected(ClientID); SendConnectionReady(ClientID); } } else if(Msg == NETMSG_ENTERGAME) { if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID)) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); m_aClients[ClientID].m_State = CClient::STATE_INGAME; GameServer()->OnClientEnter(ClientID); } } else if(Msg == NETMSG_INPUT) { CClient::CInput *pInput; int64 TagTime; m_aClients[ClientID].m_LastAckedSnapshot = Unpacker.GetInt(); int IntendedTick = Unpacker.GetInt(); int Size = Unpacker.GetInt(); // check for errors if(Unpacker.Error() || Size/4 > MAX_INPUT_SIZE) return; if(m_aClients[ClientID].m_LastAckedSnapshot > 0) m_aClients[ClientID].m_SnapRate = CClient::SNAPRATE_FULL; if(m_aClients[ClientID].m_Snapshots.Get(m_aClients[ClientID].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0) m_aClients[ClientID].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq()); // add message to report the input timing // skip packets that are old if(IntendedTick > m_aClients[ClientID].m_LastInputTick) { int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq(); CMsgPacker Msg(NETMSG_INPUTTIMING); Msg.AddInt(IntendedTick); Msg.AddInt(TimeLeft); SendMsgEx(&Msg, 0, ClientID, true); } m_aClients[ClientID].m_LastInputTick = IntendedTick; pInput = &m_aClients[ClientID].m_aInputs[m_aClients[ClientID].m_CurrentInput]; if(IntendedTick <= Tick()) IntendedTick = Tick()+1; pInput->m_GameTick = IntendedTick; for(int i = 0; i < Size/4; i++) pInput->m_aData[i] = Unpacker.GetInt(); mem_copy(m_aClients[ClientID].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int)); m_aClients[ClientID].m_CurrentInput++; m_aClients[ClientID].m_CurrentInput %= 200; // call the mod with the fresh input data if(m_aClients[ClientID].m_State == CClient::STATE_INGAME) GameServer()->OnClientDirectInput(ClientID, m_aClients[ClientID].m_LatestInput.m_aData); } else if(Msg == NETMSG_RCON_CMD) { const char *pCmd = Unpacker.GetString(); if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d rcon='%s'", ClientID, pCmd); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); m_RconClientID = ClientID; m_RconAuthLevel = m_aClients[ClientID].m_Authed; Console()->SetAccessLevel(m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD); Console()->ExecuteLineFlag(pCmd, CFGFLAG_SERVER); Console()->SetAccessLevel(IConsole::ACCESS_LEVEL_ADMIN); m_RconClientID = IServer::RCON_CID_SERV; m_RconAuthLevel = AUTHED_ADMIN; } } else if(Msg == NETMSG_RCON_AUTH) { const char *pPw; Unpacker.GetString(); // login name, not used pPw = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(Unpacker.Error() == 0) { if(g_Config.m_SvRconPassword[0] == 0 && g_Config.m_SvRconModPassword[0] == 0) { SendRconLine(ClientID, "No rcon password set on server. Set sv_rcon_password and/or sv_rcon_mod_password to enable the remote console."); } else if(g_Config.m_SvRconPassword[0] && str_comp(pPw, g_Config.m_SvRconPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); Msg.AddInt(1); //authed Msg.AddInt(1); //cmdlist SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); m_aClients[ClientID].m_Authed = AUTHED_ADMIN; int SendRconCmds = Unpacker.GetInt(); if(Unpacker.Error() == 0 && SendRconCmds) m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_ADMIN, CFGFLAG_SERVER); SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted."); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } else if(g_Config.m_SvRconModPassword[0] && str_comp(pPw, g_Config.m_SvRconModPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); Msg.AddInt(1); //authed Msg.AddInt(1); //cmdlist SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); m_aClients[ClientID].m_Authed = AUTHED_MOD; int SendRconCmds = Unpacker.GetInt(); if(Unpacker.Error() == 0 && SendRconCmds) m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_MOD, CFGFLAG_SERVER); SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted."); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } else if(g_Config.m_SvRconMaxTries) { m_aClients[ClientID].m_AuthTries++; char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, g_Config.m_SvRconMaxTries); SendRconLine(ClientID, aBuf); if(m_aClients[ClientID].m_AuthTries >= g_Config.m_SvRconMaxTries) { if(!g_Config.m_SvRconBantime) m_NetServer.Drop(ClientID, "Too many remote console authentication tries"); else m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), g_Config.m_SvRconBantime*60, "Too many remote console authentication tries"); } } else { SendRconLine(ClientID, "Wrong password."); } } } else if(Msg == NETMSG_PING) { CMsgPacker Msg(NETMSG_PING_REPLY); SendMsgEx(&Msg, 0, ClientID, true); } else { if(g_Config.m_Debug) { char aHex[] = "0123456789ABCDEF"; char aBuf[512]; for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) { aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; aBuf[b*3+2] = ' '; aBuf[b*3+3] = 0; } char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientID=%d msg=%d data_size=%d", ClientID, Msg, pPacket->m_DataSize); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBufMsg); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); } } }
void CServer::SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID) { CMsgPacker Msg(NETMSG_RCON_CMD_REM); Msg.AddString(pCommandInfo->m_pName, 256); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); }
void CServer::SendRconLine(int ClientID, const char *pLine) { CMsgPacker Msg(NETMSG_RCON_LINE); Msg.AddString(pLine, 512); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); }
void CServer::SendConnectionReady(int ClientID) { CMsgPacker Msg(NETMSG_CON_READY); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true); }
void CServer::DoSnapshot() { GameServer()->OnPreSnap(); // create snapshot for demo recording if(m_DemoRecorder.IsRecording()) { char aData[CSnapshot::MAX_SIZE]; int SnapshotSize; // build snap and possibly add some messages m_SnapshotBuilder.Init(); GameServer()->OnSnap(-1); SnapshotSize = m_SnapshotBuilder.Finish(aData); // write snapshot m_DemoRecorder.RecordSnapshot(Tick(), aData, SnapshotSize); } // create snapshots for all clients for(int i = 0; i < MAX_CLIENTS; i++) { // client must be ingame to recive snapshots if(m_aClients[i].m_State != CClient::STATE_INGAME) continue; // this client is trying to recover, don't spam snapshots if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_RECOVER && (Tick()%50) != 0) continue; // this client is trying to recover, don't spam snapshots if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_INIT && (Tick()%10) != 0) continue; { char aData[CSnapshot::MAX_SIZE]; CSnapshot *pData = (CSnapshot*)aData; // Fix compiler warning for strict-aliasing char aDeltaData[CSnapshot::MAX_SIZE]; char aCompData[CSnapshot::MAX_SIZE]; int SnapshotSize; int Crc; static CSnapshot EmptySnap; CSnapshot *pDeltashot = &EmptySnap; int DeltashotSize; int DeltaTick = -1; int DeltaSize; m_SnapshotBuilder.Init(); GameServer()->OnSnap(i); // finish snapshot SnapshotSize = m_SnapshotBuilder.Finish(pData); Crc = pData->Crc(); // remove old snapshos // keep 3 seconds worth of snapshots m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick-SERVER_TICK_SPEED*3); // save it the snapshot m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0); // find snapshot that we can preform delta against EmptySnap.Clear(); { DeltashotSize = m_aClients[i].m_Snapshots.Get(m_aClients[i].m_LastAckedSnapshot, 0, &pDeltashot, 0); if(DeltashotSize >= 0) DeltaTick = m_aClients[i].m_LastAckedSnapshot; else { // no acked package found, force client to recover rate if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_FULL) m_aClients[i].m_SnapRate = CClient::SNAPRATE_RECOVER; } } // create delta DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, pData, aDeltaData); if(DeltaSize) { // compress it int SnapshotSize; const int MaxSize = MAX_SNAPSHOT_PACKSIZE; int NumPackets; SnapshotSize = CVariableInt::Compress(aDeltaData, DeltaSize, aCompData); NumPackets = (SnapshotSize+MaxSize-1)/MaxSize; for(int n = 0, Left = SnapshotSize; Left; n++) { int Chunk = Left < MaxSize ? Left : MaxSize; Left -= Chunk; if(NumPackets == 1) { CMsgPacker Msg(NETMSG_SNAPSINGLE); Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); Msg.AddInt(Crc); Msg.AddInt(Chunk); Msg.AddRaw(&aCompData[n*MaxSize], Chunk); SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true); } else { CMsgPacker Msg(NETMSG_SNAP); Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); Msg.AddInt(NumPackets); Msg.AddInt(n); Msg.AddInt(Crc); Msg.AddInt(Chunk); Msg.AddRaw(&aCompData[n*MaxSize], Chunk); SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true); } } } else { CMsgPacker Msg(NETMSG_SNAPEMPTY); Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true); } } } GameServer()->OnPostSnap(); }
int CServer::SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) { return SendMsgEx(pMsg, Flags, ClientID, false); }
void CServer::ProcessClientPacket(CNetChunk *pPacket) { int ClientId = pPacket->m_ClientID; NETADDR Addr; 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()) return; if(m_aClients[ClientId].m_State == CClient::STATE_AUTH) { if(Sys && Msg == NETMSG_INFO) { char aVersion[64]; const char *pPassword; str_copy(aVersion, Unpacker.GetString(), 64); if(str_comp(aVersion, GameServer()->NetVersion()) != 0) { // OH F**K! wrong version, drop him char aReason[256]; str_format(aReason, sizeof(aReason), "wrong version. server is running '%s' and client '%s'.", GameServer()->NetVersion(), aVersion); m_NetServer.Drop(ClientId, aReason); return; } str_copy(m_aClients[ClientId].m_aName, Unpacker.GetString(), MAX_NAME_LENGTH); str_copy(m_aClients[ClientId].m_aClan, Unpacker.GetString(), MAX_CLANNAME_LENGTH); pPassword = Unpacker.GetString(); if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0) { // wrong password m_NetServer.Drop(ClientId, "wrong password"); return; } m_aClients[ClientId].m_State = CClient::STATE_CONNECTING; SendMap(ClientId); } } else { if(Sys) { // system message if(Msg == NETMSG_REQUEST_MAP_DATA) { int Chunk = Unpacker.GetInt(); int ChunkSize = 1024-128; int Offset = Chunk * ChunkSize; int Last = 0; // drop faulty map data requests if(Chunk < 0 || Offset > m_CurrentMapSize) return; if(Offset+ChunkSize >= m_CurrentMapSize) { ChunkSize = m_CurrentMapSize-Offset; if(ChunkSize < 0) ChunkSize = 0; Last = 1; } CMsgPacker Msg(NETMSG_MAP_DATA); Msg.AddInt(Last); Msg.AddInt(m_CurrentMapSize); Msg.AddInt(ChunkSize); Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId, true); if(g_Config.m_Debug) dbg_msg("server", "sending chunk %d with size %d", Chunk, ChunkSize); } else if(Msg == NETMSG_READY) { if(m_aClients[ClientId].m_State == CClient::STATE_CONNECTING) { Addr = m_NetServer.ClientAddr(ClientId); dbg_msg("server", "player is ready. ClientId=%x ip=%d.%d.%d.%d", ClientId, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); m_aClients[ClientId].m_State = CClient::STATE_READY; GameServer()->OnClientConnected(ClientId); } } else if(Msg == NETMSG_ENTERGAME) { if(m_aClients[ClientId].m_State == CClient::STATE_READY) { Addr = m_NetServer.ClientAddr(ClientId); dbg_msg("server", "player has entered the game. ClientId=%x ip=%d.%d.%d.%d", ClientId, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); m_aClients[ClientId].m_State = CClient::STATE_INGAME; GameServer()->OnClientEnter(ClientId); } } else if(Msg == NETMSG_INPUT) { CClient::CInput *pInput; int64 TagTime; m_aClients[ClientId].m_LastAckedSnapshot = Unpacker.GetInt(); int IntendedTick = Unpacker.GetInt(); int Size = Unpacker.GetInt(); // check for errors if(Unpacker.Error() || Size/4 > MAX_INPUT_SIZE) return; if(m_aClients[ClientId].m_LastAckedSnapshot > 0) m_aClients[ClientId].m_SnapRate = CClient::SNAPRATE_FULL; if(m_aClients[ClientId].m_Snapshots.Get(m_aClients[ClientId].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0) m_aClients[ClientId].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq()); // add message to report the input timing // skip packets that are old if(IntendedTick > m_aClients[ClientId].m_LastInputTick) { int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq(); CMsgPacker Msg(NETMSG_INPUTTIMING); Msg.AddInt(IntendedTick); Msg.AddInt(TimeLeft); SendMsgEx(&Msg, 0, ClientId, true); } m_aClients[ClientId].m_LastInputTick = IntendedTick; pInput = &m_aClients[ClientId].m_aInputs[m_aClients[ClientId].m_CurrentInput]; if(IntendedTick <= Tick()) IntendedTick = Tick()+1; pInput->m_GameTick = IntendedTick; for(int i = 0; i < Size/4; i++) pInput->m_aData[i] = Unpacker.GetInt(); mem_copy(m_aClients[ClientId].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int)); m_aClients[ClientId].m_CurrentInput++; m_aClients[ClientId].m_CurrentInput %= 200; // call the mod with the fresh input data if(m_aClients[ClientId].m_State == CClient::STATE_INGAME) GameServer()->OnClientDirectInput(ClientId, m_aClients[ClientId].m_LatestInput.m_aData); } else if(Msg == NETMSG_RCON_CMD) { const char *pCmd = Unpacker.GetString(); if(Unpacker.Error() == 0 && m_aClients[ClientId].m_Authed) { dbg_msg("server", "ClientId=%d rcon='%s'", ClientId, pCmd); Console()->ExecuteLine(pCmd); } } else if(Msg == NETMSG_RCON_AUTH) { const char *pPw; Unpacker.GetString(); // login name, not used pPw = Unpacker.GetString(); if(Unpacker.Error() == 0) { if(g_Config.m_SvRconPassword[0] == 0) { SendRconLine(ClientId, "No rcon password set on server. Set sv_rcon_password to enable the remote console."); } else if(str_comp(pPw, g_Config.m_SvRconPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); Msg.AddInt(1); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientId, true); m_aClients[ClientId].m_Authed = 1; SendRconLine(ClientId, "Authentication successful. Remote console access granted."); dbg_msg("server", "ClientId=%d authed", ClientId); } else { SendRconLine(ClientId, "Wrong password."); } } } else if(Msg == NETMSG_PING) { CMsgPacker Msg(NETMSG_PING_REPLY); SendMsgEx(&Msg, 0, ClientId, true); } else { char aHex[] = "0123456789ABCDEF"; char aBuf[512]; for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) { aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; aBuf[b*3+2] = ' '; aBuf[b*3+3] = 0; } dbg_msg("server", "strange message ClientId=%d msg=%d data_size=%d", ClientId, Msg, pPacket->m_DataSize); dbg_msg("server", "%s", aBuf); } } else { // game message if(m_aClients[ClientId].m_State >= CClient::STATE_READY) GameServer()->OnMessage(Msg, &Unpacker, ClientId); } }