From 128c42210bc93036cb6b9e0f66737244f5185721 Mon Sep 17 00:00:00 2001 From: joris <joris.dauphin@gmail.com> Date: Mon, 8 Apr 2013 16:36:28 +0200 Subject: [PATCH] Fix HandleSuicideClick over network. --- src/network/network.cpp | 161 ++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 74 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index b75eeb01b..d758e91ac 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -735,14 +735,81 @@ static bool IsNetworkCommandReady(unsigned long gameCycle) return true; } -static void NetworkParseInGameEvent(unsigned char *buf, int len, const CHost &host) +static void ParseResendCommand(const CNetworkPacket &packet) { - CNetworkPacket packet; - int commands = packet.Deserialize(buf, len); - if (commands < 0) { - DebugPrint("Bad packet read\n"); + // Destination cycle (time to execute). + unsigned long n = ((GameCycle + 128) & ~0xFF) | packet.Header.Cycle; + if (n > GameCycle + 128) { + n -= 0x100; + } + // FIXME: not necessary to send this packet multiple times!!!! + // other side sends re-send until it gets an answer. + if (n != NetworkIn[n & 0xFF][ThisPlayer->Index][0].Time) { + // Asking for a cycle we haven't gotten to yet, ignore for now return; } + NetworkSendPacket(NetworkIn[n & 0xFF][ThisPlayer->Index]); + // Check if a player quit this cycle + for (int j = 0; j < HostsCount; ++j) { + for (int c = 0; c < MaxNetworkCommands; ++c) { + const CNetworkCommandQueue *ncq; + ncq = &NetworkIn[n & 0xFF][Hosts[j].PlyNr][c]; + if (ncq->Time && ncq->Type == MessageQuit) { + CNetworkPacket np; + np.Header.Cycle = ncq->Time & 0xFF; + np.Header.Type[0] = ncq->Type; + np.Command[0] = ncq->Data; + for (int k = 1; k < MaxNetworkCommands; ++k) { + np.Header.Type[k] = MessageNone; + } + NetworkBroadcast(np, 1); + } + } + } +} + +static bool IsAValidCommand(const CNetworkPacket &packet, int index, const CNetworkCommand &nc) +{ + const int player = Hosts[index].PlyNr; + + switch (packet.Header.Type[index] & 0x7F) { + case MessageExtendedCommand: // FIXME: ensure the sender is part of the command + return true; + case MessageSync: // Sync does not matter + return true; + case MessageQuit: + case MessageQuitAck: + case MessageResend: + case MessageChat: + case MessageChatTerm: + // FIXME: ensure it's from the right player + return true; + case MessageCommandDismiss: { + const unsigned int slot = ntohs(nc.Unit); + const CUnit *unit = slot < UnitManager.GetUsedSlotCount() ? &UnitManager.GetSlotUnit(slot) : NULL; + + if (unit && unit->Type->ClicksToExplode) { + return true; + } + } + // Fall through! + default: { + const unsigned int slot = ntohs(nc.Unit); + const CUnit *unit = slot < UnitManager.GetUsedSlotCount() ? &UnitManager.GetSlotUnit(slot) : NULL; + + if (unit && (unit->Player->Index == player + || Players[player].IsTeamed(*unit))) { + return true; + } else { + return false; + } + } + } + // FIXME: not all values in nc have been validated +} + +static void NetworkParseInGameEvent(unsigned char *buf, int len, const CHost &host) +{ const int index = FindHostIndexBy(host); if (index == -1 || PlayerQuit[Hosts[index].PlyNr]) { #ifdef DEBUG @@ -753,6 +820,12 @@ static void NetworkParseInGameEvent(unsigned char *buf, int len, const CHost &ho } const int player = Hosts[index].PlyNr; + CNetworkPacket packet; + int commands = packet.Deserialize(buf, len); + if (commands < 0) { + DebugPrint("Bad packet read\n"); + return; + } // In a normal packet there is a least sync, selection may not have that if (packet.Header.Type[0] == MessageSelection || commands == 0) { NetworkProcessSelection(packet, player); @@ -761,7 +834,6 @@ static void NetworkParseInGameEvent(unsigned char *buf, int len, const CHost &ho // Parse the packet commands. for (int i = 0; i != commands; ++i) { const CNetworkCommand &nc = packet.Command[i]; - bool validCommand = false; // Handle some messages. if (packet.Header.Type[i] == MessageQuit) { @@ -769,82 +841,23 @@ static void NetworkParseInGameEvent(unsigned char *buf, int len, const CHost &ho if (playerNum >= 0 && playerNum < NumPlayers) { PlayerQuit[playerNum] = 1; - validCommand = true; } } if (packet.Header.Type[i] == MessageResend) { + ParseResendCommand(packet); + return; + } + // Receive statistic + NetworkLastFrame[player] = FrameCounter; + + bool validCommand = IsAValidCommand(packet, i, nc); + // Place in network in + if (validCommand) { // Destination cycle (time to execute). unsigned long n = ((GameCycle + 128) & ~0xFF) | packet.Header.Cycle; if (n > GameCycle + 128) { n -= 0x100; } - // FIXME: not necessary to send this packet multiple times!!!! - // other side sends re-send until it gets an answer. - if (n != NetworkIn[n & 0xFF][ThisPlayer->Index][0].Time) { - // Asking for a cycle we haven't gotten to yet, ignore for now - return; - } - NetworkSendPacket(NetworkIn[n & 0xFF][ThisPlayer->Index]); - // Check if a player quit this cycle - for (int j = 0; j < HostsCount; ++j) { - for (int c = 0; c < MaxNetworkCommands; ++c) { - const CNetworkCommandQueue *ncq; - ncq = &NetworkIn[n & 0xFF][Hosts[j].PlyNr][c]; - if (ncq->Time && ncq->Type == MessageQuit) { - CNetworkPacket np; - np.Header.Cycle = ncq->Time & 0xFF; - np.Header.Type[0] = ncq->Type; - np.Command[0] = ncq->Data; - for (int k = 1; k < MaxNetworkCommands; ++k) { - np.Header.Type[k] = MessageNone; - } - NetworkBroadcast(np, 1); - } - } - } - return; - } - // Destination cycle (time to execute). - unsigned long n = ((GameCycle + 128) & ~0xFF) | packet.Header.Cycle; - if (n > GameCycle + 128) { - n -= 0x100; - } - // Receive statistic - NetworkLastFrame[player] = FrameCounter; - - // Place in network in - switch (packet.Header.Type[i] & 0x7F) { - case MessageExtendedCommand: - // FIXME: ensure the sender is part of the command - validCommand = true; - break; - case MessageSync: - // Sync does not matter - validCommand = true; - break; - case MessageQuit: - case MessageQuitAck: - case MessageResend: - case MessageChat: - case MessageChatTerm: - // FIXME: ensure it's from the right player - validCommand = true; - break; - case MessageCommandDismiss: // Fall through! - default: { - const unsigned int slot = ntohs(nc.Unit); - const CUnit *unit = slot < UnitManager.GetUsedSlotCount() ? &UnitManager.GetSlotUnit(slot) : NULL; - - if (unit && (unit->Player->Index == player - || Players[player].IsTeamed(*unit))) { - validCommand = true; - } else { - validCommand = false; - } - } - } - // FIXME: not all values in nc have been validated - if (validCommand) { NetworkIn[packet.Header.Cycle][player][i].Time = n; NetworkIn[packet.Header.Cycle][player][i].Type = packet.Header.Type[i]; NetworkIn[packet.Header.Cycle][player][i].Data = nc;