diff --git a/Core/GameEngine/Include/GameNetwork/NetworkDefs.h b/Core/GameEngine/Include/GameNetwork/NetworkDefs.h index da50e56b42..dea06f74b9 100644 --- a/Core/GameEngine/Include/GameNetwork/NetworkDefs.h +++ b/Core/GameEngine/Include/GameNetwork/NetworkDefs.h @@ -41,11 +41,10 @@ extern Int MIN_RUNAHEAD; extern Int FRAME_DATA_LENGTH; extern Int FRAMES_TO_KEEP; -// This is the connection numbering: 1-8 are for players, 9 is a broadcast con. +// This is the connection numbering: 1-8 are for players enum ConnectionNumbers CPP_11(: Int) { MAX_PLAYER = 7, // The index of the highest possible player number. This is 0 based, so the most players allowed in a game is MAX_PLAYER+1. - NUM_CONNECTIONS }; static const Int MAX_SLOTS = MAX_PLAYER+1; diff --git a/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp index 959c882d62..3cb4483ffa 100644 --- a/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp +++ b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp @@ -102,7 +102,7 @@ ConnectionManager::~ConnectionManager(void) m_frameData[i] = nullptr; } - for (i = 0; i < NUM_CONNECTIONS; ++i) { + for (i = 0; i < MAX_SLOTS; ++i) { deleteInstance(m_connections[i]); m_connections[i] = nullptr; } @@ -160,7 +160,7 @@ void ConnectionManager::init() // m_transport->reset(); UnsignedInt i = 0; - for (; i < NUM_CONNECTIONS; ++i) { + for (; i < MAX_SLOTS; ++i) { m_connections[i] = nullptr; } @@ -236,7 +236,7 @@ void ConnectionManager::reset() m_transport = nullptr; UnsignedInt i = 0; - for (; i < (UnsignedInt)NUM_CONNECTIONS; ++i) { + for (; i < (UnsignedInt)MAX_SLOTS; ++i) { deleteInstance(m_connections[i]); m_connections[i] = nullptr; } @@ -302,6 +302,7 @@ Int ConnectionManager::getPingsReceived() Bool ConnectionManager::isPlayerConnected( Int playerID ) { + DEBUG_ASSERTCRASH( playerID < MAX_SLOTS, ("ConnectionManager::isPlayerConnected - %d is an invalid player number", playerID) ); return ( playerID == m_localSlot || (m_connections[playerID] && !m_connections[playerID]->isQuitting()) ); } @@ -431,6 +432,10 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) { } // Early validation checks + if (msg->getPlayerID() >= MAX_SLOTS) { + return TRUE; + } + if ((m_connections[msg->getPlayerID()] == nullptr) && (msg->getPlayerID() != m_localSlot)) { // if this is from a player that is no longer in the game, then ignore them. return TRUE; @@ -442,7 +447,7 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) { return FALSE; } - if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS) && (msg->getPlayerID() != m_localSlot)) { + if (msg->getPlayerID() != m_localSlot) { if (m_connections[msg->getPlayerID()] == nullptr) { return TRUE; } @@ -536,8 +541,8 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) { void ConnectionManager::processFrameResendRequest(NetFrameResendRequestCommandMsg *msg) { // first make sure this is a valid slot - Int playerID = msg->getPlayerID(); - if ((playerID < 0) || (playerID >= MAX_SLOTS)) { + const UnsignedInt playerID = msg->getPlayerID(); + if (playerID >= MAX_SLOTS) { return; } @@ -601,16 +606,19 @@ void ConnectionManager::processWrapper(NetCommandRef *ref) */ void ConnectionManager::processRunAheadMetrics(NetRunAheadMetricsCommandMsg *msg) { - UnsignedInt player = msg->getPlayerID(); - if ((player >= 0) && (player < MAX_SLOTS) && (isPlayerConnected(player))) { - m_latencyAverages[player] = msg->getAverageLatency(); - m_fpsAverages[player] = msg->getAverageFps(); + const UnsignedInt playerID = msg->getPlayerID(); + if (playerID >= MAX_SLOTS) { + return; + } + if (isPlayerConnected(playerID)) { + m_latencyAverages[playerID] = msg->getAverageLatency(); + m_fpsAverages[playerID] = msg->getAverageFps(); //DEBUG_LOG(("ConnectionManager::processRunAheadMetrics - player %d, fps = %d, latency = %f", player, msg->getAverageFps(), msg->getAverageLatency())); - if (m_fpsAverages[player] > 100) { + if (m_fpsAverages[playerID] > 100) { // limit the reported frame rate average to 100. This is done because if a // user alt-tab's out of the game their frame rate climbs to in the neighborhood of // 300, that was deemed "ugly" by the powers that be. - m_fpsAverages[player] = 100; + m_fpsAverages[playerID] = 100; } } } @@ -619,7 +627,10 @@ void ConnectionManager::processDisconnectChat(NetDisconnectChatCommandMsg *msg) { UnicodeString unitext; UnicodeString name; - UnsignedByte playerID = msg->getPlayerID(); + const UnsignedInt playerID = msg->getPlayerID(); + if (playerID >= MAX_SLOTS) { + return; + } if (playerID == m_localSlot) { name = m_localUser->GetName(); } else if (isPlayerConnected(playerID)) { @@ -634,12 +645,15 @@ void ConnectionManager::processChat(NetChatCommandMsg *msg) { UnicodeString unitext; UnicodeString name; - UnsignedByte playerID = msg->getPlayerID(); + const UnsignedInt playerID = msg->getPlayerID(); + if (playerID >= MAX_SLOTS) { + return; + } //DEBUG_LOG(("processChat(): playerID = %d", playerID)); if (playerID == m_localSlot) { name = m_localUser->GetName(); //DEBUG_LOG(("connection is null, using %ls", name.str())); - } else if (((m_connections[playerID] != nullptr) && (m_connections[playerID]->isQuitting() == FALSE))) { + } else if ((m_connections[playerID] != nullptr) && (m_connections[playerID]->isQuitting() == FALSE)) { name = m_connections[playerID]->getUser()->GetName(); //DEBUG_LOG(("connection is non-null, using %ls", name.str())); } @@ -794,9 +808,14 @@ void ConnectionManager::processFileProgress(NetFileProgressCommandMsg *msg) { DEBUG_LOG(("ConnectionManager::processFileProgress() - command %d is at %d%%", msg->getFileID(), msg->getProgress())); - Int oldProgress = s_fileProgressMap[msg->getPlayerID()][msg->getFileID()]; - s_fileProgressMap[msg->getPlayerID()][msg->getFileID()] = max(oldProgress, msg->getProgress()); + const UnsignedInt playerID = msg->getPlayerID(); + if (playerID >= MAX_SLOTS) { + return; + } + const UnsignedShort fileID = msg->getFileID(); + const Int oldProgress = s_fileProgressMap[playerID][fileID]; + s_fileProgressMap[playerID][fileID] = max(oldProgress, msg->getProgress()); } void ConnectionManager::processProgress( NetProgressCommandMsg *msg ) @@ -820,9 +839,9 @@ void ConnectionManager::processTimeOutGameStart( NetCommandMsg *msg ) void ConnectionManager::processFrameInfo(NetFrameCommandMsg *msg) { //stupid frame info, why don't you process yourself? - UnsignedInt playerID = msg->getPlayerID(); + const UnsignedInt playerID = msg->getPlayerID(); - if ((playerID >= 0) && (playerID < MAX_SLOTS)) { + if (playerID < MAX_SLOTS) { if (m_frameData[playerID] != nullptr) { // DEBUG_LOG(("ConnectionManager::processFrameInfo - player %d, frame %d, command count %d, received on frame %d", playerID, msg->getExecutionFrame(), msg->getCommandCount(), TheGameLogic->getFrame())); m_frameData[playerID]->setFrameCommandCount(msg->getExecutionFrame(), msg->getCommandCount()); @@ -839,7 +858,7 @@ void ConnectionManager::processAckStage1(NetCommandMsg *msg) { Bool doDebug = (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ? TRUE : FALSE; #endif - UnsignedByte playerID = msg->getPlayerID(); + const UnsignedInt playerID = msg->getPlayerID(); NetCommandRef *ref = nullptr; #if defined(RTS_DEBUG) @@ -848,12 +867,12 @@ void ConnectionManager::processAckStage1(NetCommandMsg *msg) { } #endif - if ((playerID >= 0) && (playerID < NUM_CONNECTIONS)) { + if (playerID < MAX_SLOTS) { if (m_connections[playerID] != nullptr) { ref = m_connections[playerID]->processAck(msg); } } else { - DEBUG_ASSERTCRASH((playerID >= 0) && (playerID < NUM_CONNECTIONS), ("ConnectionManager::processAck - %d is an invalid player number", playerID)); + DEBUG_CRASH(("ConnectionManager::processAck - %d is an invalid player number", playerID)); } if (ref != nullptr) { @@ -1073,7 +1092,7 @@ void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) { if (CommandRequiresDirectSend(msg) && CommandRequiresAck(msg)) { // Send this ack directly back to the sending player, don't go through the packet router. - if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) { + if (msg->getPlayerID() < MAX_SLOTS) { if (m_connections[msg->getPlayerID()] != nullptr) { m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID()); } @@ -1086,21 +1105,21 @@ void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) { m_connections[m_packetRouterSlot]->sendNetCommandMsg(ackmsg, 1 << m_packetRouterSlot); } else if (m_localSlot == m_packetRouterSlot) { // we are the packet router, send the ack to the player that sent the command. - if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) { + if (msg->getPlayerID() < MAX_SLOTS) { if (m_connections[msg->getPlayerID()] != nullptr) { // DEBUG_LOG(("ConnectionManager::ackCommand - acking command %d from player %d directly to player.", commandID, msg->getPlayerID())); m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID()); } else { - // DEBUG_ASSERTCRASH(m_connections[msg->getPlayerID()] != nullptr, ("Connection to player is null")); + // DEBUG_CRASH(("Connection to player is null")); } } else { - DEBUG_ASSERTCRASH((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS), ("Command sent by an invalid player ID.")); + DEBUG_CRASH(("Command sent by an invalid player ID.")); } } else { - DEBUG_ASSERTCRASH(m_connections[m_packetRouterSlot] != nullptr, ("Connection to packet router is null")); + DEBUG_CRASH(("Connection to packet router is null")); } } else { - DEBUG_ASSERTCRASH((m_packetRouterSlot >= 0) && (m_packetRouterSlot < MAX_SLOTS), ("I don't know who the packet router is.")); + DEBUG_CRASH(("I don't know who the packet router is.")); } } @@ -1120,11 +1139,13 @@ void ConnectionManager::sendRemoteCommand(NetCommandRef *msg) { DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - sending net command %d of type %s from player %d, relay is 0x%x", msg->getCommand()->getID(), GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getRelay())); - UnsignedByte relay = msg->getRelay(); - if ((relay & (1 << m_localSlot)) && (m_frameData[msg->getCommand()->getPlayerID()] != nullptr)) { + const UnsignedByte relay = msg->getRelay(); + const UnsignedInt playerID = msg->getCommand()->getPlayerID(); + FrameDataManager *frameDataMgr = playerID < MAX_SLOTS ? m_frameData[playerID] : nullptr; + if ((relay & (1 << m_localSlot)) && (frameDataMgr != nullptr)) { if (IsCommandSynchronized(msg->getCommand()->getNetCommandType())) { DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - adding net command of type %s to player %d for frame %d", GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getCommand()->getExecutionFrame())); - m_frameData[msg->getCommand()->getPlayerID()]->addNetCommandMsg(msg->getCommand()); + frameDataMgr->addNetCommandMsg(msg->getCommand()); } } @@ -1190,7 +1211,7 @@ void ConnectionManager::update(Bool isInGame) { // send any necessary keep-alive packets. doKeepAlive(); - for (Int i = 0; i < NUM_CONNECTIONS; ++i) { + for (Int i = 0; i < MAX_SLOTS; ++i) { if (m_connections[i] != nullptr) { /* if (m_connections[i]->isQueueEmpty() == FALSE) { diff --git a/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp index 6aec6e5868..19256a2d54 100644 --- a/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp +++ b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp @@ -371,7 +371,11 @@ void DisconnectManager::processDisconnectVote(NetCommandMsg *msg, ConnectionMana void DisconnectManager::processDisconnectFrame(NetCommandMsg *msg, ConnectionManager *conMgr) { NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)msg; - UnsignedInt playerID = cmdMsg->getPlayerID(); + const UnsignedInt playerID = cmdMsg->getPlayerID(); + if (playerID >= MAX_SLOTS) { + return; + } + if (m_disconnectFrames[playerID] >= cmdMsg->getDisconnectFrame()) { // this message isn't valid, we have a disconnect frame that is later than this already. return; @@ -415,7 +419,7 @@ void DisconnectManager::processDisconnectScreenOff(NetCommandMsg *msg, Connectio DEBUG_LOG(("DisconnectManager::processDisconnectScreenOff - got a screen off command from player %d for frame %d", cmdMsg->getPlayerID(), cmdMsg->getNewFrame())); - if ((playerID < 0) || (playerID >= MAX_SLOTS)) { + if (playerID >= MAX_SLOTS) { return; }