From 8a3b233659922c85e4a32a0f5201b7167d8e0f44 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 22 Feb 2016 13:58:07 -0800 Subject: [PATCH 01/22] don't crash if entity vanishes while doing touch test --- examples/controllers/handControllerGrab.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 3051f3faaf..dc43b3f117 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -564,7 +564,7 @@ function MyController(hand) { "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } - + this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject); }; @@ -1587,11 +1587,10 @@ function MyController(hand) { } ids.forEach(function(id) { - var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { return; - } else { + } else if (props.boundingBox) { var entityMinPoint = props.boundingBox.brn; var entityMaxPoint = props.boundingBox.tfl; var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); @@ -1616,7 +1615,6 @@ function MyController(hand) { } }); - }; this.startTouch = function(entityID) { From c4706490766f8fb5bf0531536db4f12c4e2328e1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 22 Feb 2016 14:00:01 -0800 Subject: [PATCH 02/22] don't crash if entity vanishes while doing touch test --- examples/controllers/handControllerGrab.js | 47 +++++++++++----------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index dc43b3f117..786ff33c82 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1589,31 +1589,32 @@ function MyController(hand) { ids.forEach(function(id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { - return; - } else if (props.boundingBox) { - var entityMinPoint = props.boundingBox.brn; - var entityMaxPoint = props.boundingBox.tfl; - var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); - var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); - - if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { - // we haven't been touched before, but either right or left is touching us now - _this.allTouchedIDs[id] = true; - _this.startTouch(id); - } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { - // we have been touched before and are still being touched - // continue touch - _this.continueTouch(id); - } else if (_this.allTouchedIDs[id]) { - delete _this.allTouchedIDs[id]; - _this.stopTouch(id); - - } else { - //we are in another state - return; - } + continue; } + if (!props || !props.boundingBox) { + continue; + } + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id]) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } }); }; From f6526272de23ddf57a6f62e544c646ff86d3f240 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Feb 2016 16:58:15 -0800 Subject: [PATCH 03/22] 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 04/22] 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 05/22] 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 06/22] 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 07/22] 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 08/22] 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 09/22] 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 10/22] 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 11/22] 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 12/22] 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 13/22] 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 14/22] 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; From 23b204c0c6390fd2e5a9d95a20649da7c0e6f6d5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 22 Feb 2016 19:03:12 -0800 Subject: [PATCH 15/22] fix logic that checks getEntityProperties return value --- examples/controllers/handControllerGrab.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 1aaf78f68d..1fd6045fe0 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1588,11 +1588,10 @@ function MyController(hand) { ids.forEach(function(id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); - if (props.name === 'pointer') { - continue; - } - if (!props || !props.boundingBox) { - continue; + if (!props || + !props.boundingBox || + props.name === 'pointer') { + return; } var entityMinPoint = props.boundingBox.brn; var entityMaxPoint = props.boundingBox.tfl; From 160a107bbd079af69a4b521afa550c68f4e07f05 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 19:36:00 -0800 Subject: [PATCH 16/22] Auto-unhide the desktop when showing or raising a window --- interface/resources/qml/desktop/Desktop.qml | 13 +++++++++++-- interface/src/Application.cpp | 9 ++++++++- interface/src/Application.h | 1 + libraries/ui/src/OffscreenUi.cpp | 5 +++++ libraries/ui/src/OffscreenUi.h | 3 +++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 0286c45ac3..e2aecdfd18 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -10,12 +10,19 @@ import "../js/Utils.js" as Utils // windows will be childed. FocusScope { id: desktop - anchors.fill: parent; objectName: "desktop" + // Allow the scale of the desktop to be changed without screwing up the size relative to the parent. + height: parent.height / scale + width: parent.width / scale + onHeightChanged: d.repositionAll(); onWidthChanged: d.repositionAll(); + // Controls and windows can trigger this signal to ensure the desktop becomes visible + // when they're opened. + signal showDesktop(); + // Allows QML/JS to find the desktop through the parent chain property bool desktopRoot: true @@ -217,6 +224,8 @@ FocusScope { } reposition(targetWindow); + + showDesktop(); } function reposition(item) { @@ -314,7 +323,7 @@ FocusScope { enabled: DebugQML onTriggered: focusDebugger.visible = !focusDebugger.visible } - + } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64cd586e13..704940433a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1198,7 +1198,8 @@ void Application::initializeUi() { // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // support the window management and scripting proxies for VR use offscreenUi->createDesktop(QString("hifi/Desktop.qml")); - + connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop); + // FIXME either expose so that dialogs can set this themselves or // do better detection in the offscreen UI of what has focus offscreenUi->setNavigationFocused(false); @@ -5128,3 +5129,9 @@ void Application::readArgumentsFromLocalSocket() { qApp->openUrl(QString::fromUtf8(message)); } } + +void Application::showDesktop() { + if (!_overlayConductor.getEnabled()) { + _overlayConductor.setEnabled(true); + } +} \ No newline at end of file diff --git a/interface/src/Application.h b/interface/src/Application.h index 96bafce23f..8cc2a33038 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -280,6 +280,7 @@ public slots: void runTests(); private slots: + void showDesktop(); void clearDomainOctreeDetails(); void idle(uint64_t now); void aboutToQuit(); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index fa40fedb9b..7e84836c86 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -112,6 +112,7 @@ void OffscreenUi::create(QOpenGLContext* context) { } void OffscreenUi::show(const QUrl& url, const QString& name, std::function f) { + emit showDesktop(); QQuickItem* item = getRootItem()->findChild(name); // First load? if (!item) { @@ -127,6 +128,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::functionfindChild(name); // Already loaded? if (item) { + emit showDesktop(); item->setVisible(!item->isVisible()); return; } @@ -134,6 +136,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::functionfindChild(name); if (item && !item->isVisible()) { + emit showDesktop(); item->setVisible(true); } } @@ -439,6 +442,8 @@ void OffscreenUi::createDesktop(const QUrl& url) { new VrMenu(this); new KeyboardFocusHack(); + + connect(_desktop, SIGNAL(showDesktop()), this, SLOT(showDesktop())); } QQuickItem* OffscreenUi::getDesktop() { diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index de479853f3..8b00180d43 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -106,6 +106,9 @@ public: // Compatibility with QInputDialog::getItem static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone); +signals: + void showDesktop(); + private: QString fileDialog(const QVariantMap& properties); From 749f4478ab174711cdde95d32384c45cb2a203f1 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 23 Feb 2016 09:33:37 -0800 Subject: [PATCH 17/22] Fixed bug with parsing numbers for editjs --- examples/html/entityProperties.html | 2 +- examples/particle_explorer/particleExplorerTool.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 67ed261b5d..e3ad77870d 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -75,7 +75,7 @@ function createEmitNumberPropertyUpdateFunction(propertyName) { return function() { EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":' + Number(this.value.toFixed(4)) + '}}' + '{ "type":"update", "properties":{"' + propertyName + '":' + parseFloat(this.value).toFixed(4) + '}}' ); }; } diff --git a/examples/particle_explorer/particleExplorerTool.js b/examples/particle_explorer/particleExplorerTool.js index 20dfa6f1ba..007eb717ec 100644 --- a/examples/particle_explorer/particleExplorerTool.js +++ b/examples/particle_explorer/particleExplorerTool.js @@ -32,11 +32,9 @@ ParticleExplorerTool = function() { that.destroyWebView = function() { if (!that.webView) { - print("EBL CAN'ZT CLOSE WEB VIEW- IT DOESNT EXISTS!") return; } - print("EBL CLOSING WEB VIEW") that.webView.close(); that.webView = null; that.activeParticleEntity = 0; From 1c53f9bc877f729c3d4783f3110160b0f42e73a7 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 23 Feb 2016 10:40:50 -0800 Subject: [PATCH 18/22] Fix the cleanup of the render::Item::ID in the EntityITem Rendereable wich were often not invalidated after beeing removed from the scene. THis caused a bug with particule system when beeing added /removed / updated quickly --- interface/src/avatar/Avatar.cpp | 3 ++- interface/src/ui/overlays/Overlay.cpp | 2 +- interface/src/ui/overlays/Overlays.cpp | 2 +- libraries/entities-renderer/src/RenderableEntityItem.h | 3 ++- .../entities-renderer/src/RenderableModelEntityItem.cpp | 1 + .../src/RenderableParticleEffectEntityItem.cpp | 6 ++++-- .../entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 1 + .../entities-renderer/src/RenderableZoneEntityItem.cpp | 3 ++- libraries/render/src/render/Item.h | 4 ++++ 9 files changed, 18 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f62eb5a070..efa6f6004b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -315,6 +315,7 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemID); + render::Item::clearID(_renderItemID); _skeletonModel.removeFromScene(scene, pendingChanges); getHead()->getFaceModel().removeFromScene(scene, pendingChanges); for (auto& attachmentModel : _attachmentModels) { @@ -323,7 +324,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr>(_renderItemID, [](render::Payload& p) {}); } } diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 1e3390e49f..64b5e2aedf 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -229,6 +229,6 @@ bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemID); - _renderItemID = render::Item::INVALID_ITEM_ID; + render::Item::clearID(_renderItemID); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index b53a5a0d05..c2b769d146 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -94,7 +94,7 @@ void Overlays::cleanupOverlaysToDelete() { Overlay::Pointer overlay = _overlaysToDelete.takeLast(); auto itemID = overlay->getRenderItemID(); - if (itemID != render::Item::INVALID_ITEM_ID) { + if (render::Item::isValidID(itemID)) { overlay->removeFromScene(overlay, scene, pendingChanges); } } while (!_overlaysToDelete.isEmpty()); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 7b3ea8edaa..30d3f9d83c 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -66,10 +66,11 @@ public: void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myItem); + render::Item::clearID(_myItem); } void notifyChanged() { - if (_myItem == render::Item::INVALID_ITEM_ID) { + if (!render::Item::isValidID(_myItem)) { return; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 89f819b0da..e3870705c9 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -251,6 +251,7 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myMetaItem); + render::Item::clearID(_myMetaItem); if (_model) { _model->removeFromScene(scene, pendingChanges); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e62dc82988..4d8eebf05b 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -179,6 +179,7 @@ void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemId); _scene = nullptr; + render::Item::clearID(_renderItemId); }; void RenderableParticleEffectEntityItem::update(const quint64& now) { @@ -199,7 +200,8 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { } void RenderableParticleEffectEntityItem::updateRenderItem() { - if (!_scene) { + // this 2 tests are synonyms for this class, but we would like to get rid of the _scene pointer ultimately + if (!_scene || !render::Item::isValidID(_renderItemId)) { return; } if (!getVisible()) { @@ -312,7 +314,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { } void RenderableParticleEffectEntityItem::notifyBoundChanged() { - if (_renderItemId == render::Item::INVALID_ITEM_ID) { + if (!render::Item::isValidID(_renderItemId)) { return; } render::PendingChanges pendingChanges; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 1029f3b3af..ef777df403 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -572,6 +572,7 @@ void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myItem); + render::Item::clearID(_myItem); } namespace render { diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 56771296db..44345ac0a2 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -230,6 +230,7 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myMetaItem); + render::Item::clearID(_myMetaItem); if (_model) { _model->removeFromScene(scene, pendingChanges); } @@ -237,7 +238,7 @@ void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shar void RenderableZoneEntityItem::notifyBoundChanged() { - if (_myMetaItem == render::Item::INVALID_ITEM_ID) { + if (!render::Item::isValidID(_myMetaItem)) { return; } render::PendingChanges pendingChanges; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 74c832a0c4..8aaaf07300 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -217,6 +217,10 @@ public: static const ID INVALID_ITEM_ID = 0; static const ItemCell INVALID_CELL = -1; + // Convenient function to clear an ID or check it s valid + static void clearID(ID& id) { id = INVALID_ITEM_ID; } + static bool isValidID(const ID id) { return id != INVALID_ITEM_ID; } + // Bound is the AABBox fully containing this item typedef AABox Bound; From 5d9ee84e6364a053c05275009fea50c98b69c7e2 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 23 Feb 2016 10:42:39 -0800 Subject: [PATCH 19/22] Extend the test for number of active injectors to apply to injector restarts. --- libraries/audio/src/AudioInjector.cpp | 8 ++++-- libraries/audio/src/AudioInjectorManager.cpp | 26 ++++++++++++++------ libraries/audio/src/AudioInjectorManager.h | 3 ++- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 157e973f5b..ad6b436d02 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -104,7 +104,9 @@ void AudioInjector::restart() { // reset state to start sending from beginning again _nextFrame = 0; - _frameTimer->invalidate(); + if (_frameTimer) { + _frameTimer->invalidate(); + } _hasSentFirstFrame = false; // check our state to decide if we need extra handling for the restart request @@ -122,7 +124,9 @@ void AudioInjector::restart() { injectLocally(); } else { // wake the AudioInjectorManager back up if it's stuck waiting - injectorManager->restartFinishedInjector(this); + if (!injectorManager->restartFinishedInjector(this)) { + _state = State::Finished; // we're not playing, so reset the state used by isPlaying. + } } } } diff --git a/libraries/audio/src/AudioInjectorManager.cpp b/libraries/audio/src/AudioInjectorManager.cpp index 032ad71145..0c060d30ad 100644 --- a/libraries/audio/src/AudioInjectorManager.cpp +++ b/libraries/audio/src/AudioInjectorManager.cpp @@ -129,6 +129,16 @@ void AudioInjectorManager::run() { static const int MAX_INJECTORS_PER_THREAD = 40; // calculated based on AudioInjector time to send frame, with sufficient padding +bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a lock. + if (_injectors.size() >= MAX_INJECTORS_PER_THREAD) { + qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of" + << MAX_INJECTORS_PER_THREAD << "current audio injectors."; + return true; + } + qDebug() << "current injectors:" << _injectors.size(); + return false; +} + bool AudioInjectorManager::threadInjector(AudioInjector* injector) { if (_shouldStop) { qDebug() << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down."; @@ -138,8 +148,9 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) { // guard the injectors vector with a mutex Lock lock(_injectorsMutex); - // check if we'll be able to thread this injector (do we have < max concurrent injectors) - if (_injectors.size() < MAX_INJECTORS_PER_THREAD) { + if (wouldExceedLimits()) { + return false; + } else { if (!_thread) { createThread(); } @@ -156,23 +167,22 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) { _injectorReady.notify_one(); return true; - } else { - // unable to thread this injector, at the max - qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of" - << MAX_INJECTORS_PER_THREAD << "current audio injectors."; - return false; } } -void AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) { +bool AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) { if (!_shouldStop) { // guard the injectors vector with a mutex Lock lock(_injectorsMutex); + if (wouldExceedLimits()) { + return false; + } // add the injector to the queue with a send timestamp of now _injectors.emplace(usecTimestampNow(), InjectorQPointer { injector }); // notify our wait condition so we can inject two frames for this injector immediately _injectorReady.notify_one(); } + return true; } diff --git a/libraries/audio/src/AudioInjectorManager.h b/libraries/audio/src/AudioInjectorManager.h index 91648fff39..de5537856e 100644 --- a/libraries/audio/src/AudioInjectorManager.h +++ b/libraries/audio/src/AudioInjectorManager.h @@ -50,8 +50,9 @@ private: using Lock = std::unique_lock; bool threadInjector(AudioInjector* injector); - void restartFinishedInjector(AudioInjector* injector); + bool restartFinishedInjector(AudioInjector* injector); void notifyInjectorReadyCondition() { _injectorReady.notify_one(); } + bool wouldExceedLimits(); AudioInjectorManager() {}; AudioInjectorManager(const AudioInjectorManager&) = delete; From 7e39cc7753a7cfc3d15a887ccc7350b60c0e399e Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 23 Feb 2016 10:53:33 -0800 Subject: [PATCH 20/22] clean up a bit the 2 globals RenderItem in APplication.cpp --- interface/src/Application.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 704940433a..89ec196fad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3773,8 +3773,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se // The pending changes collecting the changes here render::PendingChanges pendingChanges; + // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities // Background rendering decision - if (BackgroundRenderData::_item == 0) { + if (!render::Item::isValidID(BackgroundRenderData::_item)) { auto backgroundRenderData = make_shared(); auto backgroundRenderPayload = make_shared(backgroundRenderData); BackgroundRenderData::_item = _main3DScene->allocateID(); @@ -3799,8 +3800,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se } } + // FIXME: Move this out of here!, WorldBox should be driven by the entity content just like the other entities // Make sure the WorldBox is in the scene - if (WorldBoxRenderData::_item == 0) { + if (!render::Item::isValidID(WorldBoxRenderData::_item)) { auto worldBoxRenderData = make_shared(); auto worldBoxRenderPayload = make_shared(worldBoxRenderData); From 6a987391d2d0f46682e29c912b75256755b55695 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 23 Feb 2016 10:55:36 -0800 Subject: [PATCH 21/22] Remove debugging code. --- libraries/audio/src/AudioInjectorManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/audio/src/AudioInjectorManager.cpp b/libraries/audio/src/AudioInjectorManager.cpp index 0c060d30ad..b39da1c148 100644 --- a/libraries/audio/src/AudioInjectorManager.cpp +++ b/libraries/audio/src/AudioInjectorManager.cpp @@ -135,7 +135,6 @@ bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a << MAX_INJECTORS_PER_THREAD << "current audio injectors."; return true; } - qDebug() << "current injectors:" << _injectors.size(); return false; } From d3cdc5117f27be74ef52999b18adb672a3630e4b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 23 Feb 2016 11:01:57 -0800 Subject: [PATCH 22/22] clean up one more render::Item::isValid(ID) --- interface/src/ui/overlays/Overlays.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c2b769d146..2bc1286419 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -241,7 +241,7 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { render::ItemKey itemKey = render::payloadGetKey(thisOverlay); if (itemKey != oldItemKey) { auto itemID = thisOverlay->getRenderItemID(); - if (itemID != render::Item::INVALID_ITEM_ID) { + if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); render::PendingChanges pendingChanges; pendingChanges.resortItem(itemID, oldItemKey, itemKey);