From bf920c2b80e1041dafec8ca8c7bd19c0bd630ebd Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:16:39 -0700 Subject: [PATCH 01/11] Compact Domain heartbeat JSON --- domain-server/src/DomainServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 052a7c0fec..231e9ba014 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1121,7 +1121,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { domainObject[DOMAIN_HEARTBEAT_KEY] = heartbeatObject; - QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson())); + QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManagerAuth::Required, From 87e27d9570b9419802ddbed6f664d42baf912db8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:16:02 -0700 Subject: [PATCH 02/11] Factor out metadata generation from heartbeat --- domain-server/src/DomainServer.cpp | 79 ++++++++++++++++-------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 231e9ba014..ae3c26a34d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1067,62 +1067,69 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) sendHeartbeatToMetaverse(newPublicSockAddr.getAddress().toString()); } - -void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { - const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; - - auto nodeList = DependencyManager::get(); - const QUuid& domainID = nodeList->getSessionUUID(); - - // setup the domain object to send to the data server - const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address"; - const QString AUTOMATIC_NETWORKING_KEY = "automatic_networking"; - - QJsonObject domainObject; - if (!networkAddress.isEmpty()) { - domainObject[PUBLIC_NETWORK_ADDRESS_KEY] = networkAddress; - } - - domainObject[AUTOMATIC_NETWORKING_KEY] = _automaticNetworkingSetting; - - // add a flag to indicate if this domain uses restricted access - for now that will exclude it from listings - const QString RESTRICTED_ACCESS_FLAG = "restricted"; - - domainObject[RESTRICTED_ACCESS_FLAG] = - _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); - - // figure out the breakdown of currently connected interface clients - int numConnectedUnassigned = 0; - QJsonObject userHostnames; - +QVariantMap getMetadata() { static const QString DEFAULT_HOSTNAME = "*"; + auto nodeList = DependencyManager::get(); + int numConnectedUnassigned = 0; + QVariantMap userHostnames; + + // figure out the breakdown of currently connected interface clients nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { - if (node->getLinkedData()) { - auto nodeData = static_cast(node->getLinkedData()); + auto linkedData = node->getLinkedData(); + if (linkedData) { + auto nodeData = static_cast(linkedData); if (!nodeData->wasAssigned()) { ++numConnectedUnassigned; // increment the count for this hostname (or the default if we don't have one) - auto hostname = nodeData->getPlaceName().isEmpty() ? DEFAULT_HOSTNAME : nodeData->getPlaceName(); + auto placeName = nodeData->getPlaceName(); + auto hostname = placeName.isEmpty() ? DEFAULT_HOSTNAME : placeName; userHostnames[hostname] = userHostnames[hostname].toInt() + 1; } } }); - static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + QVariantMap metadata; + static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; + metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; + static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; + metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; - QJsonObject heartbeatObject; - heartbeatObject[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; - heartbeatObject[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + return metadata; +} - domainObject[DOMAIN_HEARTBEAT_KEY] = heartbeatObject; +void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { + auto nodeList = DependencyManager::get(); + const QUuid& domainID = nodeList->getSessionUUID(); + + // Setup the domain object to send to the data server + QJsonObject domainObject; + + if (!networkAddress.isEmpty()) { + static const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address"; + domainObject[PUBLIC_NETWORK_ADDRESS_KEY] = networkAddress; + } + + static const QString AUTOMATIC_NETWORKING_KEY = "automatic_networking"; + domainObject[AUTOMATIC_NETWORKING_KEY] = _automaticNetworkingSetting; + + // Add a flag to indicate if this domain uses restricted access - + // for now that will exclude it from listings + static const QString RESTRICTED_ACCESS_FLAG = "restricted"; + domainObject[RESTRICTED_ACCESS_FLAG] = + _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + + // Add the metadata to the heartbeat + static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + domainObject[DOMAIN_HEARTBEAT_KEY] = QJsonObject::fromVariantMap(getMetadata()); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); + static const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManagerAuth::Required, QNetworkAccessManager::PutOperation, From 18696144f1c29e383d0bd2056395c6f8573fa19a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:23:47 -0700 Subject: [PATCH 03/11] Move metadata generation to DomainMetadata --- domain-server/src/DomainMetadata.cpp | 51 ++++++++++++++++++++++++++++ domain-server/src/DomainMetadata.h | 21 ++++++++++++ domain-server/src/DomainServer.cpp | 35 ------------------- domain-server/src/DomainServer.h | 1 + 4 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 domain-server/src/DomainMetadata.cpp create mode 100644 domain-server/src/DomainMetadata.h diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp new file mode 100644 index 0000000000..f584198b51 --- /dev/null +++ b/domain-server/src/DomainMetadata.cpp @@ -0,0 +1,51 @@ +// +// DomainMetadata.cpp +// domain-server/src +// +// Created by Zach Pomerantz on 5/25/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include "DomainMetadata.h" + +#include +#include + +#include "DomainServerNodeData.h" + +QVariantMap getMetadata() { + static const QString DEFAULT_HOSTNAME = "*"; + + auto nodeList = DependencyManager::get(); + int numConnectedUnassigned = 0; + QVariantMap userHostnames; + + // figure out the breakdown of currently connected interface clients + nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { + auto linkedData = node->getLinkedData(); + if (linkedData) { + auto nodeData = static_cast(linkedData); + + if (!nodeData->wasAssigned()) { + ++numConnectedUnassigned; + + // increment the count for this hostname (or the default if we don't have one) + auto placeName = nodeData->getPlaceName(); + auto hostname = placeName.isEmpty() ? DEFAULT_HOSTNAME : placeName; + userHostnames[hostname] = userHostnames[hostname].toInt() + 1; + } + } + }); + + QVariantMap metadata; + + static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; + metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; + + static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; + metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + + return metadata; +} diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h new file mode 100644 index 0000000000..3cd160ce85 --- /dev/null +++ b/domain-server/src/DomainMetadata.h @@ -0,0 +1,21 @@ +// +// DomainMetadata.h +// domain-server/src +// +// Created by Zach Pomerantz on 5/25/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#ifndef hifi_DomainMetadata_h +#define hifi_DomainMetadata_h + +#include + +QVariantMap getMetadata(); + +// TODO: Encapsulate +class DomainMetadata { }; + +#endif // hifi_DomainMetadata_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ae3c26a34d..f05dfd2c6d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1067,41 +1067,6 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) sendHeartbeatToMetaverse(newPublicSockAddr.getAddress().toString()); } -QVariantMap getMetadata() { - static const QString DEFAULT_HOSTNAME = "*"; - - auto nodeList = DependencyManager::get(); - int numConnectedUnassigned = 0; - QVariantMap userHostnames; - - // figure out the breakdown of currently connected interface clients - nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { - auto linkedData = node->getLinkedData(); - if (linkedData) { - auto nodeData = static_cast(linkedData); - - if (!nodeData->wasAssigned()) { - ++numConnectedUnassigned; - - // increment the count for this hostname (or the default if we don't have one) - auto placeName = nodeData->getPlaceName(); - auto hostname = placeName.isEmpty() ? DEFAULT_HOSTNAME : placeName; - userHostnames[hostname] = userHostnames[hostname].toInt() + 1; - } - } - }); - - QVariantMap metadata; - - static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; - metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; - - static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; - metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; - - return metadata; -} - void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { auto nodeList = DependencyManager::get(); const QUuid& domainID = nodeList->getSessionUUID(); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index c39e405380..0f93c50468 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -26,6 +26,7 @@ #include #include "DomainGatekeeper.h" +#include "DomainMetadata.h" #include "DomainServerSettingsManager.h" #include "DomainServerWebSessionData.h" #include "WalletTransaction.h" From b13e7a1a8f48cb61e7862591f5927a04cbf5abe5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:35:52 -0700 Subject: [PATCH 04/11] Encapsulate metadata in DomainMetadata --- domain-server/src/DomainMetadata.cpp | 12 ++++++------ domain-server/src/DomainMetadata.h | 15 ++++++++++++--- domain-server/src/DomainServer.cpp | 2 +- domain-server/src/DomainServer.h | 2 ++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index f584198b51..224fe1939b 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,7 +15,7 @@ #include "DomainServerNodeData.h" -QVariantMap getMetadata() { +void DomainMetadata::generate() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); @@ -39,13 +39,13 @@ QVariantMap getMetadata() { } }); - QVariantMap metadata; - static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; - metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; + _metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; - metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + _metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; - return metadata; +#if DEV_BUILD + qDebug() << "Regenerated domain metadata - users:" << _metadata; +#endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 3cd160ce85..5096f1bb3e 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -12,10 +12,19 @@ #define hifi_DomainMetadata_h #include +#include -QVariantMap getMetadata(); +class DomainMetadata { +public: + QVariantMap toVariantMap() { generate(); return _metadata; } + QJsonObject toJSON() { generate(); return QJsonObject::fromVariantMap(_metadata); } -// TODO: Encapsulate -class DomainMetadata { }; +protected slots: + // TODO: Connect appropriate signals to obviate JIT generation + void generate(); + +protected: + QVariantMap _metadata; +}; #endif // hifi_DomainMetadata_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index f05dfd2c6d..9b1fbb1d84 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1090,7 +1090,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { // Add the metadata to the heartbeat static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; - domainObject[DOMAIN_HEARTBEAT_KEY] = QJsonObject::fromVariantMap(getMetadata()); + domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.toJSON(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 0f93c50468..0a1df41f50 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -168,6 +168,8 @@ private: DomainServerSettingsManager _settingsManager; + DomainMetadata _metadata; + HifiSockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket; From 85055d82bfe9342cc297d0c0329cb6711aeadc5a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 2 Jun 2016 17:05:58 -0700 Subject: [PATCH 05/11] Regenerate Domain metadata on user (dis)connect --- domain-server/src/DomainMetadata.cpp | 2 +- domain-server/src/DomainMetadata.h | 9 ++++--- domain-server/src/DomainServer.cpp | 36 +++++++++++++++++++--------- domain-server/src/DomainServer.h | 2 ++ 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 224fe1939b..c45a07e646 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,7 +15,7 @@ #include "DomainServerNodeData.h" -void DomainMetadata::generate() { +void DomainMetadata::usersChanged() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 5096f1bb3e..f92c40ce61 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -16,12 +16,11 @@ class DomainMetadata { public: - QVariantMap toVariantMap() { generate(); return _metadata; } - QJsonObject toJSON() { generate(); return QJsonObject::fromVariantMap(_metadata); } + QVariantMap toVariantMap() { return _metadata; } + QJsonObject toJSON() { return QJsonObject::fromVariantMap(_metadata); } -protected slots: - // TODO: Connect appropriate signals to obviate JIT generation - void generate(); +public slots: + void usersChanged(); protected: QVariantMap _metadata; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9b1fbb1d84..5a9fc816c5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -97,6 +97,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : // make sure we hear about newly connected nodes from our gatekeeper connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); + // update the metadata when a user (dis)connects + connect(this, &DomainServer::userConnected, &_metadata, &DomainMetadata::usersChanged); + connect(this, &DomainServer::userDisconnected, &_metadata, &DomainMetadata::usersChanged); + if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth()) { // we either read a certificate and private key or were not passed one // and completed login or did not need to @@ -767,12 +771,16 @@ QUrl DomainServer::oauthAuthorizationURL(const QUuid& stateUUID) { } void DomainServer::handleConnectedNode(SharedNodePointer newNode) { - - DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); - + DomainServerNodeData* nodeData = static_cast(newNode->getLinkedData()); + // reply back to the user with a PacketType::DomainList sendDomainListToNode(newNode, nodeData->getSendingSockAddr()); - + + // if this node is a user (unassigned Agent), signal + if (newNode->getType() == NodeType::Agent && !nodeData->wasAssigned()) { + emit userConnected(); + } + // send out this node to our other connected nodes broadcastNewNode(newNode); } @@ -1890,11 +1898,10 @@ void DomainServer::nodeAdded(SharedNodePointer node) { } void DomainServer::nodeKilled(SharedNodePointer node) { - // if this peer connected via ICE then remove them from our ICE peers hash _gatekeeper.removeICEPeer(node->getUUID()); - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); if (nodeData) { // if this node's UUID matches a static assignment we need to throw it back in the assignment queue @@ -1906,15 +1913,22 @@ void DomainServer::nodeKilled(SharedNodePointer node) { } } - // If this node was an Agent ask DomainServerNodeData to potentially remove the interpolation we stored - nodeData->removeOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, - uuidStringWithoutCurlyBraces(node->getUUID())); - // cleanup the connection secrets that we set up for this node (on the other nodes) foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) { SharedNodePointer otherNode = DependencyManager::get()->nodeWithUUID(otherNodeSessionUUID); if (otherNode) { - reinterpret_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + static_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + } + } + + if (node->getType() == NodeType::Agent) { + // if this node was an Agent ask DomainServerNodeData to remove the interpolation we potentially stored + nodeData->removeOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, + uuidStringWithoutCurlyBraces(node->getUUID())); + + // if this node is a user (unassigned Agent), signal + if (!nodeData->wasAssigned()) { + emit userDisconnected(); } } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 0a1df41f50..acda550ce5 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -92,6 +92,8 @@ private slots: signals: void iceServerChanged(); + void userConnected(); + void userDisconnected(); private: void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid()); From 5c293646b960007ab8dfff83712909db57f84861 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 2 Jun 2016 17:22:39 -0700 Subject: [PATCH 06/11] Segment metadata users --- domain-server/src/DomainMetadata.cpp | 17 +++++++++++------ domain-server/src/DomainMetadata.h | 10 ++++++++-- domain-server/src/DomainServer.cpp | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index c45a07e646..c92303ee7b 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,6 +15,14 @@ #include "DomainServerNodeData.h" +const QString DomainMetadata::USERS_KEY = "users"; +const QString DomainMetadata::USERS_NUM_KEY = "num_users"; +const QString DomainMetadata::USERS_HOSTNAMES_KEY = "users_hostnames"; + +DomainMetadata::DomainMetadata() : + _metadata{{ USERS_KEY, {} }} { +} + void DomainMetadata::usersChanged() { static const QString DEFAULT_HOSTNAME = "*"; @@ -39,13 +47,10 @@ void DomainMetadata::usersChanged() { } }); - static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; - _metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; - - static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; - _metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + QVariantMap users = {{ USERS_NUM_KEY, numConnectedUnassigned }, { USERS_HOSTNAMES_KEY, userHostnames }}; + _metadata[USERS_KEY] = users; #if DEV_BUILD - qDebug() << "Regenerated domain metadata - users:" << _metadata; + qDebug() << "Regenerated domain metadata - users:" << users; #endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index f92c40ce61..ae6dfe10a1 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -15,9 +15,15 @@ #include class DomainMetadata { + static const QString USERS_KEY; + static const QString USERS_NUM_KEY; + static const QString USERS_HOSTNAMES_KEY; + public: - QVariantMap toVariantMap() { return _metadata; } - QJsonObject toJSON() { return QJsonObject::fromVariantMap(_metadata); } + DomainMetadata(); + + QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } + QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS_KEY].toMap()); } public slots: void usersChanged(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 5a9fc816c5..c24fd02727 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1098,7 +1098,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { // Add the metadata to the heartbeat static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; - domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.toJSON(); + domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.getUsers(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); From 55e5c1f6e0bdbe1e2e23d73296954eaaee371f0b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 2 Jun 2016 18:01:59 -0700 Subject: [PATCH 07/11] Declare metadata descriptors --- domain-server/src/DomainMetadata.cpp | 73 +++++++++++++++++++++++----- domain-server/src/DomainMetadata.h | 30 ++++++++++-- domain-server/src/DomainServer.cpp | 9 ++-- 3 files changed, 93 insertions(+), 19 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index c92303ee7b..0481e9911d 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,29 +15,77 @@ #include "DomainServerNodeData.h" -const QString DomainMetadata::USERS_KEY = "users"; -const QString DomainMetadata::USERS_NUM_KEY = "num_users"; -const QString DomainMetadata::USERS_HOSTNAMES_KEY = "users_hostnames"; +const QString DomainMetadata::USERS = "users"; +const QString DomainMetadata::USERS_NUM_TOTAL = "num_users"; +const QString DomainMetadata::USERS_NUM_ANON = "num_anon_users"; +const QString DomainMetadata::USERS_HOSTNAMES = "user_hostnames"; +// users metadata will appear as (JSON): +// { "num_users": Number, +// "num_anon_users": Number, +// "user_hostnames": { : Number } +// } -DomainMetadata::DomainMetadata() : - _metadata{{ USERS_KEY, {} }} { +const QString DomainMetadata::DESCRIPTORS = "descriptors"; +const QString DomainMetadata::DESCRIPTORS_DESCRIPTION = "description"; +const QString DomainMetadata::DESCRIPTORS_CAPACITY = "capacity"; // parsed from security +const QString DomainMetadata::DESCRIPTORS_RESTRICTION = "restriction"; // parsed from ACL +const QString DomainMetadata::DESCRIPTORS_MATURITY = "maturity"; +const QString DomainMetadata::DESCRIPTORS_HOSTS = "hosts"; +const QString DomainMetadata::DESCRIPTORS_TAGS = "tags"; +// descriptors metadata will appear as (JSON): +// { "capacity": Number, +// TODO: "hours": String, // UTF-8 representation of the week, split into 15" segments +// "restriction": String, // enum of either OPEN, RESTRICTED_HIFI, RESTRICTED_ACL +// "maturity": String, // enum corresponding to ESRB ratings +// "hosts": [ String ], // capped list of usernames +// "description": String, // capped description +// TODO: "img": { +// "src": String, +// "type": String, +// "size": Number, +// "updated_at": Number, +// }, +// "tags": [ String ], // capped list of tags +// } + +// metadata will appear as (JSON): +// { users: , descriptors: } +// +// it is meant to be sent to and consumed by an external API + +DomainMetadata::DomainMetadata() { + _metadata[USERS] = {}; + _metadata[DESCRIPTORS] = {}; +} + +void DomainMetadata::setDescriptors(QVariantMap& settings) { + // TODO + + QVariantMap descriptors; + + #if DEV_BUILD || PR_BUILD + qDebug() << "Regenerated domain metadata - descriptors:" << descriptors; +#endif } void DomainMetadata::usersChanged() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); - int numConnectedUnassigned = 0; + int numConnected = 0; + int numConnectedAnonymously = 0; QVariantMap userHostnames; // figure out the breakdown of currently connected interface clients - nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { + nodeList->eachNode([&numConnected, &numConnectedAnonymously, &userHostnames](const SharedNodePointer& node) { auto linkedData = node->getLinkedData(); if (linkedData) { auto nodeData = static_cast(linkedData); if (!nodeData->wasAssigned()) { - ++numConnectedUnassigned; + ++numConnected; + + // TODO: numConnectedAnonymously // increment the count for this hostname (or the default if we don't have one) auto placeName = nodeData->getPlaceName(); @@ -47,10 +95,13 @@ void DomainMetadata::usersChanged() { } }); - QVariantMap users = {{ USERS_NUM_KEY, numConnectedUnassigned }, { USERS_HOSTNAMES_KEY, userHostnames }}; - _metadata[USERS_KEY] = users; + QVariantMap users = { + { USERS_NUM_TOTAL, numConnected }, + { USERS_NUM_ANON, numConnectedAnonymously }, + { USERS_HOSTNAMES, userHostnames }}; + _metadata[USERS] = users; -#if DEV_BUILD +#if DEV_BUILD || PR_BUILD qDebug() << "Regenerated domain metadata - users:" << users; #endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index ae6dfe10a1..e2f4674afc 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -14,16 +14,36 @@ #include #include -class DomainMetadata { - static const QString USERS_KEY; - static const QString USERS_NUM_KEY; - static const QString USERS_HOSTNAMES_KEY; +class DomainMetadata : public QObject { +Q_OBJECT + + static const QString USERS; + static const QString USERS_NUM_TOTAL; + static const QString USERS_NUM_ANON; + static const QString USERS_HOSTNAMES; + + static const QString DESCRIPTORS; + static const QString DESCRIPTORS_DESCRIPTION; + static const QString DESCRIPTORS_CAPACITY; + static const QString DESCRIPTORS_HOURS; + static const QString DESCRIPTORS_RESTRICTION; + static const QString DESCRIPTORS_MATURITY; + static const QString DESCRIPTORS_HOSTS; + static const QString DESCRIPTORS_TAGS; + static const QString DESCRIPTORS_IMG; + static const QString DESCRIPTORS_IMG_SRC; + static const QString DESCRIPTORS_IMG_TYPE; + static const QString DESCRIPTORS_IMG_SIZE; + static const QString DESCRIPTORS_IMG_UPDATED_AT; public: DomainMetadata(); QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } - QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS_KEY].toMap()); } + QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS].toMap()); } + QJsonObject getDescriptors() { return QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); } + + void setDescriptors(QVariantMap& settings); public slots: void usersChanged(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c24fd02727..88c4e215b2 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -94,13 +94,13 @@ DomainServer::DomainServer(int argc, char* argv[]) : qRegisterMetaType("DomainServerWebSessionData"); qRegisterMetaTypeStreamOperators("DomainServerWebSessionData"); - // make sure we hear about newly connected nodes from our gatekeeper - connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); - // update the metadata when a user (dis)connects connect(this, &DomainServer::userConnected, &_metadata, &DomainMetadata::usersChanged); connect(this, &DomainServer::userDisconnected, &_metadata, &DomainMetadata::usersChanged); + // make sure we hear about newly connected nodes from our gatekeeper + connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); + if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth()) { // we either read a certificate and private key or were not passed one // and completed login or did not need to @@ -116,6 +116,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : optionallyGetTemporaryName(args); } + + // update the metadata with current descriptors + _metadata.setDescriptors(_settingsManager.getSettingsMap()); } DomainServer::~DomainServer() { From 209ace1b867ae8cf64678e3b983c5137e7407ec7 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 3 Jun 2016 11:11:06 -0700 Subject: [PATCH 08/11] Include anonymously connected user metadata --- domain-server/src/DomainMetadata.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 0481e9911d..75ff0d697c 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -85,7 +85,9 @@ void DomainMetadata::usersChanged() { if (!nodeData->wasAssigned()) { ++numConnected; - // TODO: numConnectedAnonymously + if (nodeData->getUsername().isEmpty()) { + ++numConnectedAnonymously; + } // increment the count for this hostname (or the default if we don't have one) auto placeName = nodeData->getPlaceName(); From e04c6e8c44f716ac8497b3e2d6a9f78a63a4b709 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 3 Jun 2016 14:36:43 -0700 Subject: [PATCH 09/11] Add description/hosts/rating to settings UI --- .../resources/describe-settings.json | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index cac0d28e1e..ba00392cd7 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 1.2, + "version": 1.3, "settings": [ { "name": "metaverse", @@ -71,6 +71,76 @@ } ] }, + { + "name": "descriptors", + "label": "Description", + "help": "This data will be queryable from your server. It may be collected by High Fidelity and used to share your domain with others.", + "settings": [ + { + "name": "description", + "label": "Description", + "help": "A description of your domain (256 character limit)." + }, + { + "name": "maturity", + "label": "Maturity", + "help": "A maturity rating, available as a guideline for content on your domain.", + "default": "unrated", + "type": "select", + "options": [ + { + "value": "unrated", + "label": "Unrated" + }, + { + "value": "everyone", + "label": "Everyone" + }, + { + "value": "teen", + "label": "Teen (13+)" + }, + { + "value": "mature", + "label": "Mature (17+)" + }, + { + "value": "adult", + "label": "Adult (18+)" + } + ] + + }, + { + "name": "hosts", + "label": "Hosts", + "type": "table", + "help": "Usernames of hosts who can reliably show your domain to new visitors.", + "numbered": false, + "columns": [ + { + "name": "host", + "label": "Username", + "can_set": true + } + ] + }, + { + "name": "tags", + "label": "Tags", + "type": "table", + "help": "Common categories under which your domain falls.", + "numbered": false, + "columns": [ + { + "name": "tag", + "label": "Tag", + "can_set": true + } + ] + } + ] + }, { "name": "security", "label": "Security", From 09e0a2ced70d03fa1e4e17b74dbd9e25f41c89df Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 3 Jun 2016 14:59:58 -0700 Subject: [PATCH 10/11] Parse basic metadata into DomainMetadata --- domain-server/src/DomainMetadata.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 75ff0d697c..8fdbc2bbd1 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -10,6 +10,7 @@ #include "DomainMetadata.h" +#include #include #include @@ -35,7 +36,7 @@ const QString DomainMetadata::DESCRIPTORS_TAGS = "tags"; // descriptors metadata will appear as (JSON): // { "capacity": Number, // TODO: "hours": String, // UTF-8 representation of the week, split into 15" segments -// "restriction": String, // enum of either OPEN, RESTRICTED_HIFI, RESTRICTED_ACL +// "restriction": String, // enum of either open, hifi, or acl // "maturity": String, // enum corresponding to ESRB ratings // "hosts": [ String ], // capped list of usernames // "description": String, // capped description @@ -59,11 +60,25 @@ DomainMetadata::DomainMetadata() { } void DomainMetadata::setDescriptors(QVariantMap& settings) { - // TODO + const QString CAPACITY = "security.maximum_user_capacity"; + const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY); + unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0; - QVariantMap descriptors; + // TODO: Keep parity with ACL development. + const QString RESTRICTION = "security.restricted_access"; + const QString RESTRICTION_OPEN = "open"; + // const QString RESTRICTION_HIFI = "hifi"; + const QString RESTRICTION_ACL = "acl"; + const QVariant* isRestrictedVariant = valueForKeyPath(settings, RESTRICTION); + bool isRestricted = isRestrictedVariant ? isRestrictedVariant->toBool() : false; + QString restriction = isRestricted ? RESTRICTION_ACL : RESTRICTION_OPEN; - #if DEV_BUILD || PR_BUILD + QVariantMap descriptors = settings[DESCRIPTORS].toMap(); + descriptors[DESCRIPTORS_CAPACITY] = capacity; + descriptors[DESCRIPTORS_RESTRICTION] = restriction; + _metadata[DESCRIPTORS] = descriptors; + +#if DEV_BUILD || PR_BUILD qDebug() << "Regenerated domain metadata - descriptors:" << descriptors; #endif } From 9926c809179c8d98efdbce5afd497bd59b2ee63c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 8 Jun 2016 18:15:34 -0500 Subject: [PATCH 11/11] Only check user metadata before sending --- domain-server/src/DomainMetadata.cpp | 14 +++++++++++--- domain-server/src/DomainMetadata.h | 10 ++++++++++ domain-server/src/DomainServer.cpp | 5 +++++ domain-server/src/DomainServer.h | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 8fdbc2bbd1..26d2bb87ce 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -79,11 +79,11 @@ void DomainMetadata::setDescriptors(QVariantMap& settings) { _metadata[DESCRIPTORS] = descriptors; #if DEV_BUILD || PR_BUILD - qDebug() << "Regenerated domain metadata - descriptors:" << descriptors; + qDebug() << "Domain metadata descriptors set:" << descriptors; #endif } -void DomainMetadata::usersChanged() { +void DomainMetadata::updateUsers() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); @@ -119,6 +119,14 @@ void DomainMetadata::usersChanged() { _metadata[USERS] = users; #if DEV_BUILD || PR_BUILD - qDebug() << "Regenerated domain metadata - users:" << users; + qDebug() << "Domain metadata users updated:" << users; +#endif +} + +void DomainMetadata::usersChanged() { + ++_tic; + +#if DEV_BUILD || PR_BUILD + qDebug() << "Domain metadata users change detected"; #endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index e2f4674afc..7d58d43182 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -11,6 +11,8 @@ #ifndef hifi_DomainMetadata_h #define hifi_DomainMetadata_h +#include + #include #include @@ -39,17 +41,25 @@ Q_OBJECT public: DomainMetadata(); + // Returns the last set metadata + // If connected users have changed, metadata may need to be updated + // this should be checked by storing tic = getTic() between calls + // and testing it for equality before the next get (tic == getTic()) QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS].toMap()); } QJsonObject getDescriptors() { return QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); } + uint32_t getTic() { return _tic; } + void setDescriptors(QVariantMap& settings); + void updateUsers(); public slots: void usersChanged(); protected: QVariantMap _metadata; + uint32_t _tic{ 0 }; }; #endif // hifi_DomainMetadata_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 88c4e215b2..0f5498a575 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1101,6 +1101,11 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { // Add the metadata to the heartbeat static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + auto tic = _metadata.getTic(); + if (_metadataTic != tic) { + _metadataTic = tic; + _metadata.updateUsers(); + } domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.getUsers(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index acda550ce5..8b8409ff0a 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -171,6 +171,7 @@ private: DomainServerSettingsManager _settingsManager; DomainMetadata _metadata; + uint32_t _metadataTic{ 0 }; HifiSockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket;