Prevent replication flat loops

This commit is contained in:
Atlante45 2017-06-22 15:04:39 -07:00
parent c47645e075
commit 71d2540a23
6 changed files with 26 additions and 10 deletions

View file

@ -51,6 +51,11 @@ public:
static const QVector<ReverbSettings>& getReverbSettings() { return _zoneReverbSettings; } static const QVector<ReverbSettings>& getReverbSettings() { return _zoneReverbSettings; }
static const std::pair<QString, CodecPluginPointer> negotiateCodec(std::vector<QString> codecs); static const std::pair<QString, CodecPluginPointer> negotiateCodec(std::vector<QString> codecs);
static bool shouldReplicateTo(const Node& from, const Node& to) {
return to.getType() == NodeType::DownstreamAudioMixer &&
to.getPublicSocket() != from.getPublicSocket() &&
to.getLocalSocket() != from.getLocalSocket();
}
public slots: public slots:
void run() override; void run() override;
void sendStatsPacket() override; void sendStatsPacket() override;

View file

@ -146,7 +146,7 @@ void AudioMixerClientData::optionallyReplicatePacket(ReceivedMessage& message, c
// enumerate the downstream audio mixers and send them the replicated version of this packet // enumerate the downstream audio mixers and send them the replicated version of this packet
nodeList->unsafeEachNode([&](const SharedNodePointer& downstreamNode) { nodeList->unsafeEachNode([&](const SharedNodePointer& downstreamNode) {
if (downstreamNode->getType() == NodeType::DownstreamAudioMixer) { if (AudioMixer::shouldReplicateTo(node, *downstreamNode)) {
// construct the packet only once, if we have any downstream audio mixers to send to // construct the packet only once, if we have any downstream audio mixers to send to
if (!packet) { if (!packet) {
// construct an NLPacket to send to the replicant that has the contents of the received packet // construct an NLPacket to send to the replicant that has the contents of the received packet

View file

@ -143,8 +143,8 @@ void AvatarMixer::optionallyReplicatePacket(ReceivedMessage& message, const Node
std::unique_ptr<NLPacket> packet; std::unique_ptr<NLPacket> packet;
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
nodeList->eachMatchingNode([&](const SharedNodePointer& node) { nodeList->eachMatchingNode([&](const SharedNodePointer& downstreamNode) {
return node->getType() == NodeType::DownstreamAvatarMixer; return shouldReplicateTo(node, *downstreamNode);
}, [&](const SharedNodePointer& node) { }, [&](const SharedNodePointer& node) {
if (!packet) { if (!packet) {
// construct an NLPacket to send to the replicant that has the contents of the received packet // construct an NLPacket to send to the replicant that has the contents of the received packet
@ -424,8 +424,8 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
nodeList->eachMatchingNode([&](const SharedNodePointer& node) { nodeList->eachMatchingNode([&](const SharedNodePointer& node) {
// we relay avatar kill packets to agents that are not upstream // we relay avatar kill packets to agents that are not upstream
// and downstream avatar mixers, if the node that was just killed was being replicated // and downstream avatar mixers, if the node that was just killed was being replicated
return (node->getType() == NodeType::Agent && !node->isUpstream()) return (node->getType() == NodeType::Agent && !node->isUpstream()) ||
|| (killedNode->isReplicated() && node->getType() == NodeType::DownstreamAvatarMixer); (killedNode->isReplicated() && shouldReplicateTo(*killedNode, *node));
}, [&](const SharedNodePointer& node) { }, [&](const SharedNodePointer& node) {
if (node->getType() == NodeType::Agent) { if (node->getType() == NodeType::Agent) {
if (!killPacket) { if (!killPacket) {

View file

@ -28,6 +28,13 @@ class AvatarMixer : public ThreadedAssignment {
Q_OBJECT Q_OBJECT
public: public:
AvatarMixer(ReceivedMessage& message); AvatarMixer(ReceivedMessage& message);
static bool shouldReplicateTo(const Node& from, const Node& to) {
return to.getType() == NodeType::DownstreamAvatarMixer &&
to.getPublicSocket() != from.getPublicSocket() &&
to.getLocalSocket() != from.getLocalSocket();
}
public slots: public slots:
/// runs the avatar mixer /// runs the avatar mixer
void run() override; void run() override;

View file

@ -79,13 +79,13 @@ int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData,
} }
} }
int AvatarMixerSlave::sendReplicatedIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) { int AvatarMixerSlave::sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
if (destinationNode->getType() == NodeType::DownstreamAvatarMixer) { if (AvatarMixer::shouldReplicateTo(agentNode, destinationNode)) {
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
auto identityPacket = NLPacketList::create(PacketType::ReplicatedAvatarIdentity, QByteArray(), true, true); auto identityPacket = NLPacketList::create(PacketType::ReplicatedAvatarIdentity, QByteArray(), true, true);
identityPacket->write(individualData); identityPacket->write(individualData);
DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPacket), *destinationNode); DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPacket), destinationNode);
_stats.numIdentityPackets++; _stats.numIdentityPackets++;
return individualData.size(); return individualData.size();
} else { } else {
@ -453,6 +453,10 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
nodeData->resetNumAvatarsSentLastFrame(); nodeData->resetNumAvatarsSentLastFrame();
std::for_each(_begin, _end, [&](const SharedNodePointer& agentNode) { std::for_each(_begin, _end, [&](const SharedNodePointer& agentNode) {
if (!AvatarMixer::shouldReplicateTo(*agentNode, *node)) {
return;
}
// collect agents that we have avatar data for that we are supposed to replicate // collect agents that we have avatar data for that we are supposed to replicate
if (agentNode->getType() == NodeType::Agent && agentNode->getLinkedData() && agentNode->isReplicated()) { if (agentNode->getType() == NodeType::Agent && agentNode->getLinkedData() && agentNode->isReplicated()) {
const AvatarMixerClientData* agentNodeData = reinterpret_cast<const AvatarMixerClientData*>(agentNode->getLinkedData()); const AvatarMixerClientData* agentNodeData = reinterpret_cast<const AvatarMixerClientData*>(agentNode->getLinkedData());
@ -479,7 +483,7 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID()); auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID());
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp() if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) { || (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
sendReplicatedIdentityPacket(agentNodeData, node); sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
nodeData->setLastBroadcastTime(agentNode->getUUID(), start); nodeData->setLastBroadcastTime(agentNode->getUUID(), start);
} }

View file

@ -95,7 +95,7 @@ public:
private: private:
int sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode); int sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
int sendReplicatedIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode); int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
void broadcastAvatarDataToAgent(const SharedNodePointer& node); void broadcastAvatarDataToAgent(const SharedNodePointer& node);
void broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node); void broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node);