Merge pull request #13216 from birarda/bug/domain-ice-peer-id

never re-use node ID during domain connection
This commit is contained in:
John Conklin II 2018-05-24 14:09:39 -07:00 committed by GitHub
commit c89c70fbaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 28 deletions

View file

@ -479,7 +479,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
limitedNodeList->killNodeWithUUID(existingNodeID); limitedNodeList->killNodeWithUUID(existingNodeID);
} }
// add the connecting node (or re-use the matched one from eachNodeBreakable above) // add the connecting node
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection);
// set the edit rights for this user // set the edit rights for this user
@ -508,25 +508,21 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
return newNode; return newNode;
} }
SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection, SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) {
QUuid nodeID) {
HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr; HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr;
SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID); SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID);
if (connectedPeer) { if (connectedPeer && connectedPeer->getActiveSocket()) {
// 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 // set their discovered socket to whatever the activated socket on the network peer object was
discoveredSocket = *connectedPeer->getActiveSocket(); discoveredSocket = *connectedPeer->getActiveSocket();
} }
} else {
// we got a connectUUID we didn't recognize, either use the hinted node ID or randomly generate a new one // create a new node ID for the verified connecting node
if (nodeID.isNull()) { auto nodeID = QUuid::createUuid();
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<LimitedNodeList>(); auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
@ -541,6 +537,15 @@ SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const Node
return newNode; 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, bool DomainGatekeeper::verifyUserSignature(const QString& username,
const QByteArray& usernameSignature, const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr) { const HifiSockAddr& senderSockAddr) {

View file

@ -40,7 +40,7 @@ public:
const QUuid& walletUUID, const QString& nodeVersion); const QUuid& walletUUID, const QString& nodeVersion);
QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID); QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID);
void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); } void cleanupICEPeerForNode(const QUuid& nodeID);
Node::LocalID findOrCreateLocalID(const QUuid& uuid); Node::LocalID findOrCreateLocalID(const QUuid& uuid);
@ -77,8 +77,7 @@ private:
SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection, SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection,
const QString& username, const QString& username,
const QByteArray& usernameSignature); const QByteArray& usernameSignature);
SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection, SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection);
QUuid nodeID = QUuid());
bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature, bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr); const HifiSockAddr& senderSockAddr);
@ -102,6 +101,10 @@ private:
QHash<QUuid, SharedNetworkPeer> _icePeers; QHash<QUuid, SharedNetworkPeer> _icePeers;
using ConnectingNodeID = QUuid;
using ICEPeerID = QUuid;
QHash<ConnectingNodeID, ICEPeerID> _nodeToICEPeerIDs;
QHash<QString, QUuid> _connectionTokenHash; QHash<QString, QUuid> _connectionTokenHash;
// the word "optimistic" below is used for keys that we request during user connection before the user has // the word "optimistic" below is used for keys that we request during user connection before the user has

View file

@ -1017,15 +1017,22 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
sendingNode->setPublicSocket(nodeRequestData.publicSockAddr); sendingNode->setPublicSocket(nodeRequestData.publicSockAddr);
sendingNode->setLocalSocket(nodeRequestData.localSockAddr); sendingNode->setLocalSocket(nodeRequestData.localSockAddr);
// update the NodeInterestSet in case there have been any changes
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(sendingNode->getLinkedData()); DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(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 // guard against patched agents asking to hear about other agents
auto safeInterestSet = nodeRequestData.interestList.toSet(); auto safeInterestSet = nodeRequestData.interestList.toSet();
if (sendingNode->getType() == NodeType::Agent) { if (sendingNode->getType() == NodeType::Agent) {
safeInterestSet.remove(NodeType::Agent); safeInterestSet.remove(NodeType::Agent);
} }
// update the NodeInterestSet in case there have been any changes
nodeData->setNodeInterestSet(safeInterestSet); nodeData->setNodeInterestSet(safeInterestSet);
// update the connecting hostname in case it has changed // update the connecting hostname in case it has changed
@ -2945,7 +2952,7 @@ void DomainServer::nodeAdded(SharedNodePointer node) {
void DomainServer::nodeKilled(SharedNodePointer node) { void DomainServer::nodeKilled(SharedNodePointer node) {
// if this peer connected via ICE then remove them from our ICE peers hash // 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<DomainServerNodeData*>(node->getLinkedData()); DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
@ -2978,6 +2985,8 @@ void DomainServer::nodeKilled(SharedNodePointer node) {
} }
} }
} }
broadcastNodeDisconnect(node);
} }
SharedAssignmentPointer DomainServer::dequeueMatchingAssignment(const QUuid& assignmentUUID, NodeType_t nodeType) { SharedAssignmentPointer DomainServer::dequeueMatchingAssignment(const QUuid& assignmentUUID, NodeType_t nodeType) {
@ -3163,18 +3172,23 @@ void DomainServer::handleKillNode(SharedNodePointer nodeToKill) {
const QUuid& nodeUUID = nodeToKill->getUUID(); const QUuid& nodeUUID = nodeToKill->getUUID();
limitedNodeList->killNodeWithUUID(nodeUUID); limitedNodeList->killNodeWithUUID(nodeUUID);
}
static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID); void DomainServer::broadcastNodeDisconnect(const SharedNodePointer& disconnectedNode) {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID, true);
removedNodePacket->reset(); removedNodePacket->reset();
removedNodePacket->write(nodeUUID.toRfc4122()); removedNodePacket->write(disconnectedNode->getUUID().toRfc4122());
// broadcast out the DomainServerRemovedNode message // 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 // 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](const SharedNodePointer& otherNode){
limitedNodeList->sendUnreliablePacket(*removedNodePacket, *otherNode); auto removedNodePacketCopy = NLPacket::createCopy(*removedNodePacket);
limitedNodeList->sendPacket(std::move(removedNodePacketCopy), *otherNode);
}); });
} }

View file

@ -165,6 +165,7 @@ private:
unsigned int countConnectedUsers(); unsigned int countConnectedUsers();
void handleKillNode(SharedNodePointer nodeToKill); void handleKillNode(SharedNodePointer nodeToKill);
void broadcastNodeDisconnect(const SharedNodePointer& disconnnectedNode);
void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr); void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr);

View file

@ -67,9 +67,12 @@ public:
const QString& getPlaceName() { return _placeName; } const QString& getPlaceName() { return _placeName; }
void setPlaceName(const QString& placeName) { _placeName = placeName; } void setPlaceName(const QString& placeName) { _placeName = placeName; }
bool wasAssigned() const { return _wasAssigned; }; bool wasAssigned() const { return _wasAssigned; }
void setWasAssigned(bool wasAssigned) { _wasAssigned = wasAssigned; } void setWasAssigned(bool wasAssigned) { _wasAssigned = wasAssigned; }
bool hasCheckedIn() const { return _hasCheckedIn; }
void setHasCheckedIn(bool hasCheckedIn) { _hasCheckedIn = hasCheckedIn; }
private: private:
QJsonObject overrideValuesIfNeeded(const QJsonObject& newStats); QJsonObject overrideValuesIfNeeded(const QJsonObject& newStats);
QJsonArray overrideValuesIfNeeded(const QJsonArray& newStats); QJsonArray overrideValuesIfNeeded(const QJsonArray& newStats);
@ -94,6 +97,8 @@ private:
QString _placeName; QString _placeName;
bool _wasAssigned { false }; bool _wasAssigned { false };
bool _hasCheckedIn { false };
}; };
#endif // hifi_DomainServerNodeData_h #endif // hifi_DomainServerNodeData_h