Initial cut

No script work yet, just first stab at underpinnings
This commit is contained in:
David Kelly 2016-11-10 16:24:35 -08:00
parent 5b91c8f32b
commit 285520dff7
12 changed files with 94 additions and 4 deletions

View file

@ -94,6 +94,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket"); packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket"); packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket");
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled); connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
} }
@ -599,6 +600,19 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) {
}); });
} }
void AudioMixer::handleNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
auto nodeList = DependencyManager::get<NodeList>();
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<ReceivedMessage> packet, SharedNodePointer sendingNode) { void AudioMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
auto clientData = dynamic_cast<AudioMixerClientData*>(sendingNode->getLinkedData()); auto clientData = dynamic_cast<AudioMixerClientData*>(sendingNode->getLinkedData());
if (clientData) { if (clientData) {
@ -814,9 +828,13 @@ void AudioMixer::broadcastMixes() {
// if the stream should be muted, send mute packet // if the stream should be muted, send mute packet
if (nodeData->getAvatarAudioStream() if (nodeData->getAvatarAudioStream()
&& shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) { && (shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())
|| nodeData->shouldMuteClient())) {
auto mutePacket = NLPacket::create(PacketType::NoisyMute, 0); auto mutePacket = NLPacket::create(PacketType::NoisyMute, 0);
nodeList->sendPacket(std::move(mutePacket), *node); 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() if (node->getType() == NodeType::Agent && node->getActiveSocket()

View file

@ -49,6 +49,7 @@ private slots:
void handleNodeKilled(SharedNodePointer killedNode); void handleNodeKilled(SharedNodePointer killedNode);
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode); void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode); void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void handleNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void removeHRTFsForFinishedInjector(const QUuid& streamID); void removeHRTFsForFinishedInjector(const QUuid& streamID);

View file

@ -86,6 +86,9 @@ public:
bool shouldFlushEncoder() { return _shouldFlushEncoder; } bool shouldFlushEncoder() { return _shouldFlushEncoder; }
QString getCodecName() { return _selectedCodecName; } QString getCodecName() { return _selectedCodecName; }
bool shouldMuteClient() { return _shouldMuteClient; }
void setShouldMuteClient(bool shouldMuteClient) { _shouldMuteClient = shouldMuteClient; }
signals: signals:
void injectorStreamFinished(const QUuid& streamIdentifier); void injectorStreamFinished(const QUuid& streamIdentifier);
@ -114,6 +117,8 @@ private:
Decoder* _decoder{ nullptr }; // for mic stream Decoder* _decoder{ nullptr }; // for mic stream
bool _shouldFlushEncoder { false }; bool _shouldFlushEncoder { false };
bool _shouldMuteClient { false };
}; };
#endif // hifi_AudioMixerClientData_h #endif // hifi_AudioMixerClientData_h

View file

@ -498,7 +498,8 @@ void DomainServer::setupNodeListAndAssignments() {
// NodeList won't be available to the settings manager when it is created, so call registerListener here // 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::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket");
packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket"); packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket");
packetReceiver.registerListener(PacketType::NodeMuteRequest, &_settingsManager, "processNodeMuteRequestPacket");
// register the gatekeeper for the packets it needs to receive // register the gatekeeper for the packets it needs to receive
packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket");
packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket"); packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket");

View file

@ -634,6 +634,38 @@ bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() {
return changed; return changed;
} }
void DomainServerSettingsManager::processNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> 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<LimitedNodeList>();
auto matchingNode = limitedNodeList->nodeWithUUID(nodeUUID);
if (matchingNode) {
// send this along to the audio mixer
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
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<ReceivedMessage> message, SharedNodePointer sendingNode) { void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
// before we do any processing on this packet make sure it comes from a node that is allowed to kick // before we do any processing on this packet make sure it comes from a node that is allowed to kick

View file

@ -105,6 +105,7 @@ public slots:
private slots: private slots:
void processSettingsRequestPacket(QSharedPointer<ReceivedMessage> message); void processSettingsRequestPacket(QSharedPointer<ReceivedMessage> message);
void processNodeKickRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); void processNodeKickRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void processNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
private: private:
QStringList _argumentList; QStringList _argumentList;

View file

@ -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.";
}
}

View file

@ -74,6 +74,7 @@ public:
bool isIgnoringNode(const QUuid& nodeID) const; bool isIgnoringNode(const QUuid& nodeID) const;
void kickNodeBySessionID(const QUuid& nodeID); void kickNodeBySessionID(const QUuid& nodeID);
void muteNodeBySessionID(const QUuid& nodeID);
public slots: public slots:
void reset(); void reset();

View file

@ -26,7 +26,8 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
<< PacketType::NodeJsonStats << PacketType::EntityQuery << PacketType::NodeJsonStats << PacketType::EntityQuery
<< PacketType::OctreeDataNack << PacketType::EntityEditNack << PacketType::OctreeDataNack << PacketType::EntityEditNack
<< PacketType::DomainListRequest << PacketType::StopNode << PacketType::DomainListRequest << PacketType::StopNode
<< PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest; << PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest
<< PacketType::NodeMuteRequest;
const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>() const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
<< PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment << PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment

View file

@ -99,7 +99,8 @@ public:
SelectedAudioFormat, SelectedAudioFormat,
MoreEntityShapes, MoreEntityShapes,
NodeKickRequest, NodeKickRequest,
LAST_PACKET_TYPE = NodeKickRequest NodeMuteRequest,
LAST_PACKET_TYPE = NodeMuteRequest
}; };
}; };

View file

@ -29,6 +29,11 @@ void UsersScriptingInterface::kick(const QUuid& nodeID) {
DependencyManager::get<NodeList>()->kickNodeBySessionID(nodeID); DependencyManager::get<NodeList>()->kickNodeBySessionID(nodeID);
} }
void UsersScriptingInterface::mute(const QUuid& nodeID) {
// ask the NodeList to mute the user with the given session ID
DependencyManager::get<NodeList>()->muteNodeBySessionID(nodeID);
}
bool UsersScriptingInterface::getCanKick() { bool UsersScriptingInterface::getCanKick() {
// ask the NodeList to return our ability to kick // ask the NodeList to return our ability to kick
return DependencyManager::get<NodeList>()->getThisNodeCanKick(); return DependencyManager::get<NodeList>()->getThisNodeCanKick();

View file

@ -28,6 +28,7 @@ public:
public slots: public slots:
void ignore(const QUuid& nodeID); void ignore(const QUuid& nodeID);
void kick(const QUuid& nodeID); void kick(const QUuid& nodeID);
void mute(const QUuid& nodeID);
bool getCanKick(); bool getCanKick();