mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 01:24:18 +00:00
made clients sending startinfo a requirement to prevent empty player infos
This commit is contained in:
parent
7b91ebd01c
commit
27e5a6af0d
|
@ -518,8 +518,6 @@ void CClient::SendInfo()
|
|||
{
|
||||
CMsgPacker Msg(NETMSG_INFO);
|
||||
Msg.AddString(GameClient()->NetVersion(), 128);
|
||||
Msg.AddString(g_Config.m_PlayerName, 128);
|
||||
Msg.AddString(g_Config.m_ClanName, 128);
|
||||
Msg.AddString(g_Config.m_Password, 128);
|
||||
SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
|
||||
}
|
||||
|
@ -1175,7 +1173,6 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
|
|||
{
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
||||
SendReady();
|
||||
GameClient()->OnConnected();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1238,8 +1235,7 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
|
|||
if(!pError)
|
||||
{
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
||||
SendReady();
|
||||
GameClient()->OnConnected();
|
||||
SendReady();
|
||||
}
|
||||
else
|
||||
DisconnectWithReason(pError);
|
||||
|
@ -1261,6 +1257,10 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(Msg == NETMSG_CON_READY)
|
||||
{
|
||||
GameClient()->OnConnected();
|
||||
}
|
||||
else if(Msg == NETMSG_PING)
|
||||
{
|
||||
CMsgPacker Msg(NETMSG_PING_REPLY);
|
||||
|
|
|
@ -76,6 +76,8 @@ public:
|
|||
virtual void OnClientDrop(int ClientID) = 0;
|
||||
virtual void OnClientDirectInput(int ClientID, void *pInput) = 0;
|
||||
virtual void OnClientPredictedInput(int ClientID, void *pInput) = 0;
|
||||
|
||||
virtual bool IsClientReady(int ClientID) = 0;
|
||||
|
||||
virtual const char *GameType() = 0;
|
||||
virtual const char *Version() = 0;
|
||||
|
|
|
@ -572,6 +572,12 @@ void CServer::SendMap(int ClientID)
|
|||
SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
|
||||
}
|
||||
|
||||
void CServer::SendConnectionReady(int ClientID)
|
||||
{
|
||||
CMsgPacker Msg(NETMSG_CON_READY);
|
||||
SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
|
||||
}
|
||||
|
||||
void CServer::SendRconLine(int ClientID, const char *pLine)
|
||||
{
|
||||
CMsgPacker Msg(NETMSG_RCON_LINE);
|
||||
|
@ -612,250 +618,243 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
if(Unpacker.Error())
|
||||
return;
|
||||
|
||||
if(m_aClients[ClientID].m_State == CClient::STATE_AUTH)
|
||||
if(Sys)
|
||||
{
|
||||
if(Sys && Msg == NETMSG_INFO)
|
||||
// system message
|
||||
if(Msg == NETMSG_INFO)
|
||||
{
|
||||
char aVersion[64];
|
||||
const char *pPassword;
|
||||
str_copy(aVersion, Unpacker.GetString(CUnpacker::SANITIZE_CC), 64);
|
||||
if(str_comp(aVersion, GameServer()->NetVersion()) != 0)
|
||||
if(m_aClients[ClientID].m_State == CClient::STATE_AUTH)
|
||||
{
|
||||
// OH FUCK! 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;
|
||||
const char *pVersion = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
||||
if(str_comp(pVersion, GameServer()->NetVersion()) != 0)
|
||||
{
|
||||
// wrong version
|
||||
char aReason[256];
|
||||
str_format(aReason, sizeof(aReason), "Wrong version. Server is running '%s' and client '%s'", GameServer()->NetVersion(), pVersion);
|
||||
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;
|
||||
SendMap(ClientID);
|
||||
}
|
||||
|
||||
str_copy(m_aClients[ClientID].m_aName, Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), MAX_NAME_LENGTH);
|
||||
str_copy(m_aClients[ClientID].m_aClan, Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), MAX_CLANNAME_LENGTH);
|
||||
pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
||||
|
||||
if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0)
|
||||
}
|
||||
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)
|
||||
{
|
||||
// wrong password
|
||||
m_NetServer.Drop(ClientID, "Wrong password");
|
||||
return;
|
||||
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)
|
||||
{
|
||||
Addr = m_NetServer.ClientAddr(ClientID);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x ip=%d.%d.%d.%d",
|
||||
ClientID, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
|
||||
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))
|
||||
{
|
||||
Addr = m_NetServer.ClientAddr(ClientID);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "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]);
|
||||
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;
|
||||
|
||||
m_aClients[ClientID].m_State = CClient::STATE_CONNECTING;
|
||||
SendMap(ClientID);
|
||||
// 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;
|
||||
Console()->ExecuteLine(pCmd);
|
||||
m_RconClientID = -1;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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.");
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed", 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
|
||||
{
|
||||
NETADDR Addr = m_NetServer.ClientAddr(ClientID);
|
||||
BanAdd(Addr, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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_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)
|
||||
{
|
||||
Addr = m_NetServer.ClientAddr(ClientID);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x ip=%d.%d.%d.%d",
|
||||
ClientID, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
|
||||
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);
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "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]);
|
||||
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;
|
||||
Console()->ExecuteLine(pCmd);
|
||||
m_RconClientID = -1;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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.");
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed", 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
|
||||
{
|
||||
NETADDR Addr = m_NetServer.ClientAddr(ClientID);
|
||||
BanAdd(Addr, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// game message
|
||||
if(m_aClients[ClientID].m_State >= CClient::STATE_READY)
|
||||
GameServer()->OnMessage(Msg, &Unpacker, ClientID);
|
||||
}
|
||||
// game message
|
||||
if(m_aClients[ClientID].m_State >= CClient::STATE_READY)
|
||||
GameServer()->OnMessage(Msg, &Unpacker, ClientID);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ public:
|
|||
static int DelClientCallback(int ClientID, const char *pReason, void *pUser);
|
||||
|
||||
void SendMap(int ClientID);
|
||||
void SendConnectionReady(int ClientID);
|
||||
void SendRconLine(int ClientID, const char *pLine);
|
||||
static void SendRconLineAuthed(const char *pLine, void *pUser);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ enum
|
|||
// sent by server
|
||||
NETMSG_MAP_CHANGE, // sent when client should switch map
|
||||
NETMSG_MAP_DATA, // map transfer, contains a chunk of the map file
|
||||
NETMSG_CON_READY, // connection is ready, client should send start info
|
||||
NETMSG_SNAP, // normal snapshot, multiple parts
|
||||
NETMSG_SNAPEMPTY, // empty snapshot
|
||||
NETMSG_SNAPSINGLE, // ?
|
||||
|
|
|
@ -786,57 +786,65 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
else
|
||||
pPlayer->m_SpectatorID = pMsg->m_SpectatorID;
|
||||
}
|
||||
else if (MsgID == NETMSGTYPE_CL_CHANGEINFO || MsgID == NETMSGTYPE_CL_STARTINFO)
|
||||
{
|
||||
CNetMsg_Cl_ChangeInfo *pMsg = (CNetMsg_Cl_ChangeInfo *)pRawMsg;
|
||||
|
||||
if(g_Config.m_SvSpamprotection && pPlayer->m_LastChangeInfo && pPlayer->m_LastChangeInfo+Server()->TickSpeed()*5 > Server()->Tick())
|
||||
else if (MsgID == NETMSGTYPE_CL_STARTINFO)
|
||||
{
|
||||
if(pPlayer->m_IsReady)
|
||||
return;
|
||||
|
||||
|
||||
CNetMsg_Cl_StartInfo *pMsg = (CNetMsg_Cl_StartInfo *)pRawMsg;
|
||||
pPlayer->m_LastChangeInfo = Server()->Tick();
|
||||
|
||||
// set start infos
|
||||
Server()->SetClientName(ClientID, pMsg->m_pName);
|
||||
str_copy(pPlayer->m_TeeInfos.m_SkinName, pMsg->m_pSkin, sizeof(pPlayer->m_TeeInfos.m_SkinName));
|
||||
pPlayer->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;
|
||||
pPlayer->m_TeeInfos.m_ColorBody = pMsg->m_ColorBody;
|
||||
pPlayer->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet;
|
||||
m_pController->OnPlayerInfoChange(pPlayer);
|
||||
|
||||
// copy old name
|
||||
char aOldName[MAX_NAME_LENGTH];
|
||||
str_copy(aOldName, Server()->ClientName(ClientID), MAX_NAME_LENGTH);
|
||||
// send vote options
|
||||
CNetMsg_Sv_VoteClearOptions ClearMsg;
|
||||
Server()->SendPackMsg(&ClearMsg, MSGFLAG_VITAL, ClientID);
|
||||
CVoteOption *pCurrent = m_pVoteOptionFirst;
|
||||
while(pCurrent)
|
||||
{
|
||||
CNetMsg_Sv_VoteOption OptionMsg;
|
||||
OptionMsg.m_pCommand = pCurrent->m_aCommand;
|
||||
Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID);
|
||||
pCurrent = pCurrent->m_pNext;
|
||||
}
|
||||
|
||||
// send tuning parameters to client
|
||||
SendTuningParams(ClientID);
|
||||
|
||||
// client is ready to enter
|
||||
pPlayer->m_IsReady = true;
|
||||
CNetMsg_Sv_ReadyToEnter m;
|
||||
Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID);
|
||||
}
|
||||
else if (MsgID == NETMSGTYPE_CL_CHANGEINFO)
|
||||
{
|
||||
if(g_Config.m_SvSpamprotection && pPlayer->m_LastChangeInfo && pPlayer->m_LastChangeInfo+Server()->TickSpeed()*5 > Server()->Tick())
|
||||
return;
|
||||
|
||||
CNetMsg_Cl_ChangeInfo *pMsg = (CNetMsg_Cl_ChangeInfo *)pRawMsg;
|
||||
pPlayer->m_LastChangeInfo = Server()->Tick();
|
||||
|
||||
// set infos
|
||||
char aOldName[MAX_NAME_LENGTH];
|
||||
str_copy(aOldName, Server()->ClientName(ClientID), sizeof(aOldName));
|
||||
Server()->SetClientName(ClientID, pMsg->m_pName);
|
||||
if(MsgID == NETMSGTYPE_CL_CHANGEINFO && str_comp(aOldName, Server()->ClientName(ClientID)) != 0)
|
||||
if(str_comp(aOldName, Server()->ClientName(ClientID)) != 0)
|
||||
{
|
||||
char aChatText[256];
|
||||
str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID));
|
||||
SendChat(-1, CGameContext::CHAT_ALL, aChatText);
|
||||
}
|
||||
|
||||
// set skin
|
||||
str_copy(pPlayer->m_TeeInfos.m_SkinName, pMsg->m_pSkin, sizeof(pPlayer->m_TeeInfos.m_SkinName));
|
||||
|
||||
pPlayer->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;
|
||||
pPlayer->m_TeeInfos.m_ColorBody = pMsg->m_ColorBody;
|
||||
pPlayer->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet;
|
||||
m_pController->OnPlayerInfoChange(pPlayer);
|
||||
|
||||
if(MsgID == NETMSGTYPE_CL_STARTINFO)
|
||||
{
|
||||
// send vote options
|
||||
CNetMsg_Sv_VoteClearOptions ClearMsg;
|
||||
Server()->SendPackMsg(&ClearMsg, MSGFLAG_VITAL, ClientID);
|
||||
CVoteOption *pCurrent = m_pVoteOptionFirst;
|
||||
while(pCurrent)
|
||||
{
|
||||
CNetMsg_Sv_VoteOption OptionMsg;
|
||||
OptionMsg.m_pCommand = pCurrent->m_aCommand;
|
||||
Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID);
|
||||
pCurrent = pCurrent->m_pNext;
|
||||
}
|
||||
|
||||
// send tuning parameters to client
|
||||
SendTuningParams(ClientID);
|
||||
|
||||
//
|
||||
CNetMsg_Sv_ReadyToEnter m;
|
||||
Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID);
|
||||
}
|
||||
}
|
||||
else if (MsgID == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused)
|
||||
{
|
||||
|
@ -1167,6 +1175,11 @@ void CGameContext::OnPostSnap()
|
|||
m_Events.Clear();
|
||||
}
|
||||
|
||||
bool CGameContext::IsClientReady(int ClientID)
|
||||
{
|
||||
return m_apPlayers[ClientID] && m_apPlayers[ClientID]->m_IsReady ? true : false;
|
||||
}
|
||||
|
||||
const char *CGameContext::GameType() { return m_pController && m_pController->m_pGameType ? m_pController->m_pGameType : ""; }
|
||||
const char *CGameContext::Version() { return GAME_VERSION; }
|
||||
const char *CGameContext::NetVersion() { return GAME_NETVERSION; }
|
||||
|
|
|
@ -161,6 +161,8 @@ public:
|
|||
virtual void OnClientDirectInput(int ClientID, void *pInput);
|
||||
virtual void OnClientPredictedInput(int ClientID, void *pInput);
|
||||
|
||||
virtual bool IsClientReady(int ClientID);
|
||||
|
||||
virtual const char *GameType();
|
||||
virtual const char *Version();
|
||||
virtual const char *NetVersion();
|
||||
|
|
|
@ -47,6 +47,8 @@ public:
|
|||
|
||||
// used for spectator mode
|
||||
int m_SpectatorID;
|
||||
|
||||
bool m_IsReady;
|
||||
|
||||
//
|
||||
int m_Vote;
|
||||
|
|
Loading…
Reference in a new issue