diff --git a/Core/GameEngine/Include/GameNetwork/NetCommandList.h b/Core/GameEngine/Include/GameNetwork/NetCommandList.h index 3e042d92123..cb7f262415a 100644 --- a/Core/GameEngine/Include/GameNetwork/NetCommandList.h +++ b/Core/GameEngine/Include/GameNetwork/NetCommandList.h @@ -50,6 +50,7 @@ class NetCommandList : public MemoryPoolObject void init(); ///< Initialize the list void reset(); ///< Reset the list to the initial state. NetCommandRef * addMessage(NetCommandMsg *cmdMsg); ///< Add message to the list in its properly ordered place. + NetCommandRef * addMessage(NetCommandRef *&msg); ///< Add message to the list in its properly ordered place. Bool isEqualCommandMsg(NetCommandMsg *msg1, NetCommandMsg *msg2); NetCommandRef * getFirstMessage(); ///< Get the first message on the list. NetCommandRef * findMessage(NetCommandMsg *msg); ///< Find and return a reference to the given message if one exists. diff --git a/Core/GameEngine/Include/GameNetwork/NetCommandMsg.h b/Core/GameEngine/Include/GameNetwork/NetCommandMsg.h index 6b97d8fbef4..888b3d93d8e 100644 --- a/Core/GameEngine/Include/GameNetwork/NetCommandMsg.h +++ b/Core/GameEngine/Include/GameNetwork/NetCommandMsg.h @@ -35,6 +35,61 @@ class NetCommandRef; +//----------------------------------------------------------------------------- +class NetCommandDataChunk +{ + NetCommandDataChunk(const NetCommandDataChunk&) CPP_11(= delete); + void operator=(const NetCommandDataChunk&) CPP_11(= delete); + +public: + NetCommandDataChunk(Byte *data, UnsignedInt size) + : m_data(reinterpret_cast(data)) + , m_size(size) + {} + + NetCommandDataChunk(UnsignedByte *data, UnsignedInt size) + : m_data(data) + , m_size(size) + {} + + NetCommandDataChunk(UnsignedInt size) + : m_data(NEW UnsignedByte[size]) + , m_size(size) + {} + + ~NetCommandDataChunk() + { + delete[] m_data; + } + + const UnsignedByte *data() const + { + return m_data; + } + + UnsignedByte *data() + { + return m_data; + } + + UnsignedInt size() const + { + return m_size; + } + + UnsignedByte *release() + { + UnsignedByte *ret = m_data; + m_data = nullptr; + m_size = 0; + return ret; + } + +private: + UnsignedByte *m_data; + UnsignedInt m_size; +}; + //----------------------------------------------------------------------------- class NetCommandMsg : public MemoryPoolObject { @@ -60,6 +115,7 @@ class NetCommandMsg : public MemoryPoolObject virtual size_t getSizeForSmallNetPacket(const Select* select = nullptr) const = 0; virtual size_t copyBytesForSmallNetPacket(UnsignedByte* buffer, const NetCommandRef& ref, const Select* select = nullptr) const = 0; virtual Select getSmallNetPacketSelect() const = 0; + virtual size_t readMessageData(NetCommandRef& ref, NetPacketBuf buf) const = 0; void attach(); void detach(); @@ -77,25 +133,30 @@ class NetCommandMsg : public MemoryPoolObject template class NetCommandMsgT : public NetCommandMsg { - virtual size_t getSizeForNetPacket() const + virtual size_t getSizeForNetPacket() const override { return NetPacketType::getSize(*this); } - virtual size_t copyBytesForNetPacket(UnsignedByte* buffer, const NetCommandRef& ref) const + virtual size_t copyBytesForNetPacket(UnsignedByte* buffer, const NetCommandRef& ref) const override { return NetPacketType::copyBytes(buffer, ref); } - virtual size_t getSizeForSmallNetPacket(const Select* select = nullptr) const + virtual size_t getSizeForSmallNetPacket(const Select* select = nullptr) const override { return SmallNetPacketType::getSize(*this, select); } - virtual size_t copyBytesForSmallNetPacket(UnsignedByte* buffer, const NetCommandRef& ref, const Select* select = nullptr) const + virtual size_t copyBytesForSmallNetPacket(UnsignedByte* buffer, const NetCommandRef& ref, const Select* select = nullptr) const override { return SmallNetPacketType::copyBytes(buffer, ref, select); } + + virtual size_t readMessageData(NetCommandRef& ref, NetPacketBuf buf) const override + { + return SmallNetPacketType::CommandData::readMessage(ref, buf); + } }; //----------------------------------------------------------------------------- @@ -114,7 +175,7 @@ class NetGameCommandMsg : public NetCommandMsgT @@ -615,5 +676,5 @@ class NetTimeOutGameStartCommandMsg : public NetCommandMsgT +size_t readObject(T &value, NetPacketBuf src) +{ + const size_t readLen = min(sizeof(value), src.size()); + memcpy(&value, src.data(), readLen); + return readLen; +} + +inline size_t readBytes(UnsignedByte *dest, size_t destLen, NetPacketBuf src) +{ + const size_t readLen = min(destLen, src.size()); + memcpy(dest, src.data(), readLen); + return readLen; +} + +inline size_t readStringWithoutNull(UnicodeString &str, size_t maxStrLen, NetPacketBuf src) +{ + const size_t strLen = min(maxStrLen, src.size() / sizeof(WideChar)); + const size_t cpyLen = strLen * sizeof(WideChar); + + if (strLen > 0) + { + WideChar *strBuf = str.getBufferForRead(strLen); + memcpy(strBuf, src.data(), cpyLen); + strBuf[strLen] = 0; + } + return cpyLen; +} + +inline size_t readStringWithNull(AsciiString &str, size_t maxStrLen, NetPacketBuf src) +{ + const size_t realStrLen = strnlen(reinterpret_cast(src.data()), src.size()); + const size_t usedStrLen = min(realStrLen, maxStrLen); + const size_t realCpyLen = realStrLen * sizeof(char); + const size_t usedCpyLen = usedStrLen * sizeof(char); + + if (usedStrLen > 0) + { + char *strBuf = str.getBufferForRead(usedStrLen); + memcpy(strBuf, src.data(), usedCpyLen); + strBuf[usedStrLen] = 0; + } + return realCpyLen + sizeof(char); +} + template size_t writePrimitive(UnsignedByte *dest, T value) { @@ -70,19 +155,19 @@ size_t writePrimitive(UnsignedByte *dest, T value) } template -size_t writeObject(UnsignedByte *dest, const T& value) +size_t writeObject(UnsignedByte *dest, const T &value) { memcpy(dest, &value, sizeof(value)); return sizeof(value); } -inline size_t writeBytes(UnsignedByte *dest, const UnsignedByte* src, size_t len) +inline size_t writeBytes(UnsignedByte *dest, const UnsignedByte *src, size_t len) { memcpy(dest, src, len); return len; } -inline size_t writeStringWithoutNull(UnsignedByte *dest, const UnicodeString& value, size_t maxLen) +inline size_t writeStringWithoutNull(UnsignedByte *dest, const UnicodeString &value, size_t maxLen) { const size_t copyLen = std::min(value.getLength(), maxLen); const size_t copyBytes = copyLen * sizeof(WideChar); @@ -90,7 +175,7 @@ inline size_t writeStringWithoutNull(UnsignedByte *dest, const UnicodeString& va return copyBytes; } -inline size_t writeStringWithNull(UnsignedByte *dest, const AsciiString& value) +inline size_t writeStringWithNull(UnsignedByte *dest, const AsciiString &value) { memcpy(dest, value.str(), value.getByteCount() + 1); return static_cast(value.getByteCount() + 1); @@ -125,48 +210,48 @@ namespace NetPacketFieldTypes struct NetPacketCommandTypeField { NetPacketCommandTypeField() : fieldType(NetPacketFieldTypes::CommandType) {} - char fieldType; + const NetPacketFieldType fieldType; UnsignedByte commandType; }; struct NetPacketRelayField { NetPacketRelayField() : fieldType(NetPacketFieldTypes::Relay) {} - char fieldType; + const NetPacketFieldType fieldType; UnsignedByte relay; }; struct NetPacketFrameField { NetPacketFrameField() : fieldType(NetPacketFieldTypes::Frame) {} - char fieldType; + const NetPacketFieldType fieldType; UnsignedInt frame; }; struct NetPacketPlayerIdField { NetPacketPlayerIdField() : fieldType(NetPacketFieldTypes::PlayerId) {} - char fieldType; + const NetPacketFieldType fieldType; UnsignedByte playerId; }; struct NetPacketCommandIdField { NetPacketCommandIdField() : fieldType(NetPacketFieldTypes::CommandId) {} - char fieldType; + const NetPacketFieldType fieldType; UnsignedShort commandId; }; struct NetPacketDataField { NetPacketDataField() : fieldType(NetPacketFieldTypes::Data) {} - char fieldType; + const NetPacketFieldType fieldType; }; struct NetPacketRepeatField { NetPacketRepeatField() : fieldType(NetPacketFieldTypes::Repeat) {} - char fieldType; + const NetPacketFieldType fieldType; }; //////////////////////////////////////////////////////////////////////////////// @@ -222,6 +307,9 @@ struct SmallNetPacketCommandBase static size_t getSize(const SmallNetPacketCommandBaseSelect *select = nullptr); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref, const SmallNetPacketCommandBaseSelect *select = nullptr); + static size_t readMessage(NetCommandRef *&ref, CommandBase &base, NetPacketBuf buf); +private: + static NetCommandMsg *constructNetCommandMsg(const CommandBase &base); }; //////////////////////////////////////////////////////////////////////////////// @@ -286,6 +374,7 @@ struct NetPacketNoData static size_t getSize(const NetCommandMsg &) { return 0; } static size_t copyBytes(UnsignedByte *, const NetCommandRef &) { return 0; } + static size_t readMessage(NetCommandRef &, NetPacketBuf) { return 0; } }; //////////////////////////////////////////////////////////////////////////////// @@ -304,6 +393,7 @@ struct NetPacketAckCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketAckCommandBase @@ -339,6 +429,7 @@ struct NetPacketFrameCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketFrameCommandBase @@ -374,6 +465,7 @@ struct NetPacketPlayerLeaveCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketPlayerLeaveCommandBase @@ -410,6 +502,7 @@ struct NetPacketRunAheadMetricsCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketRunAheadMetricsCommandBase @@ -446,6 +539,7 @@ struct NetPacketRunAheadCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketRunAheadCommandBase @@ -481,6 +575,7 @@ struct NetPacketDestroyPlayerCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketDestroyPlayerCommandBase @@ -521,6 +616,7 @@ struct NetPacketKeepAliveCommandBase static size_t getSize() { return sizeof(CommandBase); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; //////////////////////////////////////////////////////////////////////////////// @@ -560,6 +656,7 @@ struct NetPacketDisconnectPlayerCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketDisconnectPlayerCommandBase @@ -639,6 +736,7 @@ struct NetPacketDisconnectVoteCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketDisconnectVoteCommandBase @@ -669,6 +767,7 @@ struct NetPacketChatCommandData static size_t getSize(const NetCommandMsg &msg); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketChatCommandBase @@ -699,6 +798,7 @@ struct NetPacketDisconnectChatCommandData static size_t getSize(const NetCommandMsg &msg); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketDisconnectChatCommandBase @@ -729,6 +829,7 @@ struct NetPacketGameCommandData static size_t getSize(const NetCommandMsg &msg); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketGameCommandBase @@ -769,6 +870,7 @@ struct NetPacketWrapperCommandData static size_t getSize(const NetCommandMsg &msg); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketWrapperCommandBase @@ -798,6 +900,7 @@ struct NetPacketFileCommandData static size_t getSize(const NetCommandMsg &msg); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketFileCommandBase @@ -828,6 +931,7 @@ struct NetPacketFileAnnounceCommandData static size_t getSize(const NetCommandMsg &msg); static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketFileAnnounceCommandBase @@ -864,6 +968,7 @@ struct NetPacketFileProgressCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketFileProgressCommandBase @@ -899,6 +1004,7 @@ struct NetPacketProgressCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketProgressCommandBase @@ -978,6 +1084,7 @@ struct NetPacketDisconnectFrameCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketDisconnectFrameCommandBase @@ -1013,6 +1120,7 @@ struct NetPacketDisconnectScreenOffCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketDisconnectScreenOffCommandBase @@ -1048,6 +1156,7 @@ struct NetPacketFrameResendRequestCommandData static size_t getSize(const NetCommandMsg &msg) { return sizeof(FixedData); } static size_t copyBytes(UnsignedByte *buffer, const NetCommandRef &ref); + static size_t readMessage(NetCommandRef &ref, NetPacketBuf buf); }; struct NetPacketFrameResendRequestCommandBase diff --git a/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp index f81dd0b290c..39239e54684 100644 --- a/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp +++ b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp @@ -722,7 +722,7 @@ void ConnectionManager::processFile(NetFileCommandMsg *msg) // uncompress Targas #ifdef COMPRESS_TARGAS Bool deleteBuf = FALSE; - if (msg->getFilename().endsWith(".tga") && CompressionManager::isDataCompressed(buf, len)) + if (msg->getPortableFilename().endsWith(".tga") && CompressionManager::isDataCompressed(buf, len)) { Int uncompLen = CompressionManager::getUncompressedSize(buf, len); UnsignedByte *uncompBuffer = NEW UnsignedByte[uncompLen]; @@ -2196,6 +2196,7 @@ void ConnectionManager::sendFile(AsciiString path, UnsignedByte playerMask, Unsi Int len = theFile->size(); char *buf = theFile->readEntireAndClose(); + NetCommandDataChunk rawDataChunk(buf, len); // compress Targas #ifdef COMPRESS_TARGAS @@ -2211,35 +2212,31 @@ void ConnectionManager::sendFile(AsciiString path, UnsignedByte playerMask, Unsi delete[] compressedBuf; compressedBuf = nullptr; } + + NetCommandDataChunk compressedDataChunk(compressedBuf, compressedSize); #endif // COMPRESS_TARGAS NetFileCommandMsg *fileMsg = newInstance(NetFileCommandMsg); fileMsg->setPlayerID(m_localSlot); fileMsg->setID(commandID); fileMsg->setRealFilename(path); + #ifdef COMPRESS_TARGAS if (compressedBuf) { DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Compressed '%s' from %d to %d (%g%%) before transfer", path.str(), len, compressedSize, (Real)compressedSize/(Real)len*100.0f)); - fileMsg->setFileData((unsigned char *)compressedBuf, compressedSize); + fileMsg->setFileData(compressedDataChunk); } else #endif // COMPRESS_TARGAS { - fileMsg->setFileData((unsigned char *)buf, len); + fileMsg->setFileData(rawDataChunk); } DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFile() - creating file message with ID of %d for '%s' going to %X from %d, size of %d", fileMsg->getID(), fileMsg->getRealFilename().str(), playerMask, fileMsg->getPlayerID(), fileMsg->getFileLength())); - delete[] buf; - buf = nullptr; -#ifdef COMPRESS_TARGAS - delete[] compressedBuf; - compressedBuf = nullptr; -#endif // COMPRESS_TARGAS - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Sending file: '%s', len %d, to %X", path.str(), len, playerMask)); sendLocalCommand(fileMsg, playerMask); diff --git a/Core/GameEngine/Source/GameNetwork/NetCommandList.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandList.cpp index b6a834c987b..579b8578c72 100644 --- a/Core/GameEngine/Source/GameNetwork/NetCommandList.cpp +++ b/Core/GameEngine/Source/GameNetwork/NetCommandList.cpp @@ -128,13 +128,19 @@ void NetCommandList::reset() { */ NetCommandRef * NetCommandList::addMessage(NetCommandMsg *cmdMsg) { if (cmdMsg == nullptr) { - DEBUG_ASSERTCRASH(cmdMsg != nullptr, ("NetCommandList::addMessage - command message was null")); + DEBUG_CRASH(("NetCommandList::addMessage - command message was null")); return nullptr; } -// UnsignedInt id = cmdMsg->getID(); - NetCommandRef *msg = NEW_NETCOMMANDREF(cmdMsg); + return addMessage(msg); +} + +NetCommandRef * NetCommandList::addMessage(NetCommandRef *&msg) { + if (msg == nullptr) { + DEBUG_CRASH(("NetCommandList::addMessage - command ref was null")); + return nullptr; + } if (m_first == nullptr) { // this is the first node, so we don't have to worry about ordering it. @@ -304,6 +310,7 @@ NetCommandRef * NetCommandList::addMessage(NetCommandMsg *cmdMsg) { // This command is already in the list, don't duplicate it. deleteInstance(msg); + msg = nullptr; return nullptr; } diff --git a/Core/GameEngine/Source/GameNetwork/NetCommandMsg.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandMsg.cpp index dd652a6cba3..4be0ff253e7 100644 --- a/Core/GameEngine/Source/GameNetwork/NetCommandMsg.cpp +++ b/Core/GameEngine/Source/GameNetwork/NetCommandMsg.cpp @@ -937,12 +937,11 @@ UnsignedByte * NetWrapperCommandMsg::getData() { return m_data; } -void NetWrapperCommandMsg::setData(UnsignedByte *data, UnsignedInt dataLength) +void NetWrapperCommandMsg::setData(NetCommandDataChunk &dataChunk) { delete[] m_data; - m_data = NEW UnsignedByte[dataLength]; // pool[]ify - memcpy(m_data, data, dataLength); - m_dataLength = dataLength; + m_dataLength = dataChunk.size(); + m_data = dataChunk.release(); } UnsignedInt NetWrapperCommandMsg::getDataLength() const { @@ -1036,11 +1035,11 @@ UnsignedByte * NetFileCommandMsg::getFileData() { return m_data; } -void NetFileCommandMsg::setFileData(UnsignedByte *data, UnsignedInt dataLength) +void NetFileCommandMsg::setFileData(NetCommandDataChunk &dataChunk) { - m_dataLength = dataLength; - m_data = NEW UnsignedByte[dataLength]; // pool[]ify - memcpy(m_data, data, dataLength); + delete[] m_data; + m_dataLength = dataChunk.size(); + m_data = dataChunk.release(); } NetCommandMsg::Select NetFileCommandMsg::getSmallNetPacketSelect() const { diff --git a/Core/GameEngine/Source/GameNetwork/NetCommandRef.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandRef.cpp index 470a387ff77..ba59cab5694 100644 --- a/Core/GameEngine/Source/GameNetwork/NetCommandRef.cpp +++ b/Core/GameEngine/Source/GameNetwork/NetCommandRef.cpp @@ -41,9 +41,13 @@ NetCommandRef::NetCommandRef(NetCommandMsg *msg) #endif { m_msg = msg; + if (m_msg != nullptr) + { + m_msg->attach(); + } m_next = nullptr; m_prev = nullptr; - m_msg->attach(); + m_relay = 0; m_timeLastSent = -1; #ifdef DEBUG_NETCOMMANDREF @@ -61,7 +65,7 @@ NetCommandRef::~NetCommandRef() { m_msg->detach(); } - DEBUG_ASSERTCRASH(m_next == nullptr, ("NetCommandRef::~NetCommandRef - m_next != nullptr")); + DEBUG_ASSERTCRASH(m_next == nullptr, ("NetCommandRef::~NetCommandRef - m_next != nullptr")); DEBUG_ASSERTCRASH(m_prev == nullptr, ("NetCommandRef::~NetCommandRef - m_prev != nullptr")); #ifdef DEBUG_NETCOMMANDREF diff --git a/Core/GameEngine/Source/GameNetwork/NetPacket.cpp b/Core/GameEngine/Source/GameNetwork/NetPacket.cpp index 2c59457c84c..c04446d7e51 100644 --- a/Core/GameEngine/Source/GameNetwork/NetPacket.cpp +++ b/Core/GameEngine/Source/GameNetwork/NetPacket.cpp @@ -34,160 +34,38 @@ #include "GameNetwork/NetPacketStructs.h" -// This function assumes that all of the fields are either of default value or are -// present in the raw data. -NetCommandRef * NetPacket::ConstructNetCommandMsgFromRawData(UnsignedByte *data, UnsignedShort dataLength) { - NetCommandType commandType = NETCOMMANDTYPE_GAMECOMMAND; - UnsignedByte commandTypeByte = static_cast(commandType); - UnsignedShort commandID = 0; - UnsignedInt frame = 0; - UnsignedByte playerID = 0; - UnsignedByte relay = 0; - - Int offset = 0; - NetCommandRef *ref = nullptr; - NetCommandMsg *msg = nullptr; - - while (offset < (Int)dataLength) { - - switch (data[offset]) { - - case NetPacketFieldTypes::CommandType: - ++offset; - memcpy(&commandTypeByte, data + offset, sizeof(commandTypeByte)); - offset += sizeof(commandTypeByte); - commandType = static_cast(commandTypeByte); - break; - - case NetPacketFieldTypes::Relay: - ++offset; - memcpy(&relay, data + offset, sizeof(relay)); - offset += sizeof(relay); - break; - - case NetPacketFieldTypes::Frame: - ++offset; - memcpy(&frame, data + offset, sizeof(frame)); - offset += sizeof(frame); - break; - - case NetPacketFieldTypes::PlayerId: - ++offset; - memcpy(&playerID, data + offset, sizeof(playerID)); - offset += sizeof(playerID); - break; - - case NetPacketFieldTypes::CommandId: - ++offset; - memcpy(&commandID, data + offset, sizeof(commandID)); - offset += sizeof(commandID); - break; - - case NetPacketFieldTypes::Data: - ++offset; - - switch (commandType) { - - case NETCOMMANDTYPE_GAMECOMMAND: - msg = readGameMessage(data, offset); - break; - case NETCOMMANDTYPE_ACKBOTH: - msg = readAckBothMessage(data, offset); - break; - case NETCOMMANDTYPE_ACKSTAGE1: - msg = readAckStage1Message(data, offset); - break; - case NETCOMMANDTYPE_ACKSTAGE2: - msg = readAckStage2Message(data, offset); - break; - case NETCOMMANDTYPE_FRAMEINFO: - msg = readFrameMessage(data, offset); - break; - case NETCOMMANDTYPE_PLAYERLEAVE: - msg = readPlayerLeaveMessage(data, offset); - break; - case NETCOMMANDTYPE_RUNAHEADMETRICS: - msg = readRunAheadMetricsMessage(data, offset); - break; - case NETCOMMANDTYPE_RUNAHEAD: - msg = readRunAheadMessage(data, offset); - break; - case NETCOMMANDTYPE_DESTROYPLAYER: - msg = readDestroyPlayerMessage(data, offset); - break; - case NETCOMMANDTYPE_KEEPALIVE: - msg = readKeepAliveMessage(data, offset); - break; - case NETCOMMANDTYPE_DISCONNECTKEEPALIVE: - msg = readDisconnectKeepAliveMessage(data, offset); - break; - case NETCOMMANDTYPE_DISCONNECTPLAYER: - msg = readDisconnectPlayerMessage(data, offset); - break; - case NETCOMMANDTYPE_PACKETROUTERQUERY: - msg = readPacketRouterQueryMessage(data, offset); - break; - case NETCOMMANDTYPE_PACKETROUTERACK: - msg = readPacketRouterAckMessage(data, offset); - break; - case NETCOMMANDTYPE_DISCONNECTCHAT: - msg = readDisconnectChatMessage(data, offset); - break; - case NETCOMMANDTYPE_DISCONNECTVOTE: - msg = readDisconnectVoteMessage(data, offset); - break; - case NETCOMMANDTYPE_CHAT: - msg = readChatMessage(data, offset); - break; - case NETCOMMANDTYPE_PROGRESS: - msg = readProgressMessage(data, offset); - break; - case NETCOMMANDTYPE_LOADCOMPLETE: - msg = readLoadCompleteMessage(data, offset); - break; - case NETCOMMANDTYPE_TIMEOUTSTART: - msg = readTimeOutGameStartMessage(data, offset); - break; - case NETCOMMANDTYPE_WRAPPER: - msg = readWrapperMessage(data, offset); - break; - case NETCOMMANDTYPE_FILE: - msg = readFileMessage(data, offset); - break; - case NETCOMMANDTYPE_FILEANNOUNCE: - msg = readFileAnnounceMessage(data, offset); - break; - case NETCOMMANDTYPE_FILEPROGRESS: - msg = readFileProgressMessage(data, offset); - break; - case NETCOMMANDTYPE_DISCONNECTFRAME: - msg = readDisconnectFrameMessage(data, offset); - break; - case NETCOMMANDTYPE_DISCONNECTSCREENOFF: - msg = readDisconnectScreenOffMessage(data, offset); - break; - case NETCOMMANDTYPE_FRAMERESENDREQUEST: - msg = readFrameResendRequestMessage(data, offset); - break; - - } - - msg->setExecutionFrame(frame); - msg->setID(commandID); - msg->setPlayerID(playerID); - msg->setNetCommandType(commandType); - - ref = NEW_NETCOMMANDREF(msg); - - ref->setRelay(relay); +static size_t constructNetCommandRef(NetCommandRef *&ref, SmallNetPacketCommandBase::CommandBase &base, NetPacketBuf buf) +{ + size_t size = SmallNetPacketCommandBase::readMessage(ref, base, buf); - msg->detach(); - msg = nullptr; + if (ref != nullptr) + { + DEBUG_ASSERTCRASH(ref->getCommand() != nullptr, ("constructNetCommandRef: ref->getCommand() is null")); + size += ref->getCommand()->readMessageData(*ref, buf.offset(size)); + } - return ref; + return size; +} - } +// This function assumes that all of the fields are either of default value or are +// present in the raw data. +NetCommandRef *NetPacket::ConstructNetCommandMsgFromRawData(const UnsignedByte *data, UnsignedInt dataLength) { + SmallNetPacketCommandBase::CommandBase commandBase; + commandBase.commandType.commandType = static_cast(NETCOMMANDTYPE_GAMECOMMAND); + commandBase.relay.relay = 0; + commandBase.frame.frame = 0; + commandBase.playerId.playerId = 0; + commandBase.commandId.commandId = 0; + + NetPacketBuf buf(data, dataLength); + NetCommandRef *ref = nullptr; + constructNetCommandRef(ref, commandBase, buf); + if (ref == nullptr) + { + DEBUG_CRASH(("Unrecognized packet entry, ignoring.")); + DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::ConstructNetCommandMsgFromRawData - Unrecognized packet")); + dumpPacketToLog(data, dataLength); } return ref; @@ -230,10 +108,12 @@ NetPacketList NetPacket::ConstructBigCommandPacketList(NetCommandRef *ref) { while (currentChunk < numChunks) { NetPacket *packet = newInstance(NetPacket); - UnsignedShort dataSizeThisPacket = commandSizePerPacket; + UnsignedInt dataSizeThisPacket = commandSizePerPacket; if ((bufferSize - bigPacketCurrentOffset) < dataSizeThisPacket) { dataSizeThisPacket = bufferSize - bigPacketCurrentOffset; } + NetCommandDataChunk bigPacket(dataSizeThisPacket); + memcpy(bigPacket.data(), bigPacketData + bigPacketCurrentOffset, bigPacket.size()); if (DoesCommandRequireACommandID(wrapperMsg->getNetCommandType())) { wrapperMsg->setID(GenerateNextCommandID()); @@ -244,13 +124,13 @@ NetPacketList NetPacket::ConstructBigCommandPacketList(NetCommandRef *ref) { wrapperMsg->setChunkNumber(currentChunk); wrapperMsg->setNumChunks(numChunks); wrapperMsg->setDataOffset(bigPacketCurrentOffset); - wrapperMsg->setData(bigPacketData + bigPacketCurrentOffset, dataSizeThisPacket); + wrapperMsg->setData(bigPacket); wrapperMsg->setTotalDataLength(bufferSize); wrapperMsg->setWrappedCommandID(msg->getID()); bigPacketCurrentOffset += dataSizeThisPacket; - NetCommandRef * ref = NEW_NETCOMMANDREF(wrapperMsg); + NetCommandRef *ref = NEW_NETCOMMANDREF(wrapperMsg); ref->setRelay(ref->getRelay()); if (packet->addCommand(ref) == FALSE) { @@ -527,204 +407,58 @@ Bool NetPacket::isAckStage2Repeat(NetCommandRef *msg) { */ NetCommandList * NetPacket::getCommandList() { NetCommandList *retval = newInstance(NetCommandList); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList, packet length = %d", m_packetLen)); retval->init(); // These need to be the same as the default values for m_lastPlayerID, m_lastFrame, etc. - UnsignedByte playerID = 0; - UnsignedInt frame = 0; - UnsignedShort commandID = 1; // The first command is going to be - UnsignedByte commandType = 0; - UnsignedByte relay = 0; + SmallNetPacketCommandBase::CommandBase commandBase; + commandBase.commandType.commandType = 0; + commandBase.relay.relay = 0; + commandBase.frame.frame = 0; + commandBase.playerId.playerId = 0; + commandBase.commandId.commandId = 1; // The first command is going to be + NetCommandRef *lastCommand = nullptr; Int i = 0; - while (i < m_packetLen) { - - switch(m_packet[i]) { - - case NetPacketFieldTypes::CommandType: - ++i; - memcpy(&commandType, m_packet + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - break; - case NetPacketFieldTypes::Frame: - ++i; - memcpy(&frame, m_packet + i, sizeof(UnsignedInt)); - i += sizeof(UnsignedInt); - break; - case NetPacketFieldTypes::PlayerId: - ++i; - memcpy(&playerID, m_packet + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - break; - case NetPacketFieldTypes::Relay: - ++i; - memcpy(&relay, m_packet + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - break; - case NetPacketFieldTypes::CommandId: - ++i; - memcpy(&commandID, m_packet + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - break; - case NetPacketFieldTypes::Data: { - ++i; + NetPacketBuf buf(m_packet, m_packetLen); - NetCommandMsg *msg = nullptr; + while (i < buf.size()) + { + const Bool isRepeat = m_packet[i] == NetPacketFieldTypes::Repeat; - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList() - command of type %d(%s)", commandType, GetNetCommandTypeAsString((NetCommandType)commandType))); + if (!isRepeat) + { + NetCommandRef *ref = nullptr; + i += constructNetCommandRef(ref, commandBase, buf.offset(i)); - switch((NetCommandType)commandType) + if (ref == nullptr) { - case NETCOMMANDTYPE_GAMECOMMAND: - msg = readGameMessage(m_packet, i); - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read game command from player %d for frame %d", playerID, frame)); - break; - case NETCOMMANDTYPE_ACKBOTH: - msg = readAckBothMessage(m_packet, i); - break; - case NETCOMMANDTYPE_ACKSTAGE1: - msg = readAckStage1Message(m_packet, i); - break; - case NETCOMMANDTYPE_ACKSTAGE2: - msg = readAckStage2Message(m_packet, i); - break; - case NETCOMMANDTYPE_FRAMEINFO: - msg = readFrameMessage(m_packet, i); - // frameinfodebug - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read frame %d from player %d, command count = %d, relay = 0x%X", frame, playerID, ((NetFrameCommandMsg *)msg)->getCommandCount(), relay)); - break; - case NETCOMMANDTYPE_PLAYERLEAVE: - msg = readPlayerLeaveMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read player leave message from player %d for execution on frame %d", playerID, frame)); - break; - case NETCOMMANDTYPE_RUNAHEADMETRICS: - msg = readRunAheadMetricsMessage(m_packet, i); - break; - case NETCOMMANDTYPE_RUNAHEAD: - msg = readRunAheadMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read run ahead message from player %d for execution on frame %d", playerID, frame)); - break; - case NETCOMMANDTYPE_DESTROYPLAYER: - msg = readDestroyPlayerMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read CRC info message from player %d for execution on frame %d", playerID, frame)); - break; - case NETCOMMANDTYPE_KEEPALIVE: - msg = readKeepAliveMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read keep alive message from player %d", playerID)); - break; - case NETCOMMANDTYPE_DISCONNECTKEEPALIVE: - msg = readDisconnectKeepAliveMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read keep alive message from player %d", playerID)); - break; - case NETCOMMANDTYPE_DISCONNECTPLAYER: - msg = readDisconnectPlayerMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect player message from player %d", playerID)); - break; - case NETCOMMANDTYPE_PACKETROUTERQUERY: - msg = readPacketRouterQueryMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read packet router query message from player %d", playerID)); - break; - case NETCOMMANDTYPE_PACKETROUTERACK: - msg = readPacketRouterAckMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read packet router ack message from player %d", playerID)); - break; - case NETCOMMANDTYPE_DISCONNECTCHAT: - msg = readDisconnectChatMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect chat message from player %d", playerID)); - break; - case NETCOMMANDTYPE_DISCONNECTVOTE: - msg = readDisconnectVoteMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect vote message from player %d", playerID)); - break; - case NETCOMMANDTYPE_CHAT: - msg = readChatMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read chat message from player %d", playerID)); - break; - case NETCOMMANDTYPE_PROGRESS: - msg = readProgressMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read Progress message from player %d", playerID)); - break; - case NETCOMMANDTYPE_LOADCOMPLETE: - msg = readLoadCompleteMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read LoadComplete message from player %d", playerID)); - break; - case NETCOMMANDTYPE_TIMEOUTSTART: - msg = readTimeOutGameStartMessage(m_packet, i); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read TimeOutGameStart message from player %d", playerID)); - break; - case NETCOMMANDTYPE_WRAPPER: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read Wrapper message from player %d", playerID)); - msg = readWrapperMessage(m_packet, i); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Done reading Wrapper message from player %d - wrapped command was %d", playerID, - ((NetWrapperCommandMsg *)msg)->getWrappedCommandID())); - break; - case NETCOMMANDTYPE_FILE: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read file message from player %d", playerID)); - msg = readFileMessage(m_packet, i); - break; - case NETCOMMANDTYPE_FILEANNOUNCE: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read file announce message from player %d", playerID)); - msg = readFileAnnounceMessage(m_packet, i); - break; - case NETCOMMANDTYPE_FILEPROGRESS: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read file progress message from player %d", playerID)); - msg = readFileProgressMessage(m_packet, i); - break; - case NETCOMMANDTYPE_DISCONNECTFRAME: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect frame message from player %d", playerID)); - msg = readDisconnectFrameMessage(m_packet, i); - break; - case NETCOMMANDTYPE_DISCONNECTSCREENOFF: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect screen off message from player %d", playerID)); - msg = readDisconnectScreenOffMessage(m_packet, i); - break; - case NETCOMMANDTYPE_FRAMERESENDREQUEST: - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read frame resend request message from player %d", playerID)); - msg = readFrameResendRequestMessage(m_packet, i); - break; - } - - if (msg == nullptr) { - DEBUG_CRASH(("Didn't read a message from the packet. Things are about to go wrong.")); + // we don't recognize this command, but we have to increment i so we don't fall into an infinite loop. + DEBUG_CRASH(("Unrecognized packet entry, ignoring.")); + DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList - Unrecognized packet entry at index %d", i)); + dumpPacketToLog(m_packet, m_packetLen); continue; } - // set the info - msg->setExecutionFrame(frame); - msg->setPlayerID(playerID); - msg->setNetCommandType((NetCommandType)commandType); - msg->setID(commandID); - -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("frame = %d, player = %d, command type = %d, id = %d", frame, playerID, commandType, commandID)); - // increment to the next command ID. - if (DoesCommandRequireACommandID((NetCommandType)commandType)) { - ++commandID; + if (DoesCommandRequireACommandID((NetCommandType)commandBase.commandType.commandType)) { + ++commandBase.commandId.commandId; } + NetCommandMsg *msg = ref->getCommand(); + msg->attach(); + // add the message to the list. - NetCommandRef *ref = retval->addMessage(msg); - if (ref != nullptr) { - ref->setRelay(relay); - } else { - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList - failed to set relay for message %d", msg->getID())); - } + retval->addMessage(ref); deleteInstance(lastCommand); - lastCommand = newInstance(NetCommandRef)(msg); - - msg->detach(); // Need to detach from new NetCommandMsg created by the "readXMessage" above. - - // since the message is part of the list now, we don't have to keep track of it. So we'll just set it to null. - msg = nullptr; - break; + lastCommand = NEW_NETCOMMANDREF(msg); + msg->detach(); } + else + { + i += NetPacketRepeatCommand::getSize(); - case 'Z': { - - ++i; // Repeat the last command, doing some funky cool byte-saving stuff if (lastCommand == nullptr) { DEBUG_CRASH(("Got a repeat command with no command to repeat.")); @@ -732,703 +466,69 @@ NetCommandList * NetPacket::getCommandList() { NetCommandMsg *msg = nullptr; - switch(commandType) { - + switch (commandBase.commandType.commandType) + { case NETCOMMANDTYPE_ACKSTAGE1: { msg = newInstance(NetAckStage1CommandMsg)(); - NetAckStage1CommandMsg* laststageone = (NetAckStage1CommandMsg*)(lastCommand->getCommand()); + NetAckStage1CommandMsg* laststageone = static_cast(lastCommand->getCommand()); ((NetAckStage1CommandMsg*)msg)->setCommandID(laststageone->getCommandID() + 1); ((NetAckStage1CommandMsg*)msg)->setOriginalPlayerID(laststageone->getOriginalPlayerID()); break; } case NETCOMMANDTYPE_ACKSTAGE2: { msg = newInstance(NetAckStage2CommandMsg)(); - NetAckStage2CommandMsg* laststagetwo = (NetAckStage2CommandMsg*)(lastCommand->getCommand()); + NetAckStage2CommandMsg* laststagetwo = static_cast(lastCommand->getCommand()); ((NetAckStage2CommandMsg*)msg)->setCommandID(laststagetwo->getCommandID() + 1); ((NetAckStage2CommandMsg*)msg)->setOriginalPlayerID(laststagetwo->getOriginalPlayerID()); break; } case NETCOMMANDTYPE_ACKBOTH: { msg = newInstance(NetAckBothCommandMsg)(); - NetAckBothCommandMsg* lastboth = (NetAckBothCommandMsg*)(lastCommand->getCommand()); + NetAckBothCommandMsg* lastboth = static_cast(lastCommand->getCommand()); ((NetAckBothCommandMsg*)msg)->setCommandID(lastboth->getCommandID() + 1); ((NetAckBothCommandMsg*)msg)->setOriginalPlayerID(lastboth->getOriginalPlayerID()); break; } case NETCOMMANDTYPE_FRAMEINFO: { msg = newInstance(NetFrameCommandMsg)(); - ++frame; // this is set below. + ++commandBase.frame.frame; // this is set below. ((NetFrameCommandMsg*)msg)->setCommandCount(0); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Read a repeated frame command, frame = %d, player = %d, commandID = %d", frame, playerID, commandID)); + DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Read a repeated frame command, frame = %d, playerId = %d, commandId = %d", + commandBase.frame.frame, commandBase.playerId.playerId, commandBase.commandId.commandId)); break; } default: DEBUG_CRASH(("Trying to repeat a command that shouldn't be repeated.")); continue; - } - msg->setExecutionFrame(frame); - msg->setPlayerID(playerID); - msg->setNetCommandType((NetCommandType)commandType); - msg->setID(commandID); - -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("frame = %d, player = %d, command type = %d, id = %d", frame, playerID, commandType, commandID)); + msg->setExecutionFrame(commandBase.frame.frame); + msg->setPlayerID(commandBase.playerId.playerId); + msg->setNetCommandType((NetCommandType)commandBase.commandType.commandType); + msg->setID(commandBase.commandId.commandId); // increment to the next command ID. - if (DoesCommandRequireACommandID((NetCommandType)commandType)) { - ++commandID; + if (DoesCommandRequireACommandID((NetCommandType)commandBase.commandType.commandType)) { + ++commandBase.commandId.commandId; } // add the message to the list. NetCommandRef *ref = retval->addMessage(msg); if (ref != nullptr) { - ref->setRelay(relay); + ref->setRelay(commandBase.relay.relay); } deleteInstance(lastCommand); -// lastCommand = newInstance(NetCommandRef)(msg); lastCommand = NEW_NETCOMMANDREF(msg); - - msg->detach(); // Need to detach from new NetCommandMsg created by the "readXMessage" above. - - // since the message is part of the list now, we don't have to keep track of it. So we'll just set it to null. - msg = nullptr; - break; - } - - default: - // we don't recognize this command, but we have to increment i so we don't fall into an infinite loop. - DEBUG_CRASH(("Unrecognized packet entry, ignoring.")); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList - Unrecognized packet entry at index %d", i)); - dumpPacketToLog(); - ++i; - break; - + msg->detach(); } - } deleteInstance(lastCommand); - lastCommand = nullptr; return retval; } -/** - * Reads the data portion of a game message from the given position in the packet. - */ -NetCommandMsg * NetPacket::readGameMessage(UnsignedByte *data, Int &i) -{ - NetGameCommandMsg *msg = newInstance(NetGameCommandMsg); - -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readGameMessage")); - - // Get the GameMessage command type. - GameMessage::Type newType; - memcpy(&newType, data + i, sizeof(GameMessage::Type)); - i += sizeof(GameMessage::Type); - msg->setGameMessageType(newType); - - // Get the number of argument types - UnsignedByte numArgTypes = 0; - memcpy(&numArgTypes, data + i, sizeof(numArgTypes)); - i += sizeof(numArgTypes); - - // Get the types and the number of arguments of those types. - Int totalArgCount = 0; - GameMessageParser *parser = newInstance(GameMessageParser)(); - Int j = 0; - for (; j < numArgTypes; ++j) { - UnsignedByte type = (UnsignedByte)ARGUMENTDATATYPE_UNKNOWN; - memcpy(&type, data + i, sizeof(type)); - i += sizeof(type); - - UnsignedByte argCount = 0; - memcpy(&argCount, data + i, sizeof(argCount)); - i += sizeof(argCount); - - parser->addArgType((GameMessageArgumentDataType)type, argCount); - totalArgCount += argCount; - } - - GameMessageParserArgumentType *parserArgType = parser->getFirstArgumentType(); - GameMessageArgumentDataType lasttype = ARGUMENTDATATYPE_UNKNOWN; - Int argsLeftForType = 0; - if (parserArgType != nullptr) { - lasttype = parserArgType->getType(); - argsLeftForType = parserArgType->getArgCount(); - } - for (j = 0; j < totalArgCount; ++j) { - readGameMessageArgumentFromPacket(lasttype, msg, data, i); - - --argsLeftForType; - if (argsLeftForType == 0) { - DEBUG_ASSERTCRASH(parserArgType != nullptr, ("parserArgType was null when it shouldn't have been.")); - if (parserArgType == nullptr) { - return nullptr; - } - - parserArgType = parserArgType->getNext(); - // parserArgType is allowed to be null here - if (parserArgType != nullptr) { - argsLeftForType = parserArgType->getArgCount(); - lasttype = parserArgType->getType(); - } - } - } - - deleteInstance(parser); - parser = nullptr; - - return (NetCommandMsg *)msg; -} - -void NetPacket::readGameMessageArgumentFromPacket(GameMessageArgumentDataType type, NetGameCommandMsg *msg, UnsignedByte *data, Int &i) { - - GameMessageArgumentType arg; - - switch (type) { - - case ARGUMENTDATATYPE_INTEGER: - Int theint; - memcpy(&theint, data + i, sizeof(theint)); - i += sizeof(theint); - arg.integer = theint; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_REAL: - Real thereal; - memcpy(&thereal, data + i, sizeof(thereal)); - i += sizeof(thereal); - arg.real = thereal; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_BOOLEAN: - Bool thebool; - memcpy(&thebool, data + i, sizeof(thebool)); - i += sizeof(thebool); - arg.boolean = thebool; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_OBJECTID: - ObjectID theobjectid; - memcpy(&theobjectid, data + i, sizeof(theobjectid)); - i += sizeof(theobjectid); - arg.objectID = theobjectid; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_DRAWABLEID: - DrawableID thedrawableid; - memcpy(&thedrawableid, data + i, sizeof(thedrawableid)); - i += sizeof(thedrawableid); - arg.drawableID = thedrawableid; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_TEAMID: - UnsignedInt theunsignedint; - memcpy(&theunsignedint, data + i, sizeof(theunsignedint)); - i += sizeof(theunsignedint); - arg.teamID = theunsignedint; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_LOCATION: - Coord3D coord; - memcpy(&coord, data + i, sizeof(coord)); - i += sizeof(coord); - arg.location = coord; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_PIXEL: - ICoord2D pixel; - memcpy(&pixel, data + i, sizeof(pixel)); - i += sizeof(pixel); - arg.pixel = pixel; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_PIXELREGION: - IRegion2D reg; - memcpy(®, data + i, sizeof(reg)); - i += sizeof(reg); - arg.pixelRegion = reg; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_TIMESTAMP: - UnsignedInt stamp; - memcpy(&stamp, data + i, sizeof(stamp)); - i += sizeof(stamp); - arg.timestamp = stamp; - msg->addArgument(type, arg); - break; - - case ARGUMENTDATATYPE_WIDECHAR: - WideChar c; - memcpy(&c, data + i, sizeof(c)); - i += sizeof(c); - arg.wChar = c; - msg->addArgument(type, arg); - break; - - } - -} - -/** - * Reads the data portion of the ack message at this position in the packet. - */ -NetCommandMsg * NetPacket::readAckBothMessage(UnsignedByte *data, Int &i) { - NetAckBothCommandMsg *msg = newInstance(NetAckBothCommandMsg); - - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readAckMessage, ")); - UnsignedShort cmdID = 0; - - memcpy(&cmdID, data + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - msg->setCommandID(cmdID); - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("commandID = %d, ", cmdID)); - - UnsignedByte origPlayerID = 0; - memcpy(&origPlayerID, data + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - msg->setOriginalPlayerID(origPlayerID); - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("original player id = %d", origPlayerID)); - - return msg; -} - -/** - * Reads the data portion of the ack message at this position in the packet. - */ -NetCommandMsg * NetPacket::readAckStage1Message(UnsignedByte *data, Int &i) { - NetAckStage1CommandMsg *msg = newInstance(NetAckStage1CommandMsg); - -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readAckMessage, ")); - UnsignedShort cmdID = 0; - - memcpy(&cmdID, data + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - msg->setCommandID(cmdID); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("commandID = %d, ", cmdID)); - - UnsignedByte origPlayerID = 0; - memcpy(&origPlayerID, data + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - msg->setOriginalPlayerID(origPlayerID); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("original player id = %d", origPlayerID)); - - return msg; -} - -/** - * Reads the data portion of the ack message at this position in the packet. - */ -NetCommandMsg * NetPacket::readAckStage2Message(UnsignedByte *data, Int &i) { - NetAckStage2CommandMsg *msg = newInstance(NetAckStage2CommandMsg); - -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readAckMessage, ")); - UnsignedShort cmdID = 0; - - memcpy(&cmdID, data + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - msg->setCommandID(cmdID); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("commandID = %d, ", cmdID)); - - UnsignedByte origPlayerID = 0; - memcpy(&origPlayerID, data + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - msg->setOriginalPlayerID(origPlayerID); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("original player id = %d", origPlayerID)); - - return msg; -} - -/** - * Reads the data portion of the frame message at this position in the packet. - */ -NetCommandMsg * NetPacket::readFrameMessage(UnsignedByte *data, Int &i) { - NetFrameCommandMsg *msg = newInstance(NetFrameCommandMsg); - -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readFrameMessage, ")); - UnsignedShort cmdCount = 0; - - memcpy(&cmdCount, data + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - msg->setCommandCount(cmdCount); -// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command count = %d, ", cmdCount)); - - return msg; -} - -/** - * Reads the player leave message at this position in the packet. - */ -NetCommandMsg * NetPacket::readPlayerLeaveMessage(UnsignedByte *data, Int &i) { - NetPlayerLeaveCommandMsg *msg = newInstance(NetPlayerLeaveCommandMsg); - - UnsignedByte leavingPlayerID = 0; - - memcpy(&leavingPlayerID, data + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - msg->setLeavingPlayerID(leavingPlayerID); - - return msg; -} - -/** - * Reads the run ahead metrics message at this position in the packet. - */ -NetCommandMsg * NetPacket::readRunAheadMetricsMessage(UnsignedByte *data, Int &i) { - NetRunAheadMetricsCommandMsg *msg = newInstance(NetRunAheadMetricsCommandMsg); - - Real averageLatency = (Real)0.2; - UnsignedShort averageFps = 30; - - memcpy(&averageLatency, data + i, sizeof(Real)); - i += sizeof(Real); - msg->setAverageLatency(averageLatency); - - memcpy(&averageFps, data + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - msg->setAverageFps((Int)averageFps); - return msg; -} - -/** - * Reads the run ahead message at this position in the packet. - */ -NetCommandMsg * NetPacket::readRunAheadMessage(UnsignedByte *data, Int &i) { - NetRunAheadCommandMsg *msg = newInstance(NetRunAheadCommandMsg); - - UnsignedShort newRunAhead = 20; - memcpy(&newRunAhead, data + i, sizeof(UnsignedShort)); - i += sizeof(UnsignedShort); - msg->setRunAhead(newRunAhead); - - UnsignedByte newFrameRate = 30; - memcpy(&newFrameRate, data + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - msg->setFrameRate(newFrameRate); - - return msg; -} - -/** - * Reads the CRC info message at this position in the packet. - */ -NetCommandMsg * NetPacket::readDestroyPlayerMessage(UnsignedByte *data, Int &i) { - NetDestroyPlayerCommandMsg *msg = newInstance(NetDestroyPlayerCommandMsg); - - UnsignedInt newVal = 0; - memcpy(&newVal, data + i, sizeof(UnsignedInt)); - i += sizeof(UnsignedInt); - msg->setPlayerIndex(newVal); - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Saw CRC of 0x%8.8X", newCRC)); - - return msg; -} - -/** - * Reads the keep alive data, of which there is none. - */ -NetCommandMsg * NetPacket::readKeepAliveMessage(UnsignedByte *data, Int &i) { - NetKeepAliveCommandMsg *msg = newInstance(NetKeepAliveCommandMsg); - - return msg; -} - -/** - * Reads the disconnect keep alive data, of which there is none. - */ -NetCommandMsg * NetPacket::readDisconnectKeepAliveMessage(UnsignedByte *data, Int &i) { - NetDisconnectKeepAliveCommandMsg *msg = newInstance(NetDisconnectKeepAliveCommandMsg); - - return msg; -} - -/** - * Reads the disconnect player data. Which is the slot number of the player being disconnected. - */ -NetCommandMsg * NetPacket::readDisconnectPlayerMessage(UnsignedByte *data, Int &i) { - NetDisconnectPlayerCommandMsg *msg = newInstance(NetDisconnectPlayerCommandMsg); - - UnsignedByte slot = 0; - memcpy(&slot, data + i, sizeof(slot)); - i += sizeof(slot); - msg->setDisconnectSlot(slot); - - UnsignedInt disconnectFrame = 0; - memcpy(&disconnectFrame, data + i, sizeof(disconnectFrame)); - i += sizeof(disconnectFrame); - msg->setDisconnectFrame(disconnectFrame); - - return msg; -} - -/** - * Reads the packet router query data, of which there is none. - */ -NetCommandMsg * NetPacket::readPacketRouterQueryMessage(UnsignedByte *data, Int &i) { - NetPacketRouterQueryCommandMsg *msg = newInstance(NetPacketRouterQueryCommandMsg); - - return msg; -} - -/** - * Reads the packet router ack data, of which there is none. - */ -NetCommandMsg * NetPacket::readPacketRouterAckMessage(UnsignedByte *data, Int &i) { - NetPacketRouterAckCommandMsg *msg = newInstance(NetPacketRouterAckCommandMsg); - - return msg; -} - -/** - * Reads the disconnect chat data, which is just the string. - */ -NetCommandMsg * NetPacket::readDisconnectChatMessage(UnsignedByte *data, Int &i) { - NetDisconnectChatCommandMsg *msg = newInstance(NetDisconnectChatCommandMsg); - - WideChar text[256]; - UnsignedByte length; - memcpy(&length, data + i, sizeof(UnsignedByte)); - ++i; - memcpy(text, data + i, length * sizeof(WideChar)); - i += length * sizeof(WideChar); - text[length] = 0; - - UnicodeString unitext; - unitext.set(text); - - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readDisconnectChatMessage - read message, message is %ls", unitext.str())); - - msg->setText(unitext); - return msg; -} - -/** - * Reads the chat data, which is just the string. - */ -NetCommandMsg * NetPacket::readChatMessage(UnsignedByte *data, Int &i) { - NetChatCommandMsg *msg = newInstance(NetChatCommandMsg); - - WideChar text[256]; - UnsignedByte length; - Int playerMask; - memcpy(&length, data + i, sizeof(UnsignedByte)); - ++i; - memcpy(text, data + i, length * sizeof(WideChar)); - i += length * sizeof(WideChar); - text[length] = 0; - memcpy(&playerMask, data + i, sizeof(Int)); - i += sizeof(Int); - - - UnicodeString unitext; - unitext.set(text); - - //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readChatMessage - read message, message is %ls", unitext.str())); - - msg->setText(unitext); - msg->setPlayerMask(playerMask); - return msg; -} - -/** - * Reads the disconnect vote data. Which is the slot number of the player being disconnected. - */ -NetCommandMsg * NetPacket::readDisconnectVoteMessage(UnsignedByte *data, Int &i) { - NetDisconnectVoteCommandMsg *msg = newInstance(NetDisconnectVoteCommandMsg); - - UnsignedByte slot = 0; - memcpy(&slot, data + i, sizeof(slot)); - i += sizeof(slot); - msg->setSlot(slot); - - UnsignedInt voteFrame = 0; - memcpy(&voteFrame, data + i, sizeof(voteFrame)); - i += sizeof(voteFrame); - msg->setVoteFrame(voteFrame); - - return msg; -} - -/** - * Reads the Progress data. Which is the slot number of the player being disconnected. - */ -NetCommandMsg * NetPacket::readProgressMessage(UnsignedByte *data, Int &i) { - NetProgressCommandMsg *msg = newInstance(NetProgressCommandMsg); - - UnsignedByte percentage = 0; - memcpy(&percentage, data + i, sizeof(UnsignedByte)); - i += sizeof(UnsignedByte); - msg->setPercentage(percentage); - - return msg; -} - -NetCommandMsg * NetPacket::readLoadCompleteMessage(UnsignedByte *data, Int &i) { - NetLoadCompleteCommandMsg *msg = newInstance(NetLoadCompleteCommandMsg); - return msg; -} - -NetCommandMsg * NetPacket::readTimeOutGameStartMessage(UnsignedByte *data, Int &i) { - NetTimeOutGameStartCommandMsg *msg = newInstance(NetTimeOutGameStartCommandMsg); - return msg; -} - -NetCommandMsg * NetPacket::readWrapperMessage(UnsignedByte *data, Int &i) { - NetWrapperCommandMsg *msg = newInstance(NetWrapperCommandMsg); - - // get the wrapped command ID - UnsignedShort wrappedCommandID = 0; - memcpy(&wrappedCommandID, data + i, sizeof(wrappedCommandID)); - msg->setWrappedCommandID(wrappedCommandID); - i += sizeof(wrappedCommandID); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - wrapped command ID == %d", wrappedCommandID)); - - // get the chunk number. - UnsignedInt chunkNumber = 0; - memcpy(&chunkNumber, data + i, sizeof(chunkNumber)); - msg->setChunkNumber(chunkNumber); - i += sizeof(chunkNumber); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - chunk number = %d", chunkNumber)); - - // get the number of chunks - UnsignedInt numChunks = 0; - memcpy(&numChunks, data + i, sizeof(numChunks)); - msg->setNumChunks(numChunks); - i += sizeof(numChunks); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - number of chunks = %d", numChunks)); - - // get the total data length - UnsignedInt totalDataLength = 0; - memcpy(&totalDataLength, data + i, sizeof(totalDataLength)); - msg->setTotalDataLength(totalDataLength); - i += sizeof(totalDataLength); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - total data length = %d", totalDataLength)); - - // get the data length for this chunk - UnsignedInt dataLength = 0; - memcpy(&dataLength, data + i, sizeof(dataLength)); - i += sizeof(dataLength); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - data length = %d", dataLength)); - - UnsignedInt dataOffset = 0; - memcpy(&dataOffset, data + i, sizeof(dataOffset)); - msg->setDataOffset(dataOffset); - i += sizeof(dataOffset); - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - data offset = %d", dataOffset)); - - msg->setData(data + i, dataLength); - i += dataLength; - - return msg; -} - -NetCommandMsg * NetPacket::readFileMessage(UnsignedByte *data, Int &i) { - NetFileCommandMsg *msg = newInstance(NetFileCommandMsg); - char filename[_MAX_PATH]; - - // TheSuperHackers @security Mauller/Jbremer/SkyAero 11/12/2025 Prevent buffer overflow when copying filepath string - i += strlcpy(filename, reinterpret_cast(data + i), ARRAY_SIZE(filename)); - ++i; //Increment for null terminator - msg->setPortableFilename(AsciiString(filename)); // it's transferred as a portable filename - - UnsignedInt dataLength = 0; - memcpy(&dataLength, data + i, sizeof(dataLength)); - i += sizeof(dataLength); - - UnsignedByte *buf = NEW UnsignedByte[dataLength]; - memcpy(buf, data + i, dataLength); - i += dataLength; - - msg->setFileData(buf, dataLength); - - return msg; -} - -NetCommandMsg * NetPacket::readFileAnnounceMessage(UnsignedByte *data, Int &i) { - NetFileAnnounceCommandMsg *msg = newInstance(NetFileAnnounceCommandMsg); - char filename[_MAX_PATH]; - - // TheSuperHackers @security Mauller/Jbremer/SkyAero 11/12/2025 Prevent buffer overflow when copying filepath string - i += strlcpy(filename, reinterpret_cast(data + i), ARRAY_SIZE(filename)); - ++i; //Increment for null terminator - msg->setPortableFilename(AsciiString(filename)); // it's transferred as a portable filename - - UnsignedShort fileID = 0; - memcpy(&fileID, data + i, sizeof(fileID)); - i += sizeof(fileID); - msg->setFileID(fileID); - - UnsignedByte playerMask = 0; - memcpy(&playerMask, data + i, sizeof(playerMask)); - i += sizeof(playerMask); - msg->setPlayerMask(playerMask); - - return msg; -} - -NetCommandMsg * NetPacket::readFileProgressMessage(UnsignedByte *data, Int &i) { - NetFileProgressCommandMsg *msg = newInstance(NetFileProgressCommandMsg); - - UnsignedShort fileID = 0; - memcpy(&fileID, data + i, sizeof(fileID)); - i += sizeof(fileID); - msg->setFileID(fileID); - - Int progress = 0; - memcpy(&progress, data + i, sizeof(progress)); - i += sizeof(progress); - msg->setProgress(progress); - - return msg; -} - -NetCommandMsg * NetPacket::readDisconnectFrameMessage(UnsignedByte *data, Int &i) { - NetDisconnectFrameCommandMsg *msg = newInstance(NetDisconnectFrameCommandMsg); - - UnsignedInt disconnectFrame = 0; - memcpy(&disconnectFrame, data + i, sizeof(disconnectFrame)); - i += sizeof(disconnectFrame); - msg->setDisconnectFrame(disconnectFrame); - - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readDisconnectFrameMessage - read disconnect frame for frame %d", disconnectFrame)); - - return msg; -} - -NetCommandMsg * NetPacket::readDisconnectScreenOffMessage(UnsignedByte *data, Int &i) { - NetDisconnectScreenOffCommandMsg *msg = newInstance(NetDisconnectScreenOffCommandMsg); - - UnsignedInt newFrame = 0; - memcpy(&newFrame, data + i, sizeof(newFrame)); - i += sizeof(newFrame); - msg->setNewFrame(newFrame); - - return msg; -} - -NetCommandMsg * NetPacket::readFrameResendRequestMessage(UnsignedByte *data, Int &i) { - NetFrameResendRequestCommandMsg *msg = newInstance(NetFrameResendRequestCommandMsg); - - UnsignedInt frameToResend = 0; - memcpy(&frameToResend, data + i, sizeof(frameToResend)); - i += sizeof(frameToResend); - msg->setFrameToResend(frameToResend); - - return msg; -} - /** * Returns the number of commands in this packet. Only valid if the packet is locally constructed. */ @@ -1467,16 +567,16 @@ Int NetPacket::getLength() { /** * Dumps the packet to the debug log file */ -void NetPacket::dumpPacketToLog() { - DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::dumpPacketToLog() - packet is %d bytes", m_packetLen)); - Int numLines = m_packetLen / 8; - if ((m_packetLen % 8) != 0) { +void NetPacket::dumpPacketToLog(const UnsignedByte *packet, Int packetLen) { + DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::dumpPacketToLog() - packet is %d bytes", packetLen)); + Int numLines = packetLen / 8; + if ((packetLen % 8) != 0) { ++numLines; } for (Int dumpindex = 0; dumpindex < numLines; ++dumpindex) { DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("\t%d\t", dumpindex*8)); - for (Int dumpindex2 = 0; (dumpindex2 < 8) && ((dumpindex*8 + dumpindex2) < m_packetLen); ++dumpindex2) { - DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("%02x '%c' ", m_packet[dumpindex*8 + dumpindex2], m_packet[dumpindex*8 + dumpindex2])); + for (Int dumpindex2 = 0; (dumpindex2 < 8) && ((dumpindex*8 + dumpindex2) < packetLen); ++dumpindex2) { + DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("%02x '%c' ", packet[dumpindex*8 + dumpindex2], packet[dumpindex*8 + dumpindex2])); } DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("\n")); } diff --git a/Core/GameEngine/Source/GameNetwork/NetPacketStructs.cpp b/Core/GameEngine/Source/GameNetwork/NetPacketStructs.cpp index 5f42e3388c3..500fcdbee88 100644 --- a/Core/GameEngine/Source/GameNetwork/NetPacketStructs.cpp +++ b/Core/GameEngine/Source/GameNetwork/NetPacketStructs.cpp @@ -108,6 +108,155 @@ size_t SmallNetPacketCommandBase::copyBytes(UnsignedByte *buffer, const NetComma return size; } +size_t SmallNetPacketCommandBase::readMessage(NetCommandRef *&ref, CommandBase &base, NetPacketBuf buf) +{ + size_t size = 0; + + while (size < buf.size()) + { + switch (buf[size]) + { + case NetPacketFieldTypes::CommandType: + size += network::readObject(base.commandType, buf.offset(size)); + break; + case NetPacketFieldTypes::Relay: + size += network::readObject(base.relay, buf.offset(size)); + break; + case NetPacketFieldTypes::Frame: + size += network::readObject(base.frame, buf.offset(size)); + break; + case NetPacketFieldTypes::PlayerId: + size += network::readObject(base.playerId, buf.offset(size)); + break; + case NetPacketFieldTypes::CommandId: + size += network::readObject(base.commandId, buf.offset(size)); + break; + case NetPacketFieldTypes::Data: + { + size += network::readObject(base.dataHeader, buf.offset(size)); + // The data field marks the end of the command base. + if (NetCommandMsg* msg = constructNetCommandMsg(base)) + { + ref = NEW_NETCOMMANDREF(msg); + ref->setRelay(base.relay.relay); + msg->detach(); + } + return size; + } + case NetPacketFieldTypes::Repeat: + default: + DEBUG_CRASH(("SmallNetPacketCommandBase::readBytes: Unexpected field type '%c' encountered.", buf[size])); + return size + 1; + } + } + + return size; +} + +NetCommandMsg *SmallNetPacketCommandBase::constructNetCommandMsg(const CommandBase &base) +{ + NetCommandMsg *msg = nullptr; + NetCommandType commandType = static_cast(base.commandType.commandType); + + switch (commandType) + { + case NETCOMMANDTYPE_GAMECOMMAND: + msg = newInstance(NetGameCommandMsg); + break; + case NETCOMMANDTYPE_ACKBOTH: + msg = newInstance(NetAckBothCommandMsg); + break; + case NETCOMMANDTYPE_ACKSTAGE1: + msg = newInstance(NetAckStage1CommandMsg); + break; + case NETCOMMANDTYPE_ACKSTAGE2: + msg = newInstance(NetAckStage2CommandMsg); + break; + case NETCOMMANDTYPE_FRAMEINFO: + msg = newInstance(NetFrameCommandMsg); + break; + case NETCOMMANDTYPE_PLAYERLEAVE: + msg = newInstance(NetPlayerLeaveCommandMsg); + break; + case NETCOMMANDTYPE_RUNAHEADMETRICS: + msg = newInstance(NetRunAheadMetricsCommandMsg); + break; + case NETCOMMANDTYPE_RUNAHEAD: + msg = newInstance(NetRunAheadCommandMsg); + break; + case NETCOMMANDTYPE_DESTROYPLAYER: + msg = newInstance(NetDestroyPlayerCommandMsg); + break; + case NETCOMMANDTYPE_KEEPALIVE: + msg = newInstance(NetKeepAliveCommandMsg); + break; + case NETCOMMANDTYPE_DISCONNECTKEEPALIVE: + msg = newInstance(NetDisconnectKeepAliveCommandMsg); + break; + case NETCOMMANDTYPE_DISCONNECTPLAYER: + msg = newInstance(NetDisconnectPlayerCommandMsg); + break; + case NETCOMMANDTYPE_PACKETROUTERQUERY: + msg = newInstance(NetPacketRouterQueryCommandMsg); + break; + case NETCOMMANDTYPE_PACKETROUTERACK: + msg = newInstance(NetPacketRouterAckCommandMsg); + break; + case NETCOMMANDTYPE_DISCONNECTCHAT: + msg = newInstance(NetDisconnectChatCommandMsg); + break; + case NETCOMMANDTYPE_DISCONNECTVOTE: + msg = newInstance(NetDisconnectVoteCommandMsg); + break; + case NETCOMMANDTYPE_CHAT: + msg = newInstance(NetChatCommandMsg); + break; + case NETCOMMANDTYPE_PROGRESS: + msg = newInstance(NetProgressCommandMsg); + break; + case NETCOMMANDTYPE_LOADCOMPLETE: + msg = newInstance(NetLoadCompleteCommandMsg); + break; + case NETCOMMANDTYPE_TIMEOUTSTART: + msg = newInstance(NetTimeOutGameStartCommandMsg); + break; + case NETCOMMANDTYPE_WRAPPER: + msg = newInstance(NetWrapperCommandMsg); + break; + case NETCOMMANDTYPE_FILE: + msg = newInstance(NetFileCommandMsg); + break; + case NETCOMMANDTYPE_FILEANNOUNCE: + msg = newInstance(NetFileAnnounceCommandMsg); + break; + case NETCOMMANDTYPE_FILEPROGRESS: + msg = newInstance(NetFileProgressCommandMsg); + break; + case NETCOMMANDTYPE_DISCONNECTFRAME: + msg = newInstance(NetDisconnectFrameCommandMsg); + break; + case NETCOMMANDTYPE_DISCONNECTSCREENOFF: + msg = newInstance(NetDisconnectScreenOffCommandMsg); + break; + case NETCOMMANDTYPE_FRAMERESENDREQUEST: + msg = newInstance(NetFrameResendRequestCommandMsg); + break; + default: + DEBUG_CRASH(("SmallNetPacketCommandBase::constructNetCommandMsg: Unexpected command type '%d' encountered.", commandType)); + return nullptr; + } + + DEBUG_ASSERTCRASH(commandType == msg->getNetCommandType(), + ("SmallNetPacketCommandBase::constructNetCommandMsg: Read command type '%d' does not match created command '%d'.", commandType, msg->getNetCommandType())); + + msg->setNetCommandType(static_cast(base.commandType.commandType)); + msg->setExecutionFrame(base.frame.frame); + msg->setPlayerID(base.playerId.playerId); + msg->setID(base.commandId.commandId); + + return msg; +} + //////////////////////////////////////////////////////////////////////////////// // NetPacketAckCommand //////////////////////////////////////////////////////////////////////////////// @@ -122,6 +271,20 @@ size_t NetPacketAckCommandData::copyBytes(UnsignedByte *buffer, const NetCommand return network::writeObject(buffer, data); } +size_t NetPacketAckCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.commandId = 0; + data.originalPlayerId = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setCommandID(data.commandId); + cmdMsg->setOriginalPlayerID(data.originalPlayerId); + + return size; +} + size_t NetPacketAckCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -148,6 +311,18 @@ size_t NetPacketFrameCommandData::copyBytes(UnsignedByte *buffer, const NetComma return network::writeObject(buffer, data); } +size_t NetPacketFrameCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.commandCount = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setCommandCount(data.commandCount); + + return size; +} + size_t NetPacketFrameCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -174,6 +349,18 @@ size_t NetPacketPlayerLeaveCommandData::copyBytes(UnsignedByte *buffer, const Ne return network::writeObject(buffer, data); } +size_t NetPacketPlayerLeaveCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.leavingPlayerId = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setLeavingPlayerID(data.leavingPlayerId); + + return size; +} + size_t NetPacketPlayerLeaveCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -201,6 +388,20 @@ size_t NetPacketRunAheadMetricsCommandData::copyBytes(UnsignedByte *buffer, cons return network::writeObject(buffer, data); } +size_t NetPacketRunAheadMetricsCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.averageLatency = 0.2f; + data.averageFps = 30; + + size_t size = network::readObject(data, buf); + cmdMsg->setAverageLatency(data.averageLatency); + cmdMsg->setAverageFps(data.averageFps); + + return size; +} + size_t NetPacketRunAheadMetricsCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -228,6 +429,20 @@ size_t NetPacketRunAheadCommandData::copyBytes(UnsignedByte *buffer, const NetCo return network::writeObject(buffer, data); } +size_t NetPacketRunAheadCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.runAhead = 20; + data.frameRate = 30; + + size_t size = network::readObject(data, buf); + cmdMsg->setRunAhead(data.runAhead); + cmdMsg->setFrameRate(data.frameRate); + + return size; +} + size_t NetPacketRunAheadCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -254,6 +469,18 @@ size_t NetPacketDestroyPlayerCommandData::copyBytes(UnsignedByte *buffer, const return network::writeObject(buffer, data); } +size_t NetPacketDestroyPlayerCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.playerIndex = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setPlayerIndex(data.playerIndex); + + return size; +} + size_t NetPacketDestroyPlayerCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -315,6 +542,20 @@ size_t NetPacketDisconnectPlayerCommandData::copyBytes(UnsignedByte *buffer, con return network::writeObject(buffer, data); } +size_t NetPacketDisconnectPlayerCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.disconnectSlot = 0; + data.disconnectFrame = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setDisconnectSlot(data.disconnectSlot); + cmdMsg->setDisconnectFrame(data.disconnectFrame); + + return size; +} + size_t NetPacketDisconnectPlayerCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -376,6 +617,20 @@ size_t NetPacketDisconnectVoteCommandData::copyBytes(UnsignedByte *buffer, const return network::writeObject(buffer, data); } +size_t NetPacketDisconnectVoteCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.slot = 0; + data.voteFrame = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setSlot(data.slot); + cmdMsg->setVoteFrame(data.voteFrame); + + return size; +} + size_t NetPacketDisconnectVoteCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -408,7 +663,7 @@ size_t NetPacketChatCommandData::getSize(const NetCommandMsg &msg) size_t NetPacketChatCommandData::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const CommandMsg *cmdMsg = static_cast(ref.getCommand()); - const Int textLength = std::min(cmdMsg->getText().getLength(), 255); + const size_t textLength = std::min(cmdMsg->getText().getLength(), 255); size_t size = 0; size += network::writePrimitive(buffer + size, (UnsignedByte)textLength); @@ -417,6 +672,24 @@ size_t NetPacketChatCommandData::copyBytes(UnsignedByte *buffer, const NetComman return size; } +size_t NetPacketChatCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + UnsignedByte textLength = 0; + UnicodeString unitext; + Int playerMask = 0; + + size_t size = 0; + size += network::readObject(textLength, buf.offset(size)); + size += network::readStringWithoutNull(unitext, textLength, buf.offset(size)); + size += network::readObject(playerMask, buf.offset(size)); + + cmdMsg->setText(unitext); + cmdMsg->setPlayerMask(playerMask); + + return size; +} + size_t NetPacketChatCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -456,6 +729,21 @@ size_t NetPacketDisconnectChatCommandData::copyBytes(UnsignedByte *buffer, const return size; } +size_t NetPacketDisconnectChatCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + UnsignedByte textLength = 0; + UnicodeString unitext; + + size_t size = 0; + size += network::readObject(textLength, buf.offset(size)); + size += network::readStringWithoutNull(unitext, textLength, buf.offset(size)); + + cmdMsg->setText(unitext); + + return size; +} + size_t NetPacketDisconnectChatCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -604,6 +892,116 @@ size_t NetPacketGameCommandData::copyBytes(UnsignedByte *buffer, const NetComman return size; } +size_t NetPacketGameCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + GameMessageParser *parser = newInstance(GameMessageParser)(); + Int newType = 0; + UnsignedByte numArgTypes = 0; + + size_t size = 0; + size += network::readObject(newType, buf.offset(size)); + size += network::readObject(numArgTypes, buf.offset(size)); + + cmdMsg->setGameMessageType(static_cast(newType)); + + Int totalArgCount = 0; + Int argIndex = 0; + + for (; argIndex < (Int)numArgTypes; ++argIndex) + { + UnsignedByte type = (UnsignedByte)ARGUMENTDATATYPE_UNKNOWN; + UnsignedByte argCount = 0; + + size += network::readObject(type, buf.offset(size)); + size += network::readObject(argCount, buf.offset(size)); + + parser->addArgType(static_cast(type), argCount); + totalArgCount += argCount; + } + + GameMessageParserArgumentType *parserArgType = parser->getFirstArgumentType(); + GameMessageArgumentDataType lastType = ARGUMENTDATATYPE_UNKNOWN; + Int argsLeftForType = 0; + + if (parserArgType != nullptr) + { + lastType = parserArgType->getType(); + argsLeftForType = parserArgType->getArgCount(); + } + + for (argIndex = 0; argIndex < totalArgCount; ++argIndex) + { + GameMessageArgumentType arg; + const size_t sizeBefore = size; + + switch (lastType) + { + case ARGUMENTDATATYPE_INTEGER: + size += network::readObject(arg.integer, buf.offset(size)); + break; + case ARGUMENTDATATYPE_REAL: + size += network::readObject(arg.real, buf.offset(size)); + break; + case ARGUMENTDATATYPE_BOOLEAN: + size += network::readObject(arg.boolean, buf.offset(size)); + break; + case ARGUMENTDATATYPE_OBJECTID: + size += network::readObject(arg.objectID, buf.offset(size)); + break; + case ARGUMENTDATATYPE_DRAWABLEID: + size += network::readObject(arg.drawableID, buf.offset(size)); + break; + case ARGUMENTDATATYPE_TEAMID: + size += network::readObject(arg.teamID, buf.offset(size)); + break; + case ARGUMENTDATATYPE_LOCATION: + size += network::readObject(arg.location, buf.offset(size)); + break; + case ARGUMENTDATATYPE_PIXEL: + size += network::readObject(arg.pixel, buf.offset(size)); + break; + case ARGUMENTDATATYPE_PIXELREGION: + size += network::readObject(arg.pixelRegion, buf.offset(size)); + break; + case ARGUMENTDATATYPE_TIMESTAMP: + size += network::readObject(arg.timestamp, buf.offset(size)); + break; + case ARGUMENTDATATYPE_WIDECHAR: + size += network::readObject(arg.wChar, buf.offset(size)); + break; + } + + if (size > sizeBefore) + { + cmdMsg->addArgument(lastType, arg); + } + + --argsLeftForType; + + if (argsLeftForType == 0) + { + if (parserArgType == nullptr) + { + DEBUG_CRASH(("parserArgType was null when it shouldn't have been.")); + break; + } + + parserArgType = parserArgType->getNext(); + // parserArgType is allowed to be null here + if (parserArgType != nullptr) + { + argsLeftForType = parserArgType->getArgCount(); + lastType = parserArgType->getType(); + } + } + } + + deleteInstance(parser); + + return size; +} + size_t NetPacketGameCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -648,6 +1046,33 @@ size_t NetPacketWrapperCommandData::copyBytes(UnsignedByte *buffer, const NetCom return size; } +size_t NetPacketWrapperCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.wrappedCommandId = 0; + data.chunkNumber = 0; + data.numChunks = 0; + data.totalDataLength = 0; + data.dataLength = 0; + data.dataOffset = 0; + + size_t size = 0; + size += network::readObject(data, buf.offset(size)); + + NetCommandDataChunk dataChunk(data.dataLength); + size += network::readBytes(dataChunk.data(), dataChunk.size(), buf.offset(size)); + + cmdMsg->setWrappedCommandID(data.wrappedCommandId); + cmdMsg->setChunkNumber(data.chunkNumber); + cmdMsg->setNumChunks(data.numChunks); + cmdMsg->setTotalDataLength(data.totalDataLength); + cmdMsg->setDataOffset(data.dataOffset); + cmdMsg->setData(dataChunk); + + return size; +} + size_t NetPacketWrapperCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -687,6 +1112,25 @@ size_t NetPacketFileCommandData::copyBytes(UnsignedByte *buffer, const NetComman return size; } +size_t NetPacketFileCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + AsciiString filename; + UnsignedInt dataLength = 0; + + size_t size = 0; + size += network::readStringWithNull(filename, _MAX_PATH, buf.offset(size)); + size += network::readObject(dataLength, buf.offset(size)); + + NetCommandDataChunk dataChunk(dataLength); + size += network::readBytes(dataChunk.data(), dataChunk.size(), buf.offset(size)); + + cmdMsg->setPortableFilename(filename); + cmdMsg->setFileData(dataChunk); + + return size; +} + size_t NetPacketFileCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -726,6 +1170,25 @@ size_t NetPacketFileAnnounceCommandData::copyBytes(UnsignedByte *buffer, const N return size; } +size_t NetPacketFileAnnounceCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + AsciiString filename; + UnsignedShort fileID = 0; + UnsignedByte playerMask = 0; + + size_t size = 0; + size += network::readStringWithNull(filename, _MAX_PATH, buf.offset(size)); + size += network::readObject(fileID, buf.offset(size)); + size += network::readObject(playerMask, buf.offset(size)); + + cmdMsg->setPortableFilename(filename); + cmdMsg->setFileID(fileID); + cmdMsg->setPlayerMask(playerMask); + + return size; +} + size_t NetPacketFileAnnounceCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -753,6 +1216,20 @@ size_t NetPacketFileProgressCommandData::copyBytes(UnsignedByte *buffer, const N return network::writeObject(buffer, data); } +size_t NetPacketFileProgressCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.fileId = 0; + data.progress = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setFileID(data.fileId); + cmdMsg->setProgress(data.progress); + + return size; +} + size_t NetPacketFileProgressCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -779,6 +1256,18 @@ size_t NetPacketProgressCommandData::copyBytes(UnsignedByte *buffer, const NetCo return network::writeObject(buffer, data); } +size_t NetPacketProgressCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.percentage = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setPercentage(data.percentage); + + return size; +} + size_t NetPacketProgressCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -839,6 +1328,18 @@ size_t NetPacketDisconnectFrameCommandData::copyBytes(UnsignedByte *buffer, cons return network::writeObject(buffer, data); } +size_t NetPacketDisconnectFrameCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.disconnectFrame = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setDisconnectFrame(data.disconnectFrame); + + return size; +} + size_t NetPacketDisconnectFrameCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -865,6 +1366,18 @@ size_t NetPacketDisconnectScreenOffCommandData::copyBytes(UnsignedByte *buffer, return network::writeObject(buffer, data); } +size_t NetPacketDisconnectScreenOffCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.newFrame = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setNewFrame(data.newFrame); + + return size; +} + size_t NetPacketDisconnectScreenOffCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand(); @@ -891,6 +1404,18 @@ size_t NetPacketFrameResendRequestCommandData::copyBytes(UnsignedByte *buffer, c return network::writeObject(buffer, data); } +size_t NetPacketFrameResendRequestCommandData::readMessage(NetCommandRef &ref, NetPacketBuf buf) +{ + CommandMsg *cmdMsg = static_cast(ref.getCommand()); + FixedData data; + data.frameToResend = 0; + + size_t size = network::readObject(data, buf); + cmdMsg->setFrameToResend(data.frameToResend); + + return size; +} + size_t NetPacketFrameResendRequestCommandBase::copyBytes(UnsignedByte *buffer, const NetCommandRef &ref) { const NetCommandMsg *msg = ref.getCommand();