diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index cad6d40b49..aa1c59a86b 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC67-v4.zip - URL_MD5 ba32aed18bfeaac4ccaf5ebb8ea3e804 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC68.zip + URL_MD5 a068f74d4045e257cfa7926fe6e38ad5 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index d78f0aaeb3..47b55bb5c2 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -479,7 +479,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect limitedNodeList->killNodeWithUUID(existingNodeID); } - // add the connecting node (or re-use the matched one from eachNodeBreakable above) + // add the connecting node SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); // set the edit rights for this user @@ -508,26 +508,22 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect return newNode; } -SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection, - QUuid nodeID) { +SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) { HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr; SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID); - if (connectedPeer) { - // this user negotiated a connection with us via ICE, so re-use their ICE client ID - nodeID = nodeConnection.connectUUID; - - if (connectedPeer->getActiveSocket()) { - // set their discovered socket to whatever the activated socket on the network peer object was - discoveredSocket = *connectedPeer->getActiveSocket(); - } - } else { - // we got a connectUUID we didn't recognize, either use the hinted node ID or randomly generate a new one - if (nodeID.isNull()) { - nodeID = QUuid::createUuid(); - } + if (connectedPeer && connectedPeer->getActiveSocket()) { + // set their discovered socket to whatever the activated socket on the network peer object was + discoveredSocket = *connectedPeer->getActiveSocket(); } + // create a new node ID for the verified connecting node + auto nodeID = QUuid::createUuid(); + + // add a mapping from connection node ID to ICE peer ID + // so that we can remove the ICE peer once we see this node connect + _nodeToICEPeerIDs.insert(nodeID, nodeConnection.connectUUID); + auto limitedNodeList = DependencyManager::get(); Node::LocalID newLocalID = findOrCreateLocalID(nodeID); @@ -541,6 +537,15 @@ SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const Node return newNode; } +void DomainGatekeeper::cleanupICEPeerForNode(const QUuid& nodeID) { + // remove this node ID from our node to ICE peer ID map + // and the associated ICE peer (if it still exists) + auto icePeerID = _nodeToICEPeerIDs.take(nodeID); + if (!icePeerID.isNull()) { + _icePeers.remove(icePeerID); + } +} + bool DomainGatekeeper::verifyUserSignature(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr) { diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 8402e58559..2cb9b4c8a9 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -39,8 +39,8 @@ public: void addPendingAssignedNode(const QUuid& nodeUUID, const QUuid& assignmentUUID, const QUuid& walletUUID, const QString& nodeVersion); QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID); - - void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); } + + void cleanupICEPeerForNode(const QUuid& nodeID); Node::LocalID findOrCreateLocalID(const QUuid& uuid); @@ -77,8 +77,7 @@ private: SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection, const QString& username, const QByteArray& usernameSignature); - SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection, - QUuid nodeID = QUuid()); + SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection); bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr); @@ -101,6 +100,10 @@ private: std::unordered_map _pendingAssignedNodes; QHash _icePeers; + + using ConnectingNodeID = QUuid; + using ICEPeerID = QUuid; + QHash _nodeToICEPeerIDs; QHash _connectionTokenHash; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index baeac043e4..4e65df495c 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1017,15 +1017,22 @@ void DomainServer::processListRequestPacket(QSharedPointer mess sendingNode->setPublicSocket(nodeRequestData.publicSockAddr); sendingNode->setLocalSocket(nodeRequestData.localSockAddr); - // update the NodeInterestSet in case there have been any changes DomainServerNodeData* nodeData = static_cast(sendingNode->getLinkedData()); + if (!nodeData->hasCheckedIn()) { + nodeData->setHasCheckedIn(true); + + // on first check in, make sure we've cleaned up any ICE peer for this node + _gatekeeper.cleanupICEPeerForNode(sendingNode->getUUID()); + } + // guard against patched agents asking to hear about other agents auto safeInterestSet = nodeRequestData.interestList.toSet(); if (sendingNode->getType() == NodeType::Agent) { safeInterestSet.remove(NodeType::Agent); } + // update the NodeInterestSet in case there have been any changes nodeData->setNodeInterestSet(safeInterestSet); // update the connecting hostname in case it has changed @@ -2945,7 +2952,7 @@ void DomainServer::nodeAdded(SharedNodePointer node) { void DomainServer::nodeKilled(SharedNodePointer node) { // if this peer connected via ICE then remove them from our ICE peers hash - _gatekeeper.removeICEPeer(node->getUUID()); + _gatekeeper.cleanupICEPeerForNode(node->getUUID()); DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); @@ -2978,6 +2985,8 @@ void DomainServer::nodeKilled(SharedNodePointer node) { } } } + + broadcastNodeDisconnect(node); } SharedAssignmentPointer DomainServer::dequeueMatchingAssignment(const QUuid& assignmentUUID, NodeType_t nodeType) { @@ -3163,18 +3172,23 @@ void DomainServer::handleKillNode(SharedNodePointer nodeToKill) { const QUuid& nodeUUID = nodeToKill->getUUID(); limitedNodeList->killNodeWithUUID(nodeUUID); +} - static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID); +void DomainServer::broadcastNodeDisconnect(const SharedNodePointer& disconnectedNode) { + auto limitedNodeList = DependencyManager::get(); + + static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID, true); removedNodePacket->reset(); - removedNodePacket->write(nodeUUID.toRfc4122()); + removedNodePacket->write(disconnectedNode->getUUID().toRfc4122()); // broadcast out the DomainServerRemovedNode message - limitedNodeList->eachMatchingNode([this, &nodeToKill](const SharedNodePointer& otherNode) -> bool { + limitedNodeList->eachMatchingNode([this, &disconnectedNode](const SharedNodePointer& otherNode) -> bool { // only send the removed node packet to nodes that care about the type of node this was - return isInInterestSet(otherNode, nodeToKill); + return isInInterestSet(otherNode, disconnectedNode); }, [&limitedNodeList](const SharedNodePointer& otherNode){ - limitedNodeList->sendUnreliablePacket(*removedNodePacket, *otherNode); + auto removedNodePacketCopy = NLPacket::createCopy(*removedNodePacket); + limitedNodeList->sendPacket(std::move(removedNodePacketCopy), *otherNode); }); } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index b118008d3d..01adbd99a9 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -165,6 +165,7 @@ private: unsigned int countConnectedUsers(); void handleKillNode(SharedNodePointer nodeToKill); + void broadcastNodeDisconnect(const SharedNodePointer& disconnnectedNode); void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr); diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index 6b8e9a1718..f465cceb96 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -67,8 +67,11 @@ public: const QString& getPlaceName() { return _placeName; } void setPlaceName(const QString& placeName) { _placeName = placeName; } - bool wasAssigned() const { return _wasAssigned; }; + bool wasAssigned() const { return _wasAssigned; } void setWasAssigned(bool wasAssigned) { _wasAssigned = wasAssigned; } + + bool hasCheckedIn() const { return _hasCheckedIn; } + void setHasCheckedIn(bool hasCheckedIn) { _hasCheckedIn = hasCheckedIn; } private: QJsonObject overrideValuesIfNeeded(const QJsonObject& newStats); @@ -94,6 +97,8 @@ private: QString _placeName; bool _wasAssigned { false }; + + bool _hasCheckedIn { false }; }; #endif // hifi_DomainServerNodeData_h