From 285520dff7fc29afc111a99f75b325ff750d1709 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 10 Nov 2016 16:24:35 -0800 Subject: [PATCH] Initial cut No script work yet, just first stab at underpinnings --- assignment-client/src/audio/AudioMixer.cpp | 20 +++++++++++- assignment-client/src/audio/AudioMixer.h | 1 + .../src/audio/AudioMixerClientData.h | 5 +++ domain-server/src/DomainServer.cpp | 3 +- .../src/DomainServerSettingsManager.cpp | 32 +++++++++++++++++++ .../src/DomainServerSettingsManager.h | 1 + libraries/networking/src/NodeList.cpp | 23 +++++++++++++ libraries/networking/src/NodeList.h | 1 + .../networking/src/udt/PacketHeaders.cpp | 3 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- .../src/UsersScriptingInterface.cpp | 5 +++ .../src/UsersScriptingInterface.h | 1 + 12 files changed, 94 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index f8077303d2..17198299b4 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -94,6 +94,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) : packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket"); packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); + packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket"); connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled); } @@ -599,6 +600,19 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) { }); } +void AudioMixer::handleNodeMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { + auto nodeList = DependencyManager::get(); + QUuid nodeUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + + auto node = nodeList->nodeWithUUID(nodeUUID); + if (node) { + // we need to set a flag so we send them the appropriate packet to mute them + + } else { + qWarning() << "Node mute packet received for unknown node " << uuidStringWithoutCurlyBraces(nodeUUID); + } +} + void AudioMixer::handleKillAvatarPacket(QSharedPointer packet, SharedNodePointer sendingNode) { auto clientData = dynamic_cast(sendingNode->getLinkedData()); if (clientData) { @@ -814,9 +828,13 @@ void AudioMixer::broadcastMixes() { // if the stream should be muted, send mute packet if (nodeData->getAvatarAudioStream() - && shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) { + && (shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness()) + || nodeData->shouldMuteClient())) { auto mutePacket = NLPacket::create(PacketType::NoisyMute, 0); nodeList->sendPacket(std::move(mutePacket), *node); + + // probably now we just reset the flag, once should do it (?) + nodeData->setShouldMuteClient(false); } if (node->getType() == NodeType::Agent && node->getActiveSocket() diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 3c68e4c6af..91eafadd9d 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -49,6 +49,7 @@ private slots: void handleNodeKilled(SharedNodePointer killedNode); void handleNodeIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleKillAvatarPacket(QSharedPointer packet, SharedNodePointer sendingNode); + void handleNodeMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void removeHRTFsForFinishedInjector(const QUuid& streamID); diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 52c659c240..c74461a444 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -86,6 +86,9 @@ public: bool shouldFlushEncoder() { return _shouldFlushEncoder; } QString getCodecName() { return _selectedCodecName; } + + bool shouldMuteClient() { return _shouldMuteClient; } + void setShouldMuteClient(bool shouldMuteClient) { _shouldMuteClient = shouldMuteClient; } signals: void injectorStreamFinished(const QUuid& streamIdentifier); @@ -114,6 +117,8 @@ private: Decoder* _decoder{ nullptr }; // for mic stream bool _shouldFlushEncoder { false }; + + bool _shouldMuteClient { false }; }; #endif // hifi_AudioMixerClientData_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index d13f9b883f..b58dd0fe0e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -498,7 +498,8 @@ void DomainServer::setupNodeListAndAssignments() { // NodeList won't be available to the settings manager when it is created, so call registerListener here packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket"); packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket"); - + packetReceiver.registerListener(PacketType::NodeMuteRequest, &_settingsManager, "processNodeMuteRequestPacket"); + // register the gatekeeper for the packets it needs to receive packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket"); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index c7944bbcad..ff6c4d62c6 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -634,6 +634,38 @@ bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() { return changed; } +void DomainServerSettingsManager::processNodeMuteRequestPacket(QSharedPointer message, SharedNodePointer sendingNode) { + if (sendingNode->getCanKick()) { + QUuid nodeUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + + if (!nodeUUID.isNull() && nodeUUID != sendingNode->getUUID()) { + // make sure we actually have a node with this UUID + auto limitedNodeList = DependencyManager::get(); + + auto matchingNode = limitedNodeList->nodeWithUUID(nodeUUID); + + if (matchingNode) { + // send this along to the audio mixer + auto limitedNodeList = DependencyManager::get(); + auto audioMixer = limitedNodeList->soloNodeOfType(NodeType::AudioMixer); + if (audioMixer) { + auto packet = NLPacket::create(PacketType::NodeMuteRequest, NUM_BYTES_RFC4122_UUID, true); + packet->write(nodeUUID.toRfc4122()); + limitedNodeList->sendPacket(std::move(packet), *audioMixer); + } else { + qWarning() << "Couldn't find an audio mixer, cannot process node mute request"; + } + } else { + qWarning() << "Node mute request received for unknown node. Refusing to process."; + } + } else { + qWarning() << "Node kick request received for invalid node ID or from node being kicked. Refusing to process."; + } + } else { + qWarning() << "Refusing to process a kick packet from node" << uuidStringWithoutCurlyBraces(sendingNode->getUUID()) + << "that does not have kick permissions."; + } +} void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer message, SharedNodePointer sendingNode) { // before we do any processing on this packet make sure it comes from a node that is allowed to kick diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index c067377ffc..7f874226bb 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -105,6 +105,7 @@ public slots: private slots: void processSettingsRequestPacket(QSharedPointer message); void processNodeKickRequestPacket(QSharedPointer message, SharedNodePointer sendingNode); + void processNodeMuteRequestPacket(QSharedPointer message, SharedNodePointer sendingNode); private: QStringList _argumentList; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 82bac4cc3d..782eb8da3e 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -815,3 +815,26 @@ void NodeList::kickNodeBySessionID(const QUuid& nodeID) { } } + +void NodeList::muteNodeBySessionID(const QUuid& nodeID) { + // cannot mute yourself, or nobody + if (!nodeID.isNull() && _sessionUUID != nodeID ) { + if (getThisNodeCanKick()) { + // setup the packet + auto kickPacket = NLPacket::create(PacketType::NodeMuteRequest, NUM_BYTES_RFC4122_UUID, true); + + // write the node ID to the packet + kickPacket->write(nodeID.toRfc4122()); + + qDebug() << "Sending packet to mute node" << uuidStringWithoutCurlyBraces(nodeID); + + sendPacket(std::move(kickPacket), _domainHandler.getSockAddr()); + } else { + qWarning() << "You do not have permissions to mute in this domain." + << "Request to mute node" << uuidStringWithoutCurlyBraces(nodeID) << "will not be sent"; + } + } else { + qWarning() << "NodeList::muteNodeBySessionID called with an invalid ID or an ID which matches the current session ID."; + + } +} diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 41a4a51515..4c06a13469 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -74,6 +74,7 @@ public: bool isIgnoringNode(const QUuid& nodeID) const; void kickNodeBySessionID(const QUuid& nodeID); + void muteNodeBySessionID(const QUuid& nodeID); public slots: void reset(); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 6b86b7bc6e..9bbf4dc134 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -26,7 +26,8 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketType::NodeJsonStats << PacketType::EntityQuery << PacketType::OctreeDataNack << PacketType::EntityEditNack << PacketType::DomainListRequest << PacketType::StopNode - << PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest; + << PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest + << PacketType::NodeMuteRequest; const QSet NON_SOURCED_PACKETS = QSet() << PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 0eca24176c..a3a7287ad0 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -99,7 +99,8 @@ public: SelectedAudioFormat, MoreEntityShapes, NodeKickRequest, - LAST_PACKET_TYPE = NodeKickRequest + NodeMuteRequest, + LAST_PACKET_TYPE = NodeMuteRequest }; }; diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 69ad8e04ad..702368c2b3 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -29,6 +29,11 @@ void UsersScriptingInterface::kick(const QUuid& nodeID) { DependencyManager::get()->kickNodeBySessionID(nodeID); } +void UsersScriptingInterface::mute(const QUuid& nodeID) { + // ask the NodeList to mute the user with the given session ID + DependencyManager::get()->muteNodeBySessionID(nodeID); +} + bool UsersScriptingInterface::getCanKick() { // ask the NodeList to return our ability to kick return DependencyManager::get()->getThisNodeCanKick(); diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 712eeedeb6..3c98d0a393 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -28,6 +28,7 @@ public: public slots: void ignore(const QUuid& nodeID); void kick(const QUuid& nodeID); + void mute(const QUuid& nodeID); bool getCanKick();