From ff2800e8d587fabc566cde169226ad0d1bc7ca54 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 11:49:48 -0700 Subject: [PATCH 1/9] Add isReplicant to Node --- domain-server/src/DomainServer.cpp | 5 +++++ libraries/networking/src/Node.cpp | 2 ++ libraries/networking/src/Node.h | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index d637a20454..c9005c42e4 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2211,6 +2211,11 @@ void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& } void DomainServer::nodeAdded(SharedNodePointer node) { + // TODO Check to see if node is in list of replicant nodes + if (node->getType() == NodeType::Agent) { + node->setIsReplicant(true); + } + // we don't use updateNodeWithData, so add the DomainServerNodeData to the node here node->setLinkedData(std::unique_ptr { new DomainServerNodeData() }); } diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 60227eeaa1..baad621cd6 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -135,6 +135,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) { out << node._publicSocket; out << node._localSocket; out << node._permissions; + out << node._isReplicant; return out; } @@ -144,6 +145,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) { in >> node._publicSocket; in >> node._localSocket; in >> node._permissions; + in >> node._isReplicant; return in; } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index f7afbdd864..2c8270071c 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -48,6 +48,9 @@ public: char getType() const { return _type; } void setType(char type); + bool isReplicant() const { return _isReplicant; } + void setIsReplicant(bool isReplicant) { _isReplicant = isReplicant; } + const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } @@ -89,6 +92,7 @@ private: Node& operator=(Node otherNode); NodeType_t _type; + bool _isReplicant { false }; QUuid _connectionSecret; std::unique_ptr _linkedData; From 2ff065f75164fdbe1d833103622ef93051dda6c7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 12:11:16 -0700 Subject: [PATCH 2/9] Add isReplicant to node list packet processing --- libraries/networking/src/LimitedNodeList.cpp | 4 +++- libraries/networking/src/LimitedNodeList.h | 2 +- libraries/networking/src/Node.cpp | 5 +++-- libraries/networking/src/Node.h | 4 ++-- libraries/networking/src/NodeList.cpp | 5 +++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index f9baff0daf..43b1602483 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -569,6 +569,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) { SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, const NodePermissions& permissions, + bool isReplicant, const QUuid& connectionSecret) { QReadLocker readLocker(&_nodeMutex); NodeHash::const_iterator it = _nodeHash.find(uuid); @@ -580,11 +581,12 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t matchingNode->setLocalSocket(localSocket); matchingNode->setPermissions(permissions); matchingNode->setConnectionSecret(connectionSecret); + matchingNode->setIsReplicant(isReplicant); return matchingNode; } else { // we didn't have this node, so add them - Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, connectionSecret); + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, isReplicant, connectionSecret, this); if (nodeType == NodeType::AudioMixer) { LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 72fc652733..4bc9134a73 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -146,7 +146,7 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, const NodePermissions& permissions = DEFAULT_AGENT_PERMISSIONS, - const QUuid& connectionSecret = QUuid()); + bool isReplicant = false, const QUuid& connectionSecret = QUuid()); static bool parseSTUNResponse(udt::BasePacket* packet, QHostAddress& newPublicAddress, uint16_t& newPublicPort); bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; } diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index baad621cd6..8972f68d2a 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -51,11 +51,12 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) { } Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, - const HifiSockAddr& localSocket, const NodePermissions& permissions, const QUuid& connectionSecret, - QObject* parent) : + const HifiSockAddr& localSocket, const NodePermissions& permissions, bool isReplicant, + const QUuid& connectionSecret, QObject* parent) : NetworkPeer(uuid, publicSocket, localSocket, parent), _type(type), _connectionSecret(connectionSecret), + _isReplicant(isReplicant), _pingMs(-1), // "Uninitialized" _clockSkewUsec(0), _mutex(), diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 2c8270071c..8a2129f6f1 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -39,8 +39,8 @@ class Node : public NetworkPeer { public: Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - const NodePermissions& permissions, const QUuid& connectionSecret = QUuid(), - QObject* parent = nullptr); + const NodePermissions& permissions, bool isReplicant, const QUuid& connectionSecret = QUuid(), + QObject* parent = 0); bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } bool operator!=(const Node& otherNode) const { return !(*this == otherNode); } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 2aa30b84aa..6710f3ffa3 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -654,8 +654,9 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket, nodeLocalSocket; NodePermissions permissions; + bool isReplicant; - packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions; + packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions >> isReplicant; // if the public socket address is 0 then it's reachable at the same IP // as the domain server @@ -666,7 +667,7 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { packetStream >> connectionUUID; SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, - nodeLocalSocket, permissions, connectionUUID); + nodeLocalSocket, permissions, isReplicant, connectionUUID); } void NodeList::sendAssignment(Assignment& assignment) { From 84e1a6f89388d797492fea97b8f966156a48a394 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 13:02:54 -0700 Subject: [PATCH 3/9] Rename isReplicant to isReplicated --- domain-server/src/DomainServer.cpp | 4 ++-- libraries/networking/src/LimitedNodeList.cpp | 6 +++--- libraries/networking/src/LimitedNodeList.h | 2 +- libraries/networking/src/Node.cpp | 8 ++++---- libraries/networking/src/Node.h | 8 ++++---- libraries/networking/src/NodeList.cpp | 8 +++++--- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c9005c42e4..de53898057 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2211,9 +2211,9 @@ void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& } void DomainServer::nodeAdded(SharedNodePointer node) { - // TODO Check to see if node is in list of replicant nodes + // TODO Check to see if node is in list of replicated nodes if (node->getType() == NodeType::Agent) { - node->setIsReplicant(true); + node->setIsReplicated(true); } // we don't use updateNodeWithData, so add the DomainServerNodeData to the node here diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 43b1602483..7aa17ebf04 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -569,7 +569,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) { SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, const NodePermissions& permissions, - bool isReplicant, + bool isReplicated, const QUuid& connectionSecret) { QReadLocker readLocker(&_nodeMutex); NodeHash::const_iterator it = _nodeHash.find(uuid); @@ -581,12 +581,12 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t matchingNode->setLocalSocket(localSocket); matchingNode->setPermissions(permissions); matchingNode->setConnectionSecret(connectionSecret); - matchingNode->setIsReplicant(isReplicant); + matchingNode->setIsReplicated(isReplicated); return matchingNode; } else { // we didn't have this node, so add them - Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, isReplicant, connectionSecret, this); + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, isReplicated, connectionSecret, this); if (nodeType == NodeType::AudioMixer) { LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 4bc9134a73..1ace6b2e23 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -146,7 +146,7 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, const NodePermissions& permissions = DEFAULT_AGENT_PERMISSIONS, - bool isReplicant = false, const QUuid& connectionSecret = QUuid()); + bool isReplicated = false, const QUuid& connectionSecret = QUuid()); static bool parseSTUNResponse(udt::BasePacket* packet, QHostAddress& newPublicAddress, uint16_t& newPublicPort); bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; } diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 8972f68d2a..49f032b823 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -51,12 +51,12 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) { } Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, - const HifiSockAddr& localSocket, const NodePermissions& permissions, bool isReplicant, + const HifiSockAddr& localSocket, const NodePermissions& permissions, bool isReplicated, const QUuid& connectionSecret, QObject* parent) : NetworkPeer(uuid, publicSocket, localSocket, parent), _type(type), _connectionSecret(connectionSecret), - _isReplicant(isReplicant), + _isReplicated(isReplicated), _pingMs(-1), // "Uninitialized" _clockSkewUsec(0), _mutex(), @@ -136,7 +136,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) { out << node._publicSocket; out << node._localSocket; out << node._permissions; - out << node._isReplicant; + out << node._isReplicated; return out; } @@ -146,7 +146,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) { in >> node._publicSocket; in >> node._localSocket; in >> node._permissions; - in >> node._isReplicant; + in >> node._isReplicated; return in; } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 8a2129f6f1..73c8538304 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -39,7 +39,7 @@ class Node : public NetworkPeer { public: Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - const NodePermissions& permissions, bool isReplicant, const QUuid& connectionSecret = QUuid(), + const NodePermissions& permissions, bool isReplicated, const QUuid& connectionSecret = QUuid(), QObject* parent = 0); bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } @@ -48,8 +48,8 @@ public: char getType() const { return _type; } void setType(char type); - bool isReplicant() const { return _isReplicant; } - void setIsReplicant(bool isReplicant) { _isReplicant = isReplicant; } + bool isReplicated() const { return _isReplicated; } + void setIsReplicated(bool isReplicated) { _isReplicated = isReplicated; } const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } @@ -92,7 +92,7 @@ private: Node& operator=(Node otherNode); NodeType_t _type; - bool _isReplicant { false }; + bool _isReplicated { false }; QUuid _connectionSecret; std::unique_ptr _linkedData; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 6710f3ffa3..c38a9470b1 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -654,9 +654,11 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket, nodeLocalSocket; NodePermissions permissions; - bool isReplicant; + bool isReplicated; - packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions >> isReplicant; + packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions >> isReplicated; + + qDebug() << "Node: " << nodeUUID << nodeType << isReplicated; // if the public socket address is 0 then it's reachable at the same IP // as the domain server @@ -667,7 +669,7 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { packetStream >> connectionUUID; SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, - nodeLocalSocket, permissions, isReplicant, connectionUUID); + nodeLocalSocket, permissions, isReplicated, connectionUUID); } void NodeList::sendAssignment(Assignment& assignment) { From 3142842d5d8a60a6863a35349f7ea410fba94e03 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 14:51:08 -0700 Subject: [PATCH 4/9] Fix Node initialization warnings --- libraries/networking/src/Node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 73c8538304..2ae0ab82e9 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -92,7 +92,6 @@ private: Node& operator=(Node otherNode); NodeType_t _type; - bool _isReplicated { false }; QUuid _connectionSecret; std::unique_ptr _linkedData; @@ -101,6 +100,7 @@ private: QMutex _mutex; MovingPercentile _clockSkewMovingPercentile; NodePermissions _permissions; + bool _isReplicated { false }; tbb::concurrent_unordered_set _ignoredNodeIDSet; mutable QReadWriteLock _ignoredNodeIDSetLock; From 4851d3b56409bef465365a552858ea8746992ade Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 14:52:02 -0700 Subject: [PATCH 5/9] Remove superfluous node log --- libraries/networking/src/NodeList.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index c38a9470b1..9b7a7c91dd 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -658,8 +658,6 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> permissions >> isReplicated; - qDebug() << "Node: " << nodeUUID << nodeType << isReplicated; - // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.getAddress().isNull()) { From 3b3465ea05e76dc9accf09b02bff54937ff44cef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 14:59:45 -0700 Subject: [PATCH 6/9] Add isUpstream to Node --- assignment-client/src/audio/AudioMixerSlave.cpp | 4 ++++ libraries/networking/src/Node.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index d01d961e33..2d800c3561 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -74,6 +74,10 @@ void AudioMixerSlave::mix(const SharedNodePointer& node) { return; } + if (node->isUpstream()) { + return; + } + // check that the stream is valid auto avatarStream = data->getAvatarAudioStream(); if (avatarStream == nullptr) { diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 2ae0ab82e9..6d74cf4a26 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -51,6 +51,9 @@ public: bool isReplicated() const { return _isReplicated; } void setIsReplicated(bool isReplicated) { _isReplicated = isReplicated; } + bool isUpstream() const { return _isUpstream; } + void setIsUpstream(bool isUpstream) { _isUpstream = isUpstream; } + const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } @@ -101,6 +104,7 @@ private: MovingPercentile _clockSkewMovingPercentile; NodePermissions _permissions; bool _isReplicated { false }; + bool _isUpstream { false }; tbb::concurrent_unordered_set _ignoredNodeIDSet; mutable QReadWriteLock _ignoredNodeIDSetLock; From efdd3060b0cd16c998447770828970c48d42731c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 15:00:03 -0700 Subject: [PATCH 7/9] Set isUpstream when receiving a replicated audio packet --- assignment-client/src/audio/AudioMixer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 8f8a6ff2c0..1246617540 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -122,6 +122,7 @@ void AudioMixer::queueReplicatedAudioPacket(QSharedPointer mess auto node = nodeList->addOrUpdateNode(nodeID, NodeType::Agent, message->getSenderSockAddr(), message->getSenderSockAddr()); + node->setIsUpstream(true); node->setIsMirror(true); node->setLastHeardMicrostamp(usecTimestampNow()); From eb2a41744826a84718cb7769a07fa4d612f8e8bf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 15:24:14 -0700 Subject: [PATCH 8/9] Add parent back to Node ctor --- libraries/networking/src/LimitedNodeList.cpp | 2 +- libraries/networking/src/Node.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 7aa17ebf04..7b0b2d5bc5 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -586,7 +586,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t return matchingNode; } else { // we didn't have this node, so add them - Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, isReplicated, connectionSecret, this); + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, isReplicated, connectionSecret); if (nodeType == NodeType::AudioMixer) { LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer); diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 6d74cf4a26..9082deb55b 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -40,7 +40,7 @@ public: Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, const NodePermissions& permissions, bool isReplicated, const QUuid& connectionSecret = QUuid(), - QObject* parent = 0); + QObject* parent = nullptr); bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } bool operator!=(const Node& otherNode) const { return !(*this == otherNode); } From a1d3c0dc7b86b82bf25c2bfa23de40b3674c032a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jun 2017 15:27:24 -0700 Subject: [PATCH 9/9] Fix initialization ordering error in Node --- libraries/networking/src/Node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 9082deb55b..11f88b0f52 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -98,12 +98,12 @@ private: QUuid _connectionSecret; std::unique_ptr _linkedData; + bool _isReplicated { false }; int _pingMs; qint64 _clockSkewUsec; QMutex _mutex; MovingPercentile _clockSkewMovingPercentile; NodePermissions _permissions; - bool _isReplicated { false }; bool _isUpstream { false }; tbb::concurrent_unordered_set _ignoredNodeIDSet; mutable QReadWriteLock _ignoredNodeIDSetLock;