diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index a3692c974e..62f56184f4 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -435,8 +435,29 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect return SharedNodePointer(); } + QUuid hintNodeID; + + // in case this is a node that's failing to connect + // double check we don't have the same node whose sockets match exactly already in the list + limitedNodeList->eachNodeBreakable([&](const SharedNodePointer& node){ + if (node->getPublicSocket() == nodeConnection.publicSockAddr && node->getLocalSocket() == nodeConnection.localSockAddr) { + // we have a node that already has these exact sockets - this can occur if a node + // is failing to connect to the domain + + // we'll re-use the existing node ID + // as long as the user hasn't changed their username (by logging in or logging out) + auto existingNodeData = static_cast<DomainServerNodeData*>(node->getLinkedData()); + + if (existingNodeData->getUsername() == username) { + hintNodeID = node->getUUID(); + return false; + } + } + return true; + }); + // add the connecting node (or re-use the matched one from eachNodeBreakable above) - SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); + SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection, hintNodeID); // set the edit rights for this user newNode->setPermissions(userPerms); @@ -464,12 +485,11 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect return newNode; } -SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) { +SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection, + QUuid nodeID) { HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr; SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID); - QUuid nodeID; - if (connectedPeer) { // this user negotiated a connection with us via ICE, so re-use their ICE client ID nodeID = nodeConnection.connectUUID; @@ -479,8 +499,10 @@ SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const Node discoveredSocket = *connectedPeer->getActiveSocket(); } } else { - // we got a connectUUID we didn't recognize, randomly generate a new one - nodeID = QUuid::createUuid(); + // 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(); + } } auto limitedNodeList = DependencyManager::get<LimitedNodeList>(); diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index e2d36c4cea..163f255411 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -76,7 +76,8 @@ private: SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection, const QString& username, const QByteArray& usernameSignature); - SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection); + SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection, + QUuid nodeID = QUuid()); bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr);