From f6526272de23ddf57a6f62e544c646ff86d3f240 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Feb 2016 16:58:15 -0800 Subject: [PATCH 01/12] Add header descriptions --- libraries/networking/src/NLPacket.h | 11 +++++++++++ libraries/networking/src/udt/Packet.h | 27 +++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/NLPacket.h b/libraries/networking/src/NLPacket.h index 57ada84607..4527094322 100644 --- a/libraries/networking/src/NLPacket.h +++ b/libraries/networking/src/NLPacket.h @@ -21,6 +21,17 @@ class NLPacket : public udt::Packet { Q_OBJECT public: + + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Packet Type | Packet Version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Node UUID | Hash (only if verified) | Optional (only if sourced) + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + // NLPacket Header Format + // this is used by the Octree classes - must be known at compile time static const int MAX_PACKET_HEADER_SIZE = sizeof(udt::Packet::SequenceNumberAndBitField) + sizeof(udt::Packet::MessageNumberAndBitField) + diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 02d2c3d9bd..2beac65330 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -25,6 +25,25 @@ namespace udt { class Packet : public BasePacket { Q_OBJECT public: + // Packet Header Format + // + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |C|R|M| O | Sequence Number | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | P | Message Number | Optional (only if M = 1) + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Message Part Number | Optional (only if M = 1) + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + // C: Control bit + // R: Reliable bit + // M: Message bit + // O: Obfuscation level + // P: Position bits + + // NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field using SequenceNumberAndBitField = uint32_t; @@ -35,10 +54,10 @@ public: // Use same size as MessageNumberAndBitField so we can use the enum with bitwise operations enum PacketPosition : MessageNumberAndBitField { - ONLY = 0x0, - FIRST = 0x2, - MIDDLE = 0x3, - LAST = 0x1 + ONLY = 0x0, // 00 + FIRST = 0x2, // 10 + MIDDLE = 0x3, // 11 + LAST = 0x1 // 01 }; static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); From 6d9405d91de8dcf03a3737d18e1f66b910a3ec44 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Feb 2016 16:32:43 -0800 Subject: [PATCH 02/12] Add obfuscation level to packets --- libraries/networking/src/udt/Packet.cpp | 11 +++++++++-- libraries/networking/src/udt/Packet.h | 16 +++++++++++++--- libraries/networking/src/udt/SequenceNumber.h | 6 +++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index e068727e6f..53b6ef5b68 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -119,14 +119,16 @@ void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition posi writeHeader(); } -void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const { +void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level) const { + _obfuscationLevel = level; _sequenceNumber = sequenceNumber; writeHeader(); } static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 2); static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 3); -static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK; +static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0x03) << (SEQUENCE_NUMBER_BITS - 5); +static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; static const uint8_t PACKET_POSITION_OFFSET = 30; static const uint32_t PACKET_POSITION_MASK = uint32_t(0x03) << PACKET_POSITION_OFFSET; @@ -139,6 +141,7 @@ void Packet::readHeader() const { _isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit _isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit + _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> (SEQUENCE_NUMBER_BITS - 5)); _sequenceNumber = SequenceNumber{ *seqNumBitField & ~BIT_FIELD_MASK }; // Remove the bit field if (_isPartOfMessage) { @@ -163,6 +166,10 @@ void Packet::writeHeader() const { if (_isReliable) { *seqNumBitField |= RELIABILITY_BIT_MASK; } + + if (_obfuscationLevel != NoObfuscation) { + *seqNumBitField |= (_obfuscationLevel << (SEQUENCE_NUMBER_BITS - 5)); + } if (_isPartOfMessage) { *seqNumBitField |= MESSAGE_BIT_MASK; diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 2beac65330..3eefa83edc 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -59,7 +59,15 @@ public: MIDDLE = 0x3, // 11 LAST = 0x1 // 01 }; - + + // Use same size as SequenceNumberAndBitField so we can use the enum with bitwise operations + enum ObfuscationLevel : SequenceNumberAndBitField { + NoObfuscation = 0x0, // 00 + ObfuscationL1 = 0x1, // 01 + ObfuscationL2 = 0x2, // 10 + ObfuscationL3 = 0x3, // 01 + }; + static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); @@ -75,14 +83,15 @@ public: bool isPartOfMessage() const { return _isPartOfMessage; } bool isReliable() const { return _isReliable; } - + + ObfuscationLevel getObfuscationLevel() const { return _obfuscationLevel; } SequenceNumber getSequenceNumber() const { return _sequenceNumber; } MessageNumber getMessageNumber() const { return _messageNumber; } PacketPosition getPacketPosition() const { return _packetPosition; } MessagePartNumber getMessagePartNumber() const { return _messagePartNumber; } void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber); - void writeSequenceNumber(SequenceNumber sequenceNumber) const; + void writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level = NoObfuscation) const; protected: Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false); @@ -102,6 +111,7 @@ private: // Simple holders to prevent multiple reading and bitwise ops mutable bool _isReliable { false }; mutable bool _isPartOfMessage { false }; + mutable ObfuscationLevel _obfuscationLevel { NoObfuscation }; mutable SequenceNumber _sequenceNumber { 0 }; mutable MessageNumber _messageNumber { 0 }; mutable PacketPosition _packetPosition { PacketPosition::ONLY }; diff --git a/libraries/networking/src/udt/SequenceNumber.h b/libraries/networking/src/udt/SequenceNumber.h index a75f3478b8..3abc80bdd8 100644 --- a/libraries/networking/src/udt/SequenceNumber.h +++ b/libraries/networking/src/udt/SequenceNumber.h @@ -24,9 +24,9 @@ public: using Type = int32_t; using UType = uint32_t; - // Values are for 29 bit SequenceNumber - static const Type THRESHOLD = 0x0FFFFFFF; // threshold for comparing sequence numbers - static const Type MAX = 0x1FFFFFFF; // maximum sequence number used in UDT + // Values are for 27 bit SequenceNumber + static const Type THRESHOLD = 0x03FFFFFF; // threshold for comparing sequence numbers + static const Type MAX = 0x07FFFFFF; // maximum sequence number used in UDT SequenceNumber() = default; SequenceNumber(const SequenceNumber& other) : _value(other._value) {} From 3d7d812044f4dc8313cd1bea832d1475bbf2e287 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Feb 2016 16:33:50 -0800 Subject: [PATCH 03/12] Add resend mecanic with obfuscation --- libraries/networking/src/udt/SaltShaker.cpp | 54 +++++++++++++++++++++ libraries/networking/src/udt/SaltShaker.h | 27 +++++++++++ libraries/networking/src/udt/SendQueue.cpp | 50 ++++++++++++++++--- libraries/networking/src/udt/SendQueue.h | 3 +- libraries/networking/src/udt/Socket.h | 2 +- 5 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 libraries/networking/src/udt/SaltShaker.cpp create mode 100644 libraries/networking/src/udt/SaltShaker.h diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp new file mode 100644 index 0000000000..2ae1ab520c --- /dev/null +++ b/libraries/networking/src/udt/SaltShaker.cpp @@ -0,0 +1,54 @@ +// +// SaltShaker.cpp +// libraries/networking/src/udt +// +// Created by Clement on 2/18/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SaltShaker.h" + +#include + +using namespace udt; + +using Key = uint64_t; +static const std::array KEYS {{ + 0x0, + 0xd6ea42f07644016a, + 0x700f7e3414dc4d8c, + 0x54c92e8d2c871642 +}}; + +void saltingHelper(char* start, int size, Key key) {; + const auto end = start + size; + + auto p = start; + for (; p < end; p += sizeof(Key)) { + *reinterpret_cast(p) ^= key; + } + + p -= sizeof(Key); + + for (int i = 0; p < end; ++p || ++i) { + *p ^= *(reinterpret_cast(&key) + i); + } +} + +std::unique_ptr SaltShaker::salt(const Packet& packet, unsigned int saltiness) { + Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); + + auto copy = Packet::createCopy(packet); + saltingHelper(copy->getPayload(), copy->getPayloadSize(), KEYS[saltiness]); + copy->writeSequenceNumber(copy->getSequenceNumber(), (Packet::ObfuscationLevel)saltiness); + return copy; +} + +void unsalt(Packet& packet, unsigned int saltiness) { + Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); + + saltingHelper(packet.getPayload(), packet.getPayloadSize(), KEYS[saltiness]); +} \ No newline at end of file diff --git a/libraries/networking/src/udt/SaltShaker.h b/libraries/networking/src/udt/SaltShaker.h new file mode 100644 index 0000000000..4cdf5fdbe3 --- /dev/null +++ b/libraries/networking/src/udt/SaltShaker.h @@ -0,0 +1,27 @@ +// +// SaltShaker.h +// libraries/networking/src/udt +// +// Created by Clement on 2/18/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SaltShaker_h +#define hifi_SaltShaker_h + +#include "Packet.h" + +namespace udt { + +class SaltShaker { +public: + std::unique_ptr salt(const Packet& packet, unsigned int saltiness); + void unsalt(Packet& packet, unsigned int saltiness); +}; + +} + +#endif // hifi_SaltShaker_h \ No newline at end of file diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 4d6e431b45..e8cf121609 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -24,6 +24,7 @@ #include "ControlPacket.h" #include "Packet.h" #include "PacketList.h" +#include "SaltShaker.h" #include "Socket.h" using namespace udt; @@ -225,7 +226,9 @@ void SendQueue::sendNewPacketAndAddToSentList(std::unique_ptr newPacket, { // Insert the packet we have just sent in the sent list QWriteLocker locker(&_sentLock); - _sentPackets[newPacket->getSequenceNumber()].swap(newPacket); + auto& entry = _sentPackets[newPacket->getSequenceNumber()]; + entry.first = 0; // No resend + entry.second.swap(newPacket); } Q_ASSERT_X(!newPacket, "SendQueue::sendNewPacketAndAddToSentList()", "Overriden packet in sent list"); @@ -354,14 +357,45 @@ bool SendQueue::maybeResendPacket() { auto it = _sentPackets.find(resendNumber); if (it != _sentPackets.end()) { + auto& entry = it->second; // we found the packet - grab it - auto& resendPacket = *(it->second); - - // send it off - sendPacket(resendPacket); - - // unlock the sent packets - sentLocker.unlock(); + auto& resendPacket = *(entry.second); + ++entry.first; // Add 1 resend + + static const int OBFUSCATION_THRESHOLD = 3; + if (entry.first > OBFUSCATION_THRESHOLD) { + + if (entry.first % OBFUSCATION_THRESHOLD == 0) { + QString debugString = "Obfuscating packet %1 with level %2 for the first time."; + debugString = debugString.arg((uint32_t)resendPacket.getSequenceNumber(), + entry.first / OBFUSCATION_THRESHOLD); + + if (resendPacket.isPartOfMessage()) { + debugString += "\n"; + debugString += " Message Number: %1, Part Number: %2."; + debugString = debugString.arg(resendPacket.getMessageNumber(), + resendPacket.getMessagePartNumber()); + } + + qCritical() << qPrintable(debugString); + } + + + SaltShaker shaker; + auto packet = shaker.salt(resendPacket, glm::min(entry.first / OBFUSCATION_THRESHOLD, 3)); + + // unlock the sent packets + sentLocker.unlock(); + + // send it off + sendPacket(*packet); + } else { + // send it off + sendPacket(resendPacket); + + // unlock the sent packets + sentLocker.unlock(); + } emit packetRetransmitted(); diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 5428e7a26d..da8f5e6c3f 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -126,7 +126,8 @@ private: LossList _naks; // Sequence numbers of packets to resend mutable QReadWriteLock _sentLock; // Protects the sent packet list - std::unordered_map> _sentPackets; // Packets waiting for ACK. + using PacketResendPair = std::pair>; // Number of resend + packet ptr + std::unordered_map _sentPackets; // Packets waiting for ACK. std::mutex _handshakeMutex; // Protects the handshake ACK condition_variable std::atomic _hasReceivedHandshakeACK { false }; // flag for receipt of handshake ACK from client diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index 88db8e3d86..f31adfa4ab 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -25,7 +25,7 @@ #include "CongestionControl.h" #include "Connection.h" -//#define UDT_CONNECTION_DEBUG +#define UDT_CONNECTION_DEBUG class UDTTest; From 4605cf508771ea71da5430e849111e069e28d7ea Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 11:14:05 -0800 Subject: [PATCH 04/12] Move all udt header constants to Constant.h --- libraries/networking/src/udt/Constants.h | 61 ++++++++++++++++++-- libraries/networking/src/udt/Packet.cpp | 17 ++---- libraries/networking/src/udt/Packet.h | 2 +- libraries/networking/src/udt/PacketQueue.cpp | 2 +- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/libraries/networking/src/udt/Constants.h b/libraries/networking/src/udt/Constants.h index 9f5f1db883..a13997e9a3 100644 --- a/libraries/networking/src/udt/Constants.h +++ b/libraries/networking/src/udt/Constants.h @@ -26,10 +26,63 @@ namespace udt { static const int UDP_SEND_BUFFER_SIZE_BYTES = 1048576; static const int UDP_RECEIVE_BUFFER_SIZE_BYTES = 1048576; static const int DEFAULT_SYN_INTERVAL_USECS = 10 * 1000; - static const int SEQUENCE_NUMBER_BITS = sizeof(SequenceNumber) * 8; - static const int MESSAGE_LINE_NUMBER_BITS = 32; - static const int MESSAGE_NUMBER_BITS = 30; - static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 1); + + // Header constants + + // Bit sizes (in order) + static const int CONTROL_BIT_SIZE = 1; + static const int RELIABILITY_BIT_SIZE = 1; + static const int MESSAGE_BIT_SIZE = 1; + static const int OBFUSCATION_LEVEL_SIZE = 2; + static const int SEQUENCE_NUMBER_SIZE= 27; + + static const int PACKET_POSITION_SIZE = 2; + static const int MESSAGE_NUMBER_SIZE = 30; + + static const int MESSAGE_PART_NUMBER_SIZE = 32; + + // Offsets + static const int SEQUENCE_NUMBER_OFFSET = 0; + static const int OBFUSCATION_LEVEL_OFFSET = SEQUENCE_NUMBER_OFFSET + SEQUENCE_NUMBER_SIZE; + static const int MESSAGE_BIT_OFFSET = OBFUSCATION_LEVEL_OFFSET + OBFUSCATION_LEVEL_SIZE; + static const int RELIABILITY_BIT_OFFSET = MESSAGE_BIT_OFFSET + MESSAGE_BIT_SIZE; + static const int CONTROL_BIT_OFFSET = RELIABILITY_BIT_OFFSET + RELIABILITY_BIT_SIZE; + + static const int MESSAGE_NUMBER_OFFSET = 0; + static const int PACKET_POSITION_OFFSET = MESSAGE_NUMBER_OFFSET + MESSAGE_NUMBER_SIZE; + + static const int MESSAGE_PART_NUMBER_OFFSET = 0; + + // Masks + static const uint32_t CONTROL_BIT_MASK = uint32_t(0b1) << CONTROL_BIT_OFFSET; + static const uint32_t RELIABILITY_BIT_MASK = uint32_t(0b1) << RELIABILITY_BIT_OFFSET; + static const uint32_t MESSAGE_BIT_MASK = uint32_t(0b1) << MESSAGE_BIT_OFFSET; + static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0b11) << OBFUSCATION_LEVEL_OFFSET; + static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; + static const uint32_t SEQUENCE_NUMBER_MASK = ~BIT_FIELD_MASK; + + static const uint32_t PACKET_POSITION_MASK = uint32_t(0b11) << PACKET_POSITION_OFFSET; + static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK; + + static const uint32_t MESSAGE_PART_NUMBER_MASK = ~uint32_t(0); + + // Static checks + static_assert(CONTROL_BIT_SIZE + RELIABILITY_BIT_SIZE + MESSAGE_BIT_SIZE + + OBFUSCATION_LEVEL_SIZE + SEQUENCE_NUMBER_SIZE == 32, "Sequence number line size incorrect"); + static_assert(PACKET_POSITION_SIZE + MESSAGE_NUMBER_SIZE == 32, "Message number line size incorrect"); + static_assert(MESSAGE_PART_NUMBER_SIZE == 32, "Message part number line size incorrect"); + + static_assert(CONTROL_BIT_MASK == 0b10000000000000000000000000000000, "CONTROL_BIT_MASK incorrect"); + static_assert(RELIABILITY_BIT_MASK == 0b01000000000000000000000000000000, "RELIABILITY_BIT_MASK incorrect"); + static_assert(MESSAGE_BIT_MASK == 0b00100000000000000000000000000000, "MESSAGE_BIT_MASK incorrect"); + static_assert(OBFUSCATION_LEVEL_MASK == 0b00011000000000000000000000000000, "OBFUSCATION_LEVEL_MASK incorrect"); + static_assert(BIT_FIELD_MASK == 0b11111000000000000000000000000000, "BIT_FIELD_MASK incorrect"); + static_assert(SEQUENCE_NUMBER_MASK == 0b00000111111111111111111111111111, "SEQUENCE_NUMBER_MASK incorrect"); + + static_assert(PACKET_POSITION_MASK == 0b11000000000000000000000000000000, "PACKET_POSITION_MASK incorrect"); + static_assert(MESSAGE_NUMBER_MASK == 0b00111111111111111111111111111111, "MESSAGE_NUMBER_MASK incorrect"); + + static_assert(MESSAGE_PART_NUMBER_MASK == 0b11111111111111111111111111111111, "MESSAGE_PART_NUMBER_MASK incorrect"); } #endif // hifi_udt_Constants_h diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 53b6ef5b68..17d18bebea 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -120,20 +120,11 @@ void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition posi } void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level) const { - _obfuscationLevel = level; _sequenceNumber = sequenceNumber; + _obfuscationLevel = level; writeHeader(); } -static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 2); -static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 3); -static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0x03) << (SEQUENCE_NUMBER_BITS - 5); -static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; - -static const uint8_t PACKET_POSITION_OFFSET = 30; -static const uint32_t PACKET_POSITION_MASK = uint32_t(0x03) << PACKET_POSITION_OFFSET; -static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK; - void Packet::readHeader() const { SequenceNumberAndBitField* seqNumBitField = reinterpret_cast(_packet.get()); @@ -141,8 +132,8 @@ void Packet::readHeader() const { _isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit _isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit - _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> (SEQUENCE_NUMBER_BITS - 5)); - _sequenceNumber = SequenceNumber{ *seqNumBitField & ~BIT_FIELD_MASK }; // Remove the bit field + _obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> OBFUSCATION_LEVEL_OFFSET); + _sequenceNumber = SequenceNumber{ *seqNumBitField & SEQUENCE_NUMBER_MASK }; // Remove the bit field if (_isPartOfMessage) { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; @@ -168,7 +159,7 @@ void Packet::writeHeader() const { } if (_obfuscationLevel != NoObfuscation) { - *seqNumBitField |= (_obfuscationLevel << (SEQUENCE_NUMBER_BITS - 5)); + *seqNumBitField |= (_obfuscationLevel << OBFUSCATION_LEVEL_OFFSET); } if (_isPartOfMessage) { diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 3eefa83edc..2fd38de51f 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -65,7 +65,7 @@ public: NoObfuscation = 0x0, // 00 ObfuscationL1 = 0x1, // 01 ObfuscationL2 = 0x2, // 10 - ObfuscationL3 = 0x3, // 01 + ObfuscationL3 = 0x3, // 11 }; static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); diff --git a/libraries/networking/src/udt/PacketQueue.cpp b/libraries/networking/src/udt/PacketQueue.cpp index bc3a1796e2..8ff2333a20 100644 --- a/libraries/networking/src/udt/PacketQueue.cpp +++ b/libraries/networking/src/udt/PacketQueue.cpp @@ -16,7 +16,7 @@ using namespace udt; MessageNumber PacketQueue::getNextMessageNumber() { - static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_BITS; + static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_SIZE; _currentMessageNumber = (_currentMessageNumber + 1) % MAX_MESSAGE_NUMBER; return _currentMessageNumber; } From bf5a65ca456a840314794c37a8efc81e0e6e8302 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 15:04:21 -0800 Subject: [PATCH 05/12] Add missing copies --- libraries/networking/src/udt/Constants.h | 1 + libraries/networking/src/udt/Packet.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/Constants.h b/libraries/networking/src/udt/Constants.h index a13997e9a3..0e63afe0a0 100644 --- a/libraries/networking/src/udt/Constants.h +++ b/libraries/networking/src/udt/Constants.h @@ -27,6 +27,7 @@ namespace udt { static const int UDP_RECEIVE_BUFFER_SIZE_BYTES = 1048576; static const int DEFAULT_SYN_INTERVAL_USECS = 10 * 1000; + // Header constants // Bit sizes (in order) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 17d18bebea..263c7ee6cf 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -76,15 +76,23 @@ Packet::Packet(const Packet& other) : { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; + _packetPosition = other._packetPosition; + _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; } Packet& Packet::operator=(const Packet& other) { BasePacket::operator=(other); - + _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; + _packetPosition = other._packetPosition; + _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; return *this; } @@ -94,19 +102,23 @@ Packet::Packet(Packet&& other) : { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; _packetPosition = other._packetPosition; _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; } Packet& Packet::operator=(Packet&& other) { BasePacket::operator=(std::move(other)); - + _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; _sequenceNumber = other._sequenceNumber; _packetPosition = other._packetPosition; _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; return *this; } From c29ad093066871ee684d645f16c1179d1ce8436c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 15:12:31 -0800 Subject: [PATCH 06/12] Fix obfuscation --- libraries/networking/src/udt/Packet.cpp | 24 ++++++++++++++++ libraries/networking/src/udt/SaltShaker.cpp | 8 +++--- libraries/networking/src/udt/SendQueue.cpp | 31 +++++++++++---------- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 263c7ee6cf..84b4b24ec2 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -11,6 +11,10 @@ #include "Packet.h" +#include + +#include "SaltShaker.h" + using namespace udt; static int packetMetaTypeId = qRegisterMetaType("Packet*"); @@ -68,6 +72,26 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se { readHeader(); + if (getObfuscationLevel() != Packet::NoObfuscation) { + SaltShaker shaker; + shaker.unsalt(*this, getObfuscationLevel()); + readHeader(); // read packet header again as some of the data was obfuscated + + QString debugString = "Unobfuscating packet %1 with level %2"; + debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), + QString::number(getObfuscationLevel())); + + if (isPartOfMessage()) { + debugString += "\n"; + debugString += " Message Number: %1, Part Number: %2."; + debugString = debugString.arg(QString::number(getMessageNumber()), + QString::number(getMessagePartNumber())); + } + + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .{0,1000}"); + qDebug() << qPrintable(debugString); + } + adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); } diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp index 2ae1ab520c..73c59f7925 100644 --- a/libraries/networking/src/udt/SaltShaker.cpp +++ b/libraries/networking/src/udt/SaltShaker.cpp @@ -23,7 +23,7 @@ static const std::array KEYS {{ 0x54c92e8d2c871642 }}; -void saltingHelper(char* start, int size, Key key) {; +void saltingHelper(char* start, int size, Key key) { const auto end = start + size; auto p = start; @@ -42,13 +42,13 @@ std::unique_ptr SaltShaker::salt(const Packet& packet, unsigned int salt Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); auto copy = Packet::createCopy(packet); - saltingHelper(copy->getPayload(), copy->getPayloadSize(), KEYS[saltiness]); copy->writeSequenceNumber(copy->getSequenceNumber(), (Packet::ObfuscationLevel)saltiness); + saltingHelper(copy->getData() + 4, copy->getDataSize() - 4, KEYS[saltiness]); return copy; } -void unsalt(Packet& packet, unsigned int saltiness) { +void SaltShaker::unsalt(Packet& packet, unsigned int saltiness) { Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); - saltingHelper(packet.getPayload(), packet.getPayloadSize(), KEYS[saltiness]); + saltingHelper(packet.getData() + 4, packet.getDataSize() - 4, KEYS[saltiness]); } \ No newline at end of file diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index e8cf121609..da3727b214 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -338,6 +338,8 @@ bool SendQueue::maybeSendNewPacket() { return false; } +#include + bool SendQueue::maybeResendPacket() { // the following while makes sure that we find a packet to re-send, if there is one @@ -362,27 +364,26 @@ bool SendQueue::maybeResendPacket() { auto& resendPacket = *(entry.second); ++entry.first; // Add 1 resend - static const int OBFUSCATION_THRESHOLD = 3; - if (entry.first > OBFUSCATION_THRESHOLD) { + auto saltiness = entry.first < 2 ? 0 : (entry.first - 2) % 4; - if (entry.first % OBFUSCATION_THRESHOLD == 0) { - QString debugString = "Obfuscating packet %1 with level %2 for the first time."; - debugString = debugString.arg((uint32_t)resendPacket.getSequenceNumber(), - entry.first / OBFUSCATION_THRESHOLD); + if (saltiness != 0) { + QString debugString = "Obfuscating packet %1 with level %2"; + debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()), + QString::number(saltiness)); - if (resendPacket.isPartOfMessage()) { - debugString += "\n"; - debugString += " Message Number: %1, Part Number: %2."; - debugString = debugString.arg(resendPacket.getMessageNumber(), - resendPacket.getMessagePartNumber()); - } - - qCritical() << qPrintable(debugString); + if (resendPacket.isPartOfMessage()) { + debugString += "\n"; + debugString += " Message Number: %1, Part Number: %2."; + debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()), + QString::number(resendPacket.getMessagePartNumber())); } + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .{0,1000}"); + qCritical() << qPrintable(debugString); + SaltShaker shaker; - auto packet = shaker.salt(resendPacket, glm::min(entry.first / OBFUSCATION_THRESHOLD, 3)); + auto packet = shaker.salt(resendPacket, saltiness); // unlock the sent packets sentLocker.unlock(); From 3a11e84c94cf1842690c9eee3f1382e43d270436 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 15:30:12 -0800 Subject: [PATCH 07/12] Use hex for msvc compatibility --- libraries/networking/src/udt/Constants.h | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/libraries/networking/src/udt/Constants.h b/libraries/networking/src/udt/Constants.h index 0e63afe0a0..98569ead5a 100644 --- a/libraries/networking/src/udt/Constants.h +++ b/libraries/networking/src/udt/Constants.h @@ -55,35 +55,36 @@ namespace udt { static const int MESSAGE_PART_NUMBER_OFFSET = 0; // Masks - static const uint32_t CONTROL_BIT_MASK = uint32_t(0b1) << CONTROL_BIT_OFFSET; - static const uint32_t RELIABILITY_BIT_MASK = uint32_t(0b1) << RELIABILITY_BIT_OFFSET; - static const uint32_t MESSAGE_BIT_MASK = uint32_t(0b1) << MESSAGE_BIT_OFFSET; - static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(0b11) << OBFUSCATION_LEVEL_OFFSET; + static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << CONTROL_BIT_OFFSET; + static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << RELIABILITY_BIT_OFFSET; + static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << MESSAGE_BIT_OFFSET; + static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(3) << OBFUSCATION_LEVEL_OFFSET; static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK; static const uint32_t SEQUENCE_NUMBER_MASK = ~BIT_FIELD_MASK; - static const uint32_t PACKET_POSITION_MASK = uint32_t(0b11) << PACKET_POSITION_OFFSET; + static const uint32_t PACKET_POSITION_MASK = uint32_t(3) << PACKET_POSITION_OFFSET; static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK; static const uint32_t MESSAGE_PART_NUMBER_MASK = ~uint32_t(0); + // Static checks static_assert(CONTROL_BIT_SIZE + RELIABILITY_BIT_SIZE + MESSAGE_BIT_SIZE + OBFUSCATION_LEVEL_SIZE + SEQUENCE_NUMBER_SIZE == 32, "Sequence number line size incorrect"); static_assert(PACKET_POSITION_SIZE + MESSAGE_NUMBER_SIZE == 32, "Message number line size incorrect"); static_assert(MESSAGE_PART_NUMBER_SIZE == 32, "Message part number line size incorrect"); - static_assert(CONTROL_BIT_MASK == 0b10000000000000000000000000000000, "CONTROL_BIT_MASK incorrect"); - static_assert(RELIABILITY_BIT_MASK == 0b01000000000000000000000000000000, "RELIABILITY_BIT_MASK incorrect"); - static_assert(MESSAGE_BIT_MASK == 0b00100000000000000000000000000000, "MESSAGE_BIT_MASK incorrect"); - static_assert(OBFUSCATION_LEVEL_MASK == 0b00011000000000000000000000000000, "OBFUSCATION_LEVEL_MASK incorrect"); - static_assert(BIT_FIELD_MASK == 0b11111000000000000000000000000000, "BIT_FIELD_MASK incorrect"); - static_assert(SEQUENCE_NUMBER_MASK == 0b00000111111111111111111111111111, "SEQUENCE_NUMBER_MASK incorrect"); + static_assert(CONTROL_BIT_MASK == 0x80000000, "CONTROL_BIT_MASK incorrect"); + static_assert(RELIABILITY_BIT_MASK == 0x40000000, "RELIABILITY_BIT_MASK incorrect"); + static_assert(MESSAGE_BIT_MASK == 0x20000000, "MESSAGE_BIT_MASK incorrect"); + static_assert(OBFUSCATION_LEVEL_MASK == 0x18000000, "OBFUSCATION_LEVEL_MASK incorrect"); + static_assert(BIT_FIELD_MASK == 0xF8000000, "BIT_FIELD_MASK incorrect"); + static_assert(SEQUENCE_NUMBER_MASK == 0x07FFFFFF, "SEQUENCE_NUMBER_MASK incorrect"); - static_assert(PACKET_POSITION_MASK == 0b11000000000000000000000000000000, "PACKET_POSITION_MASK incorrect"); - static_assert(MESSAGE_NUMBER_MASK == 0b00111111111111111111111111111111, "MESSAGE_NUMBER_MASK incorrect"); + static_assert(PACKET_POSITION_MASK == 0xC0000000, "PACKET_POSITION_MASK incorrect"); + static_assert(MESSAGE_NUMBER_MASK == 0x3FFFFFFF, "MESSAGE_NUMBER_MASK incorrect"); - static_assert(MESSAGE_PART_NUMBER_MASK == 0b11111111111111111111111111111111, "MESSAGE_PART_NUMBER_MASK incorrect"); + static_assert(MESSAGE_PART_NUMBER_MASK == 0xFFFFFFFF, "MESSAGE_PART_NUMBER_MASK incorrect"); } #endif // hifi_udt_Constants_h From f06ac911c543e1cd5df04f8bc726cacff2c74955 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 Feb 2016 16:05:57 -0800 Subject: [PATCH 08/12] Fix XORing algorithm --- libraries/networking/src/udt/SaltShaker.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp index 73c59f7925..4febaa789a 100644 --- a/libraries/networking/src/udt/SaltShaker.cpp +++ b/libraries/networking/src/udt/SaltShaker.cpp @@ -27,12 +27,10 @@ void saltingHelper(char* start, int size, Key key) { const auto end = start + size; auto p = start; - for (; p < end; p += sizeof(Key)) { + for (; p + sizeof(Key) < end; p += sizeof(Key)) { *reinterpret_cast(p) ^= key; } - p -= sizeof(Key); - for (int i = 0; p < end; ++p || ++i) { *p ^= *(reinterpret_cast(&key) + i); } From 17b4d6fcf9501579b8bf65315ae509cb2ad169ce Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 11:40:07 -0800 Subject: [PATCH 09/12] Factor members copy --- libraries/networking/src/udt/Packet.cpp | 50 ++++++++----------------- libraries/networking/src/udt/Packet.h | 2 + 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 84b4b24ec2..b06f7ba847 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -95,54 +95,26 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); } -Packet::Packet(const Packet& other) : - BasePacket(other) -{ - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; +Packet::Packet(const Packet& other) : BasePacket(other) { + copyMembers(other); } Packet& Packet::operator=(const Packet& other) { BasePacket::operator=(other); - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; + copyMembers(other); return *this; } -Packet::Packet(Packet&& other) : - BasePacket(std::move(other)) -{ - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; +Packet::Packet(Packet&& other) : BasePacket(std::move(other)) { + copyMembers(other); } Packet& Packet::operator=(Packet&& other) { BasePacket::operator=(std::move(other)); - _isReliable = other._isReliable; - _isPartOfMessage = other._isPartOfMessage; - _obfuscationLevel = other._obfuscationLevel; - _sequenceNumber = other._sequenceNumber; - _packetPosition = other._packetPosition; - _messageNumber = other._messageNumber; - _messagePartNumber = other._messagePartNumber; + copyMembers(other); return *this; } @@ -161,6 +133,16 @@ void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel writeHeader(); } +void Packet::copyMembers(const Packet& other) { + _isReliable = other._isReliable; + _isPartOfMessage = other._isPartOfMessage; + _obfuscationLevel = other._obfuscationLevel; + _sequenceNumber = other._sequenceNumber; + _packetPosition = other._packetPosition; + _messageNumber = other._messageNumber; + _messagePartNumber = other._messagePartNumber; +} + void Packet::readHeader() const { SequenceNumberAndBitField* seqNumBitField = reinterpret_cast(_packet.get()); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 2fd38de51f..bfd1b9a3cd 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -104,6 +104,8 @@ protected: Packet& operator=(Packet&& other); private: + void copyMembers(const Packet& other); + // Header readers - these read data to member variables after pulling packet off wire void readHeader() const; void writeHeader() const; From cb4f400c7ee567b505daf320d80f0529ef78c037 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 15:15:15 -0800 Subject: [PATCH 10/12] Cleanup obfuscation code --- libraries/networking/src/udt/Packet.cpp | 53 ++++++++++++++++----- libraries/networking/src/udt/Packet.h | 5 +- libraries/networking/src/udt/SaltShaker.cpp | 52 -------------------- libraries/networking/src/udt/SaltShaker.h | 27 ----------- libraries/networking/src/udt/SendQueue.cpp | 19 ++++---- 5 files changed, 55 insertions(+), 101 deletions(-) delete mode 100644 libraries/networking/src/udt/SaltShaker.cpp delete mode 100644 libraries/networking/src/udt/SaltShaker.h diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index b06f7ba847..f6bff06173 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -11,14 +11,35 @@ #include "Packet.h" -#include +#include -#include "SaltShaker.h" +#include using namespace udt; static int packetMetaTypeId = qRegisterMetaType("Packet*"); +using Key = uint64_t; +static const std::array KEYS {{ + 0x0, + 0x6362726973736574, + 0x7362697261726461, + 0x72687566666d616e, +}}; + +void xorHelper(char* start, int size, Key key) { + const auto end = start + size; + + auto p = start; + for (; p + sizeof(Key) < end; p += sizeof(Key)) { + *reinterpret_cast(p) ^= key; + } + + for (int i = 0; p < end; ++p || ++i) { + *p ^= *(reinterpret_cast(&key) + i); + } +} + int Packet::localHeaderSize(bool isPartOfMessage) { return sizeof(Packet::SequenceNumberAndBitField) + (isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0); @@ -72,11 +93,9 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se { readHeader(); - if (getObfuscationLevel() != Packet::NoObfuscation) { - SaltShaker shaker; - shaker.unsalt(*this, getObfuscationLevel()); - readHeader(); // read packet header again as some of the data was obfuscated + adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); + if (getObfuscationLevel() != Packet::NoObfuscation) { QString debugString = "Unobfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), QString::number(getObfuscationLevel())); @@ -90,9 +109,9 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .{0,1000}"); qDebug() << qPrintable(debugString); - } - adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); + obfuscate(NoObfuscation); // Undo obfuscation + } } Packet::Packet(const Packet& other) : BasePacket(other) { @@ -119,7 +138,7 @@ Packet& Packet::operator=(Packet&& other) { return *this; } -void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) { +void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const { _isPartOfMessage = true; _messageNumber = messageNumber; _packetPosition = position; @@ -127,12 +146,23 @@ void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition posi writeHeader(); } -void Packet::writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level) const { +void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const { _sequenceNumber = sequenceNumber; - _obfuscationLevel = level; writeHeader(); } +void Packet::obfuscate(ObfuscationLevel level) { + auto obfuscationKey = KEYS[getObfuscationLevel()] ^ KEYS[level]; // Undo old and apply new one. + if (obfuscationKey != 0) { + xorHelper(getData() + localHeaderSize(isPartOfMessage()), + getDataSize() - localHeaderSize(isPartOfMessage()), obfuscationKey); + + // Update members and header + _obfuscationLevel = level; + writeHeader(); + } +} + void Packet::copyMembers(const Packet& other) { _isReliable = other._isReliable; _isPartOfMessage = other._isPartOfMessage; @@ -155,6 +185,7 @@ void Packet::readHeader() const { if (_isPartOfMessage) { MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1; + _messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK; _packetPosition = static_cast(*messageNumberAndBitField >> PACKET_POSITION_OFFSET); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index bfd1b9a3cd..c0da3a0781 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -90,8 +90,9 @@ public: PacketPosition getPacketPosition() const { return _packetPosition; } MessagePartNumber getMessagePartNumber() const { return _messagePartNumber; } - void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber); - void writeSequenceNumber(SequenceNumber sequenceNumber, ObfuscationLevel level = NoObfuscation) const; + void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const; + void writeSequenceNumber(SequenceNumber sequenceNumber) const; + void obfuscate(ObfuscationLevel level); protected: Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false); diff --git a/libraries/networking/src/udt/SaltShaker.cpp b/libraries/networking/src/udt/SaltShaker.cpp deleted file mode 100644 index 4febaa789a..0000000000 --- a/libraries/networking/src/udt/SaltShaker.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// SaltShaker.cpp -// libraries/networking/src/udt -// -// Created by Clement on 2/18/16. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "SaltShaker.h" - -#include - -using namespace udt; - -using Key = uint64_t; -static const std::array KEYS {{ - 0x0, - 0xd6ea42f07644016a, - 0x700f7e3414dc4d8c, - 0x54c92e8d2c871642 -}}; - -void saltingHelper(char* start, int size, Key key) { - const auto end = start + size; - - auto p = start; - for (; p + sizeof(Key) < end; p += sizeof(Key)) { - *reinterpret_cast(p) ^= key; - } - - for (int i = 0; p < end; ++p || ++i) { - *p ^= *(reinterpret_cast(&key) + i); - } -} - -std::unique_ptr SaltShaker::salt(const Packet& packet, unsigned int saltiness) { - Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); - - auto copy = Packet::createCopy(packet); - copy->writeSequenceNumber(copy->getSequenceNumber(), (Packet::ObfuscationLevel)saltiness); - saltingHelper(copy->getData() + 4, copy->getDataSize() - 4, KEYS[saltiness]); - return copy; -} - -void SaltShaker::unsalt(Packet& packet, unsigned int saltiness) { - Q_ASSERT_X(saltiness < KEYS.size(), Q_FUNC_INFO, ""); - - saltingHelper(packet.getData() + 4, packet.getDataSize() - 4, KEYS[saltiness]); -} \ No newline at end of file diff --git a/libraries/networking/src/udt/SaltShaker.h b/libraries/networking/src/udt/SaltShaker.h deleted file mode 100644 index 4cdf5fdbe3..0000000000 --- a/libraries/networking/src/udt/SaltShaker.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// SaltShaker.h -// libraries/networking/src/udt -// -// Created by Clement on 2/18/16. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_SaltShaker_h -#define hifi_SaltShaker_h - -#include "Packet.h" - -namespace udt { - -class SaltShaker { -public: - std::unique_ptr salt(const Packet& packet, unsigned int saltiness); - void unsalt(Packet& packet, unsigned int saltiness); -}; - -} - -#endif // hifi_SaltShaker_h \ No newline at end of file diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index da3727b214..d3051377d3 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -18,13 +18,13 @@ #include #include +#include #include #include "../NetworkLogging.h" #include "ControlPacket.h" #include "Packet.h" #include "PacketList.h" -#include "SaltShaker.h" #include "Socket.h" using namespace udt; @@ -338,8 +338,6 @@ bool SendQueue::maybeSendNewPacket() { return false; } -#include - bool SendQueue::maybeResendPacket() { // the following while makes sure that we find a packet to re-send, if there is one @@ -364,13 +362,12 @@ bool SendQueue::maybeResendPacket() { auto& resendPacket = *(entry.second); ++entry.first; // Add 1 resend - auto saltiness = entry.first < 2 ? 0 : (entry.first - 2) % 4; + Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4); - if (saltiness != 0) { + if (level != Packet::NoObfuscation) { QString debugString = "Obfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()), - QString::number(saltiness)); - + QString::number(level)); if (resendPacket.isPartOfMessage()) { debugString += "\n"; debugString += " Message Number: %1, Part Number: %2."; @@ -382,12 +379,16 @@ bool SendQueue::maybeResendPacket() { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .{0,1000}"); qCritical() << qPrintable(debugString); - SaltShaker shaker; - auto packet = shaker.salt(resendPacket, saltiness); + + // Create copy of the packet + auto packet = Packet::createCopy(resendPacket); // unlock the sent packets sentLocker.unlock(); + // Obfuscate packet + packet->obfuscate(level); + // send it off sendPacket(*packet); } else { From 97aebaf52a820610313243b6bdc3a8e71ca1453c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 15:33:53 -0800 Subject: [PATCH 11/12] Fix log regexes --- libraries/networking/src/udt/Packet.cpp | 2 +- libraries/networking/src/udt/SendQueue.cpp | 4 +--- libraries/networking/src/udt/Socket.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index f6bff06173..9b413c0517 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -107,7 +107,7 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se QString::number(getMessagePartNumber())); } - static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .{0,1000}"); + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*"); qDebug() << qPrintable(debugString); obfuscate(NoObfuscation); // Undo obfuscation diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index d3051377d3..3d7b585ed6 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -374,9 +374,7 @@ bool SendQueue::maybeResendPacket() { debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()), QString::number(resendPacket.getMessagePartNumber())); } - - - static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .{0,1000}"); + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*"); qCritical() << qPrintable(debugString); diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 8fb5db3853..1eb7c04331 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -277,7 +277,7 @@ void Socket::readPendingDatagrams() { if (packet->isReliable()) { // if this was a reliable packet then signal the matching connection with the sequence number auto& connection = findOrCreateConnection(senderSockAddr); - + if (!connection.processReceivedSequenceNumber(packet->getSequenceNumber(), packet->getDataSize(), packet->getPayloadSize())) { From 4c18a504733cac70e219cc002af71c1aca28a9a8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Feb 2016 15:38:09 -0800 Subject: [PATCH 12/12] Only debug if define set --- libraries/networking/src/udt/Packet.cpp | 4 +++- libraries/networking/src/udt/Packet.h | 2 +- libraries/networking/src/udt/SendQueue.cpp | 3 ++- libraries/networking/src/udt/Socket.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 9b413c0517..088de49981 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -96,6 +96,7 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0); if (getObfuscationLevel() != Packet::NoObfuscation) { +#ifdef UDT_CONNECTION_DEBUG QString debugString = "Unobfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()), QString::number(getObfuscationLevel())); @@ -109,6 +110,7 @@ Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& se static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*"); qDebug() << qPrintable(debugString); +#endif obfuscate(NoObfuscation); // Undo obfuscation } @@ -138,7 +140,7 @@ Packet& Packet::operator=(Packet&& other) { return *this; } -void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const { +void Packet::writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) { _isPartOfMessage = true; _messageNumber = messageNumber; _packetPosition = position; diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index c0da3a0781..cad5cccb0e 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -90,7 +90,7 @@ public: PacketPosition getPacketPosition() const { return _packetPosition; } MessagePartNumber getMessagePartNumber() const { return _messagePartNumber; } - void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber) const; + void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber); void writeSequenceNumber(SequenceNumber sequenceNumber) const; void obfuscate(ObfuscationLevel level); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 3d7b585ed6..18269d1d43 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -365,6 +365,7 @@ bool SendQueue::maybeResendPacket() { Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4); if (level != Packet::NoObfuscation) { +#ifdef UDT_CONNECTION_DEBUG QString debugString = "Obfuscating packet %1 with level %2"; debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()), QString::number(level)); @@ -376,7 +377,7 @@ bool SendQueue::maybeResendPacket() { } static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*"); qCritical() << qPrintable(debugString); - +#endif // Create copy of the packet auto packet = Packet::createCopy(resendPacket); diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index f31adfa4ab..88db8e3d86 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -25,7 +25,7 @@ #include "CongestionControl.h" #include "Connection.h" -#define UDT_CONNECTION_DEBUG +//#define UDT_CONNECTION_DEBUG class UDTTest;