mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 11:17:32 +02:00
Merge pull request #12786 from huffman/fix/node-list-connections
Fix avatars not coming back when briefly disconnected from avatar mixer
This commit is contained in:
commit
92bf99f436
6 changed files with 64 additions and 16 deletions
|
@ -451,11 +451,12 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
||||||
return SharedNodePointer();
|
return SharedNodePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid hintNodeID;
|
QUuid existingNodeID;
|
||||||
|
|
||||||
// in case this is a node that's failing to connect
|
// 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
|
// double check we don't have the same node whose sockets match exactly already in the list
|
||||||
limitedNodeList->eachNodeBreakable([&](const SharedNodePointer& node){
|
limitedNodeList->eachNodeBreakable([&](const SharedNodePointer& node){
|
||||||
|
|
||||||
if (node->getPublicSocket() == nodeConnection.publicSockAddr && node->getLocalSocket() == nodeConnection.localSockAddr) {
|
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
|
// we have a node that already has these exact sockets - this can occur if a node
|
||||||
// is failing to connect to the domain
|
// is failing to connect to the domain
|
||||||
|
@ -465,15 +466,20 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
||||||
auto existingNodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
|
auto existingNodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||||
|
|
||||||
if (existingNodeData->getUsername() == username) {
|
if (existingNodeData->getUsername() == username) {
|
||||||
hintNodeID = node->getUUID();
|
qDebug() << "Deleting existing connection from same sockaddr: " << node->getUUID();
|
||||||
|
existingNodeID = node->getUUID();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!existingNodeID.isNull()) {
|
||||||
|
limitedNodeList->killNodeWithUUID(existingNodeID);
|
||||||
|
}
|
||||||
|
|
||||||
// add the connecting node (or re-use the matched one from eachNodeBreakable above)
|
// add the connecting node (or re-use the matched one from eachNodeBreakable above)
|
||||||
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection, hintNodeID);
|
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection);
|
||||||
|
|
||||||
// set the edit rights for this user
|
// set the edit rights for this user
|
||||||
newNode->setPermissions(userPerms);
|
newNode->setPermissions(userPerms);
|
||||||
|
|
|
@ -569,9 +569,10 @@ void LimitedNodeList::reset() {
|
||||||
|
|
||||||
// we need to make sure any socket connections are gone so wait on that here
|
// we need to make sure any socket connections are gone so wait on that here
|
||||||
_nodeSocket.clearConnections();
|
_nodeSocket.clearConnections();
|
||||||
|
_connectionIDs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) {
|
bool LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID, ConnectionID newConnectionID) {
|
||||||
QReadLocker readLocker(&_nodeMutex);
|
QReadLocker readLocker(&_nodeMutex);
|
||||||
|
|
||||||
NodeHash::iterator it = _nodeHash.find(nodeUUID);
|
NodeHash::iterator it = _nodeHash.find(nodeUUID);
|
||||||
|
@ -585,7 +586,7 @@ bool LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) {
|
||||||
_nodeHash.unsafe_erase(it);
|
_nodeHash.unsafe_erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNodeKill(matchingNode);
|
handleNodeKill(matchingNode, newConnectionID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +601,7 @@ void LimitedNodeList::processKillNode(ReceivedMessage& message) {
|
||||||
killNodeWithUUID(nodeUUID);
|
killNodeWithUUID(nodeUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) {
|
void LimitedNodeList::handleNodeKill(const SharedNodePointer& node, ConnectionID nextConnectionID) {
|
||||||
qCDebug(networking) << "Killed" << *node;
|
qCDebug(networking) << "Killed" << *node;
|
||||||
node->stopPingTimer();
|
node->stopPingTimer();
|
||||||
emit nodeKilled(node);
|
emit nodeKilled(node);
|
||||||
|
@ -608,6 +609,15 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) {
|
||||||
if (auto activeSocket = node->getActiveSocket()) {
|
if (auto activeSocket = node->getActiveSocket()) {
|
||||||
_nodeSocket.cleanupConnection(*activeSocket);
|
_nodeSocket.cleanupConnection(*activeSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto it = _connectionIDs.find(node->getUUID());
|
||||||
|
if (it != _connectionIDs.end()) {
|
||||||
|
if (nextConnectionID == NULL_CONNECTION_ID) {
|
||||||
|
it->second++;
|
||||||
|
} else {
|
||||||
|
it->second = nextConnectionID;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
|
SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
|
||||||
|
@ -629,6 +639,11 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
|
||||||
|
|
||||||
return matchingNode;
|
return matchingNode;
|
||||||
} else {
|
} else {
|
||||||
|
auto it = _connectionIDs.find(uuid);
|
||||||
|
if (it == _connectionIDs.end()) {
|
||||||
|
_connectionIDs[uuid] = INITIAL_CONNECTION_ID;
|
||||||
|
}
|
||||||
|
|
||||||
// we didn't have this node, so add them
|
// we didn't have this node, so add them
|
||||||
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket);
|
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket);
|
||||||
newNode->setIsReplicated(isReplicated);
|
newNode->setIsReplicated(isReplicated);
|
||||||
|
@ -703,13 +718,13 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<NLPacket> LimitedNodeList::constructPingPacket(PingType_t pingType) {
|
std::unique_ptr<NLPacket> LimitedNodeList::constructPingPacket(const QUuid& nodeId, PingType_t pingType) {
|
||||||
int packetSize = sizeof(PingType_t) + sizeof(quint64);
|
int packetSize = sizeof(PingType_t) + sizeof(quint64) + sizeof(int64_t);
|
||||||
|
|
||||||
auto pingPacket = NLPacket::create(PacketType::Ping, packetSize);
|
auto pingPacket = NLPacket::create(PacketType::Ping, packetSize);
|
||||||
|
|
||||||
pingPacket->writePrimitive(pingType);
|
pingPacket->writePrimitive(pingType);
|
||||||
pingPacket->writePrimitive(usecTimestampNow());
|
pingPacket->writePrimitive(usecTimestampNow());
|
||||||
|
pingPacket->writePrimitive(_connectionIDs[nodeId]);
|
||||||
|
|
||||||
return pingPacket;
|
return pingPacket;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,10 @@ const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::Lo
|
||||||
|
|
||||||
const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username";
|
const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username";
|
||||||
|
|
||||||
|
using ConnectionID = int64_t;
|
||||||
|
const ConnectionID NULL_CONNECTION_ID { -1 };
|
||||||
|
const ConnectionID INITIAL_CONNECTION_ID { 0 };
|
||||||
|
|
||||||
typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair;
|
typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair;
|
||||||
typedef tbb::concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash;
|
typedef tbb::concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash;
|
||||||
|
|
||||||
|
@ -180,7 +184,7 @@ public:
|
||||||
void getPacketStats(float& packetsInPerSecond, float& bytesInPerSecond, float& packetsOutPerSecond, float& bytesOutPerSecond);
|
void getPacketStats(float& packetsInPerSecond, float& bytesInPerSecond, float& packetsOutPerSecond, float& bytesOutPerSecond);
|
||||||
void resetPacketStats();
|
void resetPacketStats();
|
||||||
|
|
||||||
std::unique_ptr<NLPacket> constructPingPacket(PingType_t pingType = PingType::Agnostic);
|
std::unique_ptr<NLPacket> constructPingPacket(const QUuid& nodeId, PingType_t pingType = PingType::Agnostic);
|
||||||
std::unique_ptr<NLPacket> constructPingReplyPacket(ReceivedMessage& message);
|
std::unique_ptr<NLPacket> constructPingReplyPacket(ReceivedMessage& message);
|
||||||
|
|
||||||
static std::unique_ptr<NLPacket> constructICEPingPacket(PingType_t pingType, const QUuid& iceID);
|
static std::unique_ptr<NLPacket> constructICEPingPacket(PingType_t pingType, const QUuid& iceID);
|
||||||
|
@ -319,7 +323,7 @@ public slots:
|
||||||
void startSTUNPublicSocketUpdate();
|
void startSTUNPublicSocketUpdate();
|
||||||
virtual void sendSTUNRequest();
|
virtual void sendSTUNRequest();
|
||||||
|
|
||||||
bool killNodeWithUUID(const QUuid& nodeUUID);
|
bool killNodeWithUUID(const QUuid& nodeUUID, ConnectionID newConnectionID = NULL_CONNECTION_ID);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataSent(quint8 channelType, int bytes);
|
void dataSent(quint8 channelType, int bytes);
|
||||||
|
@ -371,7 +375,7 @@ protected:
|
||||||
bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode = nullptr);
|
bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode = nullptr);
|
||||||
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
||||||
|
|
||||||
void handleNodeKill(const SharedNodePointer& node);
|
void handleNodeKill(const SharedNodePointer& node, ConnectionID newConnectionID = NULL_CONNECTION_ID);
|
||||||
|
|
||||||
void stopInitialSTUNUpdate(bool success);
|
void stopInitialSTUNUpdate(bool success);
|
||||||
|
|
||||||
|
@ -418,6 +422,7 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<QUuid, ConnectionID> _connectionIDs;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
|
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
|
||||||
|
|
|
@ -214,6 +214,20 @@ void NodeList::processPingPacket(QSharedPointer<ReceivedMessage> message, Shared
|
||||||
sendingNode->setSymmetricSocket(senderSockAddr);
|
sendingNode->setSymmetricSocket(senderSockAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t connectionID;
|
||||||
|
|
||||||
|
message->readPrimitive(&connectionID);
|
||||||
|
|
||||||
|
auto it = _connectionIDs.find(sendingNode->getUUID());
|
||||||
|
if (it != _connectionIDs.end()) {
|
||||||
|
if (connectionID > it->second) {
|
||||||
|
qDebug() << "Received a ping packet with a larger connection id (" << connectionID << ">" << it->second << ") from "
|
||||||
|
<< sendingNode->getUUID();
|
||||||
|
killNodeWithUUID(sendingNode->getUUID(), connectionID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::processPingReplyPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
void NodeList::processPingReplyPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
|
@ -705,16 +719,18 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) {
|
||||||
if (node->getConnectionAttempts() > 0 && node->getConnectionAttempts() % NUM_DEBUG_CONNECTION_ATTEMPTS == 0) {
|
if (node->getConnectionAttempts() > 0 && node->getConnectionAttempts() % NUM_DEBUG_CONNECTION_ATTEMPTS == 0) {
|
||||||
qCDebug(networking) << "No response to UDP hole punch pings for node" << node->getUUID() << "in last second.";
|
qCDebug(networking) << "No response to UDP hole punch pings for node" << node->getUUID() << "in last second.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto nodeID = node->getUUID();
|
||||||
|
|
||||||
// send the ping packet to the local and public sockets for this node
|
// send the ping packet to the local and public sockets for this node
|
||||||
auto localPingPacket = constructPingPacket(PingType::Local);
|
auto localPingPacket = constructPingPacket(nodeID, PingType::Local);
|
||||||
sendPacket(std::move(localPingPacket), *node, node->getLocalSocket());
|
sendPacket(std::move(localPingPacket), *node, node->getLocalSocket());
|
||||||
|
|
||||||
auto publicPingPacket = constructPingPacket(PingType::Public);
|
auto publicPingPacket = constructPingPacket(nodeID, PingType::Public);
|
||||||
sendPacket(std::move(publicPingPacket), *node, node->getPublicSocket());
|
sendPacket(std::move(publicPingPacket), *node, node->getPublicSocket());
|
||||||
|
|
||||||
if (!node->getSymmetricSocket().isNull()) {
|
if (!node->getSymmetricSocket().isNull()) {
|
||||||
auto symmetricPingPacket = constructPingPacket(PingType::Symmetric);
|
auto symmetricPingPacket = constructPingPacket(nodeID, PingType::Symmetric);
|
||||||
sendPacket(std::move(symmetricPingPacket), *node, node->getSymmetricSocket());
|
sendPacket(std::move(symmetricPingPacket), *node, node->getSymmetricSocket());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,7 +800,7 @@ void NodeList::sendKeepAlivePings() {
|
||||||
auto type = node->getType();
|
auto type = node->getType();
|
||||||
return !node->isUpstream() && _nodeTypesOfInterest.contains(type) && !NodeType::isDownstream(type);
|
return !node->isUpstream() && _nodeTypesOfInterest.contains(type) && !NodeType::isDownstream(type);
|
||||||
}, [&](const SharedNodePointer& node) {
|
}, [&](const SharedNodePointer& node) {
|
||||||
sendPacket(constructPingPacket(), *node);
|
sendPacket(constructPingPacket(node->getUUID()), *node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
return static_cast<PacketVersion>(IcePingVersion::SendICEPeerID);
|
return static_cast<PacketVersion>(IcePingVersion::SendICEPeerID);
|
||||||
case PacketType::DomainSettings:
|
case PacketType::DomainSettings:
|
||||||
return 18; // replace min_avatar_scale and max_avatar_scale with min_avatar_height and max_avatar_height
|
return 18; // replace min_avatar_scale and max_avatar_scale with min_avatar_height and max_avatar_height
|
||||||
|
case PacketType::Ping:
|
||||||
|
return static_cast<PacketVersion>(PingVersion::IncludeConnectionID);
|
||||||
default:
|
default:
|
||||||
return 17;
|
return 17;
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,4 +323,8 @@ enum class IcePingVersion : PacketVersion {
|
||||||
SendICEPeerID = 18
|
SendICEPeerID = 18
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class PingVersion : PacketVersion {
|
||||||
|
IncludeConnectionID = 18
|
||||||
|
};
|
||||||
|
|
||||||
#endif // hifi_PacketHeaders_h
|
#endif // hifi_PacketHeaders_h
|
||||||
|
|
Loading…
Reference in a new issue