From f81836c8300ee89146f07b4757d392f3f79bcc3a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 9 Apr 2018 18:28:59 -0700 Subject: [PATCH 1/5] support specification of named landing-points in serverless-domain json files --- interface/src/Application.cpp | 3 +++ libraries/entities/src/EntityTree.cpp | 12 ++++++++++++ libraries/entities/src/EntityTree.h | 4 ++++ libraries/networking/src/AddressManager.cpp | 12 ++++++++++-- libraries/networking/src/DomainHandler.cpp | 15 +++++++++++---- libraries/networking/src/DomainHandler.h | 6 +++++- libraries/networking/src/NodeList.cpp | 20 ++++++++++++++++---- 7 files changed, 61 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 18ba881573..9a97e9a42f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3146,6 +3146,9 @@ void Application::loadServerlessDomain(QUrl domainURL) { tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0); } + std::map namedPaths = tmpTree->getNamedPaths(); + nodeList->getDomainHandler().setIsConnected(true, namedPaths); + _fullSceneReceivedCounter++; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 2cf66911a4..d5c7b9c2d6 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2303,6 +2303,18 @@ bool EntityTree::readFromMap(QVariantMap& map) { _persistDataVersion = map["DataVersion"].toInt(); } + _namedPaths.clear(); + if (map.contains("Paths")) { + QVariantMap namedPathsMap = map["Paths"].toMap(); + for(QVariantMap::const_iterator iter = namedPathsMap.begin(); iter != namedPathsMap.end(); ++iter) { + QString namedPathName = iter.key(); + QString namedPathViewPoint = iter.value().toString(); + _namedPaths[namedPathName] = namedPathViewPoint; + } + } else { + _namedPaths["/"] = "/"; + } + // map will have a top-level list keyed as "Entities". This will be extracted // and iterated over. Each member of this list is converted to a QVariantMap, then // to a QScriptValue, and then to EntityItemProperties. These properties are used diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 5f69714432..791c030fc8 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -301,6 +301,8 @@ public: static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName); static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName); + std::map getNamedPaths() const { return _namedPaths; } + signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); @@ -417,6 +419,8 @@ private: static std::function _removeMaterialFromOverlayOperator; bool _serverlessDomain { false }; + + std::map _namedPaths; }; #endif // hifi_EntityTree_h diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 3c24cc796c..56b148a43c 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -29,7 +29,7 @@ #include "UserActivityLogger.h" #include "udt/PacketHeaders.h" -const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json"; +const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json?location=/"; const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; @@ -312,7 +312,15 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { _shareablePlaceName.clear(); setDomainInfo(lookupUrl, trigger); emit lookupResultsFinished(); - handlePath(DOMAIN_SPAWNING_POINT, LookupTrigger::Internal, false); + + QString path = DOMAIN_SPAWNING_POINT; + QUrlQuery queryArgs(lookupUrl); + const QString LOCATION_QUERY_KEY = "location"; + if (queryArgs.hasQueryItem(LOCATION_QUERY_KEY)) { + path = queryArgs.queryItemValue(LOCATION_QUERY_KEY); + } + + handlePath(path, LookupTrigger::Internal, false); return true; } diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index c20d6d73be..fe3b0abcb7 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -173,9 +173,7 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { QString previousHost = _domainURL.host(); _domainURL = domainURL; - if (domainURL.scheme() != URL_SCHEME_HIFI) { - setIsConnected(true); - } else if (previousHost != domainURL.host()) { + if (previousHost != domainURL.host()) { qCDebug(networking) << "Updated domain hostname to" << domainURL.host(); if (!domainURL.host().isEmpty()) { @@ -250,6 +248,14 @@ void DomainHandler::activateICEPublicSocket() { emit completedSocketDiscovery(); } +QString DomainHandler::getViewPointFromNamedPath(QString namedPath) { + auto lookup = _namedPaths.find(namedPath); + if (lookup != _namedPaths.end()) { + return lookup->second; + } + return DOMAIN_SPAWNING_POINT; +} + void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) { for (int i = 0; i < hostInfo.addresses().size(); i++) { if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { @@ -279,7 +285,8 @@ void DomainHandler::completedIceServerHostnameLookup() { emit iceSocketAndIDReceived(); } -void DomainHandler::setIsConnected(bool isConnected) { +void DomainHandler::setIsConnected(bool isConnected, std::map namedPaths) { + _namedPaths = namedPaths; if (_isConnected != isConnected) { _isConnected = isConnected; diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index fbc60e2492..760b2f8235 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -73,9 +73,11 @@ public: void activateICEPublicSocket(); bool isConnected() const { return _isConnected; } - void setIsConnected(bool isConnected); + void setIsConnected(bool isConnected, std::map namedPaths = std::map()); bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; } + QString getViewPointFromNamedPath(QString namedPath); + bool hasSettings() const { return !_settingsObject.isEmpty(); } void requestDomainSettings(); const QJsonObject& getSettingsObject() const { return _settingsObject; } @@ -200,6 +202,8 @@ private: int _checkInPacketsSinceLastReply { 0 }; QTimer _apiRefreshTimer; + + std::map _namedPaths; }; const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" }; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index cb0d2e4cd5..3c2b4cd336 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -413,7 +413,14 @@ void NodeList::sendDomainServerCheckIn() { } void NodeList::handleDSPathQuery(const QString& newPath) { - if (_domainHandler.isSocketKnown()) { + if (_domainHandler.isServerless()) { + if (_domainHandler.isConnected()) { + auto viewpoint = _domainHandler.getViewPointFromNamedPath(newPath); + DependencyManager::get()->goToViewpointForPath(viewpoint, newPath); + } else { + _domainHandler.setPendingPath(newPath); + } + } else if (_domainHandler.isSocketKnown()) { // if we have a DS socket we assume it will get this packet and send if off right away sendDSPathQuery(newPath); } else { @@ -427,10 +434,15 @@ void NodeList::sendPendingDSPathQuery() { QString pendingPath = _domainHandler.getPendingPath(); if (!pendingPath.isEmpty()) { - qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath; - // this is a slot triggered if we just established a network link with a DS and want to send a path query - sendDSPathQuery(_domainHandler.getPendingPath()); + if (_domainHandler.isServerless()) { + auto viewpoint = _domainHandler.getViewPointFromNamedPath(pendingPath); + DependencyManager::get()->goToViewpointForPath(viewpoint, pendingPath); + } else { + qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath; + // this is a slot triggered if we just established a network link with a DS and want to send a path query + sendDSPathQuery(_domainHandler.getPendingPath()); + } // clear whatever the pending path was _domainHandler.clearPendingPath(); From ee3e8093e18bd06f1564e594bd6b882aeea228d4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 10 Apr 2018 10:19:35 -0700 Subject: [PATCH 2/5] update tutorial content to include default landing-point --- cmake/externals/serverless-content/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index 4d0773f5f5..6235205aad 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v2.zip - URL_MD5 d76bdb3e2bf7ae5d20115bd97b0c44a8 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC67.zip + URL_MD5 3fc4b7332be771d71b43b6d688de9aa7 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From a56f3f4a1029742fd668d9283f241ace9fc4138a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Apr 2018 19:06:12 -0700 Subject: [PATCH 3/5] code review --- interface/src/Application.cpp | 3 ++- libraries/networking/src/AddressManager.cpp | 4 +++- libraries/networking/src/DomainHandler.cpp | 21 +++++++++++++++------ libraries/networking/src/DomainHandler.h | 6 ++++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9a97e9a42f..37fd2da56f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3147,7 +3147,8 @@ void Application::loadServerlessDomain(QUrl domainURL) { } std::map namedPaths = tmpTree->getNamedPaths(); - nodeList->getDomainHandler().setIsConnected(true, namedPaths); + nodeList->getDomainHandler().connectedToServerless(namedPaths); + _fullSceneReceivedCounter++; } diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 56b148a43c..431a2e8ad5 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -29,7 +29,7 @@ #include "UserActivityLogger.h" #include "udt/PacketHeaders.h" -const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json?location=/"; +const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json"; const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; @@ -318,6 +318,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { const QString LOCATION_QUERY_KEY = "location"; if (queryArgs.hasQueryItem(LOCATION_QUERY_KEY)) { path = queryArgs.queryItemValue(LOCATION_QUERY_KEY); + } else { + path = DEFAULT_NAMED_PATH; } handlePath(path, LookupTrigger::Internal, false); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index fe3b0abcb7..cd8064c4c0 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -177,9 +177,11 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { qCDebug(networking) << "Updated domain hostname to" << domainURL.host(); if (!domainURL.host().isEmpty()) { - // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname - qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData()); - QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&))); + if (domainURL.scheme() == URL_SCHEME_HIFI) { + // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname + qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData()); + QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&))); + } DependencyManager::get()->flagTimeForConnectionStep( LimitedNodeList::ConnectionStep::SetDomainHostname); @@ -253,7 +255,10 @@ QString DomainHandler::getViewPointFromNamedPath(QString namedPath) { if (lookup != _namedPaths.end()) { return lookup->second; } - return DOMAIN_SPAWNING_POINT; + if (namedPath == DEFAULT_NAMED_PATH) { + return DOMAIN_SPAWNING_POINT; + } + return ""; } void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) { @@ -285,8 +290,7 @@ void DomainHandler::completedIceServerHostnameLookup() { emit iceSocketAndIDReceived(); } -void DomainHandler::setIsConnected(bool isConnected, std::map namedPaths) { - _namedPaths = namedPaths; +void DomainHandler::setIsConnected(bool isConnected) { if (_isConnected != isConnected) { _isConnected = isConnected; @@ -304,6 +308,11 @@ void DomainHandler::setIsConnected(bool isConnected, std::map } } +void DomainHandler::connectedToServerless(std::map namedPaths) { + _namedPaths = namedPaths; + setIsConnected(true); +} + void DomainHandler::requestDomainSettings() { qCDebug(networking) << "Requesting settings from domain server"; diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 760b2f8235..7137b8084d 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -73,9 +73,11 @@ public: void activateICEPublicSocket(); bool isConnected() const { return _isConnected; } - void setIsConnected(bool isConnected, std::map namedPaths = std::map()); + void setIsConnected(bool isConnected); bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; } + void connectedToServerless(std::map namedPaths); + QString getViewPointFromNamedPath(QString namedPath); bool hasSettings() const { return !_settingsObject.isEmpty(); } @@ -207,6 +209,6 @@ private: }; const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" }; - +const QString DEFAULT_NAMED_PATH { "/" }; #endif // hifi_DomainHandler_h From 0e081a394421a84b6ed161817289918e53814d07 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Apr 2018 10:42:22 -0700 Subject: [PATCH 4/5] code review --- libraries/entities/src/EntityTree.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d5c7b9c2d6..63d9a3ab16 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2311,8 +2311,6 @@ bool EntityTree::readFromMap(QVariantMap& map) { QString namedPathViewPoint = iter.value().toString(); _namedPaths[namedPathName] = namedPathViewPoint; } - } else { - _namedPaths["/"] = "/"; } // map will have a top-level list keyed as "Entities". This will be extracted From 426d18ed2a7755b38556ac258d54bef951d5d4ec Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Apr 2018 13:20:06 -0700 Subject: [PATCH 5/5] code review --- libraries/networking/src/NodeList.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 3c2b4cd336..13931be2ac 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -416,7 +416,9 @@ void NodeList::handleDSPathQuery(const QString& newPath) { if (_domainHandler.isServerless()) { if (_domainHandler.isConnected()) { auto viewpoint = _domainHandler.getViewPointFromNamedPath(newPath); - DependencyManager::get()->goToViewpointForPath(viewpoint, newPath); + if (!newPath.isEmpty()) { + DependencyManager::get()->goToViewpointForPath(viewpoint, newPath); + } } else { _domainHandler.setPendingPath(newPath); } @@ -437,7 +439,9 @@ void NodeList::sendPendingDSPathQuery() { if (_domainHandler.isServerless()) { auto viewpoint = _domainHandler.getViewPointFromNamedPath(pendingPath); - DependencyManager::get()->goToViewpointForPath(viewpoint, pendingPath); + if (!pendingPath.isEmpty()) { + DependencyManager::get()->goToViewpointForPath(viewpoint, pendingPath); + } } else { qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath; // this is a slot triggered if we just established a network link with a DS and want to send a path query @@ -510,7 +514,7 @@ void NodeList::processDomainServerPathResponse(QSharedPointer m QString viewpoint = QString::fromUtf8(message->getRawMessage() + message->getPosition(), numViewpointBytes); // Hand it off to the AddressManager so it can handle it as a relative viewpoint - if (DependencyManager::get()->goToViewpointForPath(viewpoint, pathQuery)) { + if (!pathQuery.isEmpty() && DependencyManager::get()->goToViewpointForPath(viewpoint, pathQuery)) { qCDebug(networking) << "Going to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery; } else { qCDebug(networking) << "Could not go to viewpoint" << viewpoint