From 8aea0dd951599a0891fe6eeb67ea89b446bb0608 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 13 Nov 2019 10:11:16 -0800 Subject: [PATCH] Merge in Howard's 'screenshare presence' open PR --- assignment-client/src/avatars/AvatarMixer.cpp | 6 ++ .../src/avatars/AvatarMixerClientData.cpp | 12 +++- domain-server/src/DomainServer.cpp | 60 +++++++++++++++++++ domain-server/src/DomainServer.h | 6 ++ libraries/networking/src/udt/PacketHeaders.h | 4 +- 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index c7ab810c9a..807f54953e 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -1081,6 +1081,12 @@ void AvatarMixer::setupEntityQuery() { priorityZoneQuery["avatarPriority"] = true; priorityZoneQuery["type"] = "Zone"; + QJsonObject queryFlags; + queryFlags["includeAncestors"] = true; + queryFlags["includeDescendants"] = true; + priorityZoneQuery["flags"] = queryFlags; + priorityZoneQuery["name"] = true; // Handy for debugging. + _entityViewer.getOctreeQuery().setJSONParameters(priorityZoneQuery); _slaveSharedData.entityTree = entityTree; } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 1195f0d801..ea5246c59a 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -99,6 +99,7 @@ namespace { glm::vec3 position; bool isInPriorityZone { false }; float zoneVolume { std::numeric_limits::max() }; + EntityItemID id {}; static bool operation(const OctreeElementPointer& element, void* extraData) { auto findPriorityZone = static_cast(extraData); @@ -113,6 +114,7 @@ namespace { if (volume < findPriorityZone->zoneVolume) { // Smaller volume wins findPriorityZone->isInPriorityZone = zoneItem->getAvatarPriority() == COMPONENT_MODE_ENABLED; findPriorityZone->zoneVolume = volume; + findPriorityZone->id = zoneItem->getEntityItemID(); } } } @@ -152,7 +154,15 @@ int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveShared EntityTree& entityTree = *slaveSharedData.entityTree; FindPriorityZone findPriorityZone { newPosition } ; entityTree.recurseTreeWithOperation(&FindPriorityZone::operation, &findPriorityZone); - _avatar->setHasPriority(findPriorityZone.isInPriorityZone); + bool currentlyHasPriority = findPriorityZone.isInPriorityZone; + if (currentlyHasPriority != _avatar->getHasPriority()) { + _avatar->setHasPriority(currentlyHasPriority); + auto nodeList = DependencyManager::get(); + auto packet = NLPacket::create(PacketType::AvatarZonePresence, 2 * NUM_BYTES_RFC4122_UUID, true); + packet->write(_avatar->getSessionUUID().toRfc4122()); + packet->write(findPriorityZone.id.toRfc4122()); + nodeList->sendPacket(std::move(packet), nodeList->getDomainSockAddr()); + } _avatar->setNeedsHeroCheck(false); } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ceb4679137..9eec7df86e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -766,6 +766,7 @@ void DomainServer::setupNodeListAndAssignments() { packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket"); packetReceiver.registerListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket"); packetReceiver.registerListener(PacketType::DomainDisconnectRequest, this, "processNodeDisconnectRequestPacket"); + packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacket"); // NodeList won't be available to the settings manager when it is created, so call registerListener here packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket"); @@ -3613,3 +3614,62 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointerreadAll(), QString(), QString(), username); } } + +void DomainServer::processAvatarZonePresencePacket(QSharedPointer message) { + QUuid avatar = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + + if (avatar.isNull()) { + qCWarning(domain_server) << "Ignoring null avatar presence"; + return; + } + auto limitedNodeList = DependencyManager::get(); + auto matchingNode = limitedNodeList->nodeWithUUID(avatar); + if (!matchingNode) { + qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar" << avatar; + return; + } + QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName(); + static const int SCREENSHARE_EXPIRATION_SECONDS = 24 * 60 * 60; + screensharePresence(zone.isNull() ? "" : zone.toString(), verifiedUsername, SCREENSHARE_EXPIRATION_SECONDS); +} + +void DomainServer::screensharePresence(QString roomname, QString username, int expirationSeconds) { + if (!DependencyManager::get()->hasValidAccessToken()) { + static std::once_flag presenceAuthorityWarning; + std::call_once(presenceAuthorityWarning, [] { + qCDebug(domain_server) << "No authority to send screensharePresence."; + }); + return; + } + JSONCallbackParameters callbackParams; + callbackParams.callbackReceiver = this; + callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence"; + callbackParams.errorCallbackMethod = "handleFailedScreensharePresence"; + const QString PATH = "api/v1/domains/%1/screenshare"; + QString domain_id = uuidStringWithoutCurlyBraces(getID()); + QJsonObject json, screenshare; + screenshare["username"] = username; + screenshare["roomname"] = roomname; + if (expirationSeconds > 0) { + screenshare["expiration"] = expirationSeconds; + } + json["screenshare"] = screenshare; + DependencyManager::get()->sendRequest( + PATH.arg(domain_id), + AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, + callbackParams, QJsonDocument(json).toJson() + ); +} + +void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply) { + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object(); + if (jsonObject["status"].toString() != "success") { + qCWarning(domain_server) << "screensharePresence api call failed:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); + } +} + +void DomainServer::handleFailedScreensharePresence(QNetworkReply* requestReply) { + qCWarning(domain_server) << "screensharePresence api call failed:" << requestReply->error(); +} diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index c725688b67..034ccb5a18 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -78,6 +78,8 @@ public: bool isAssetServerEnabled(); + void screensharePresence(QString roomname, QString username, int expiration_seconds = 0); + public slots: /// Called by NodeList to inform us a node has been added void nodeAdded(SharedNodePointer node); @@ -96,6 +98,7 @@ private slots: void processNodeDisconnectRequestPacket(QSharedPointer message); void processICEServerHeartbeatDenialPacket(QSharedPointer message); void processICEServerHeartbeatACK(QSharedPointer message); + void processAvatarZonePresencePacket(QSharedPointer packet); void handleDomainContentReplacementFromURLRequest(QSharedPointer message); void handleOctreeFileReplacementRequest(QSharedPointer message); @@ -129,6 +132,9 @@ private slots: void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply); void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply); + void handleSuccessfulScreensharePresence(QNetworkReply* requestReply); + void handleFailedScreensharePresence(QNetworkReply* requestReply); + void updateReplicatedNodes(); void updateDownstreamNodes(); void updateUpstreamNodes(); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fbf575065e..75904d8122 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -135,6 +135,7 @@ public: AudioSoloRequest, BulkAvatarTraitsAck, StopInjector, + AvatarZonePresence, NUM_PACKET_TYPE }; @@ -185,7 +186,8 @@ public: << PacketTypeEnum::Value::OctreeFileReplacement << PacketTypeEnum::Value::ReplicatedMicrophoneAudioNoEcho << PacketTypeEnum::Value::ReplicatedMicrophoneAudioWithEcho << PacketTypeEnum::Value::ReplicatedInjectAudio << PacketTypeEnum::Value::ReplicatedSilentAudioFrame << PacketTypeEnum::Value::ReplicatedAvatarIdentity - << PacketTypeEnum::Value::ReplicatedKillAvatar << PacketTypeEnum::Value::ReplicatedBulkAvatarData; + << PacketTypeEnum::Value::ReplicatedKillAvatar << PacketTypeEnum::Value::ReplicatedBulkAvatarData + << PacketTypeEnum::Value::AvatarZonePresence; return NON_SOURCED_PACKETS; }