diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 0582ef6487..ebcf4baafd 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -15,7 +15,7 @@ using namespace udt; int Packet::localHeaderSize(bool isPartOfMessage) { return sizeof(Packet::SequenceNumberAndBitField) + - (isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) : 0); + (isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePart) : 0); } int Packet::totalHeaderSize(bool isPartOfMessage) { @@ -109,9 +109,11 @@ Packet& Packet::operator=(Packet&& other) { return *this; } -void Packet::writeMessageNumber(MessageNumber messageNumber) { +void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePart messagePart) { _isPartOfMessage = true; _messageNumber = messageNumber; + _packetPosition = position; + _messagePart = messagePart; writeHeader(); } @@ -141,6 +143,9 @@ void Packet::readHeader() const { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; _messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK; _packetPosition = static_cast(*messageNumberAndBitField >> PACKET_POSITION_OFFSET); + + MessagePart* messagePart = messageNumberAndBitField + 1; + _messagePart = *messagePart; } } @@ -166,5 +171,8 @@ void Packet::writeHeader() const { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; *messageNumberAndBitField = _messageNumber; *messageNumberAndBitField |= _packetPosition << PACKET_POSITION_OFFSET; + + MessagePart* messagePart = messageNumberAndBitField + 1; + *messagePart = _messagePart; } } diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 6bf7c569aa..71fb22eb98 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -31,6 +31,7 @@ public: // NOTE: The MessageNumber is only actually 30 bits to leave room for a bit field using MessageNumber = uint32_t; using MessageNumberAndBitField = uint32_t; + using MessagePart = uint32_t; // Use same size as MessageNumberAndBitField so we can use the enum with bitwise operations enum PacketPosition : MessageNumberAndBitField { @@ -55,14 +56,13 @@ public: bool isPartOfMessage() const { return _isPartOfMessage; } bool isReliable() const { return _isReliable; } - SequenceNumber getSequenceNumber() const { return _sequenceNumber; } - - MessageNumber getMessageNumber() const { return _messageNumber; } - - void setPacketPosition(PacketPosition position) { _packetPosition = position; } - PacketPosition getPacketPosition() const { return _packetPosition; } - void writeMessageNumber(MessageNumber messageNumber); + SequenceNumber getSequenceNumber() const { return _sequenceNumber; } + MessageNumber getMessageNumber() const { return _messageNumber; } + PacketPosition getPacketPosition() const { return _packetPosition; } + MessagePart getMessagePart() const { return _messagePart; } + + void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePart messagePart); void writeSequenceNumber(SequenceNumber sequenceNumber) const; protected: @@ -84,8 +84,9 @@ private: mutable bool _isReliable { false }; mutable bool _isPartOfMessage { false }; mutable SequenceNumber _sequenceNumber { 0 }; - mutable PacketPosition _packetPosition { PacketPosition::ONLY }; mutable MessageNumber _messageNumber { 0 }; + mutable PacketPosition _packetPosition { PacketPosition::ONLY }; + mutable MessagePart _messagePart { 0 }; }; } // namespace udt diff --git a/libraries/networking/src/udt/PacketList.cpp b/libraries/networking/src/udt/PacketList.cpp index 64ae8f54db..8f6a65abc9 100644 --- a/libraries/networking/src/udt/PacketList.cpp +++ b/libraries/networking/src/udt/PacketList.cpp @@ -132,6 +132,24 @@ QByteArray PacketList::getMessage() { return data; } +void PacketList::preparePackets(MessageNumber messageNumber) { + Q_ASSERT(_packets.size() > 0); + + if (_packets.size() == 1) { + _packets.front()->writeMessageNumber(messageNumber, Packet::PacketPosition::ONLY, 0); + } else { + const auto second = ++_packets.begin(); + const auto last = --_packets.end(); + Packet::MessagePart messagePart = 0; + std::for_each(second, last, [&](const PacketPointer& packet) { + packet->writeMessageNumber(messageNumber, Packet::PacketPosition::MIDDLE, ++messagePart); + }); + + _packets.front()->writeMessageNumber(messageNumber, Packet::PacketPosition::FIRST, 0); + _packets.back()->writeMessageNumber(messageNumber, Packet::PacketPosition::LAST, ++messagePart); + } +} + qint64 PacketList::writeData(const char* data, qint64 maxSize) { auto sizeRemaining = maxSize; diff --git a/libraries/networking/src/udt/PacketList.h b/libraries/networking/src/udt/PacketList.h index c873e53711..5337094d1f 100644 --- a/libraries/networking/src/udt/PacketList.h +++ b/libraries/networking/src/udt/PacketList.h @@ -28,28 +28,29 @@ class Packet; class PacketList : public QIODevice { Q_OBJECT public: + using MessageNumber = uint32_t; + using PacketPointer = std::unique_ptr; + static std::unique_ptr create(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false); static std::unique_ptr fromReceivedPackets(std::list>&& packets); + PacketType getType() const { return _packetType; } bool isReliable() const { return _isReliable; } bool isOrdered() const { return _isOrdered; } + int getNumPackets() const { return _packets.size() + (_currentPacket ? 1 : 0); } + size_t getDataSize() const; + size_t getMessageSize() const; + QByteArray getMessage(); + + QByteArray getExtendedHeader() const { return _extendedHeader; } + void startSegment(); void endSegment(); - PacketType getType() const { return _packetType; } - int getNumPackets() const { return _packets.size() + (_currentPacket ? 1 : 0); } - - QByteArray getExtendedHeader() const { return _extendedHeader; } - - size_t getDataSize() const; - size_t getMessageSize() const; - void closeCurrentPacket(bool shouldSendEmpty = false); - QByteArray getMessage(); - // QIODevice virtual functions virtual bool isSequential() const { return false; } virtual qint64 size() const { return getDataSize(); } @@ -60,6 +61,8 @@ public: protected: PacketList(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false); PacketList(PacketList&& other); + + void preparePackets(MessageNumber messageNumber); virtual qint64 writeData(const char* data, qint64 maxSize); // Not implemented, added an assert so that it doesn't get used by accident diff --git a/libraries/networking/src/udt/PacketQueue.cpp b/libraries/networking/src/udt/PacketQueue.cpp index f5c1b4a9a0..48d5982eb3 100644 --- a/libraries/networking/src/udt/PacketQueue.cpp +++ b/libraries/networking/src/udt/PacketQueue.cpp @@ -45,26 +45,7 @@ void PacketQueue::queuePacket(PacketPointer packet) { } void PacketQueue::queuePacketList(PacketListPointer packetList) { - Q_ASSERT(packetList->_packets.size() > 0); - - auto messageNumber = getNextMessageNumber(); - auto markPacket = [&messageNumber](const PacketPointer& packet, Packet::PacketPosition position) { - packet->setPacketPosition(position); - packet->writeMessageNumber(messageNumber); - }; - - if (packetList->_packets.size() == 1) { - markPacket(packetList->_packets.front(), Packet::PacketPosition::ONLY); - } else { - const auto second = ++packetList->_packets.begin(); - const auto last = --packetList->_packets.end(); - std::for_each(second, last, [&](const PacketPointer& packet) { - markPacket(packet, Packet::PacketPosition::MIDDLE); - }); - - markPacket(packetList->_packets.front(), Packet::PacketPosition::FIRST); - markPacket(packetList->_packets.back(), Packet::PacketPosition::LAST); - } + packetList->preparePackets(getNextMessageNumber()); LockGuard locker(_packetsLock); _packets.splice(_packets.end(), packetList->_packets);