From 46173439ed2cb860d6df14dc8e7531b477d2c8e0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 1 Feb 2020 12:46:28 +1300 Subject: [PATCH] Enable serverless domains via HTTP and HTTPS --- interface/src/Application.cpp | 40 +++++++++++---------- interface/src/Application.h | 2 +- libraries/networking/src/AddressManager.cpp | 7 ++-- libraries/octree/src/Octree.cpp | 19 +++++++++- libraries/octree/src/Octree.h | 1 + 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6a1925c7fb..ccca85e7ec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4059,7 +4059,7 @@ void Application::setIsServerlessMode(bool serverlessDomain) { } } -std::map Application::prepareServerlessDomainContents(QUrl domainURL) { +std::map Application::prepareServerlessDomainContents(QUrl domainURL, QByteArray data) { QUuid serverlessSessionID = QUuid::createUuid(); getMyAvatar()->setSessionUUID(serverlessSessionID); auto nodeList = DependencyManager::get(); @@ -4070,14 +4070,13 @@ std::map Application::prepareServerlessDomainContents(QUrl dom permissions.setAll(true); nodeList->setPermissions(permissions); - // we can't import directly into the main tree because we would need to lock it, and - // Octree::readFromURL calls loop.exec which can run code which will also attempt to lock the tree. + // FIXME: Lock the main tree and import directly into it. EntityTreePointer tmpTree(new EntityTree()); tmpTree->setIsServerlessMode(true); tmpTree->createRootElement(); auto myAvatar = getMyAvatar(); tmpTree->setMyAvatar(myAvatar); - bool success = tmpTree->readFromURL(domainURL.toString()); + bool success = tmpTree->readFromByteArray(domainURL.toString(), data); if (success) { tmpTree->reaverageOctreeElements(); tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0); @@ -4100,12 +4099,26 @@ void Application::loadServerlessDomain(QUrl domainURL) { return; } - auto namedPaths = prepareServerlessDomainContents(domainURL); - auto nodeList = DependencyManager::get(); + QString trimmedUrl = domainURL.toString().trimmed(); + bool DEFAULT_IS_OBSERVABLE = true; + const qint64 DEFAULT_CALLER_ID = -1; + auto request = DependencyManager::get()->createResourceRequest( + this, trimmedUrl, DEFAULT_IS_OBSERVABLE, DEFAULT_CALLER_ID, "Application::loadServerlessDomain"); - nodeList->getDomainHandler().connectedToServerless(namedPaths); + if (!request) { + return; + } - _fullSceneReceivedCounter++; + connect(request, &ResourceRequest::finished, this, [=]() { + if (request->getResult() == ResourceRequest::Success) { + auto namedPaths = prepareServerlessDomainContents(domainURL, request->getData()); + auto nodeList = DependencyManager::get(); + nodeList->getDomainHandler().connectedToServerless(namedPaths); + _fullSceneReceivedCounter++; + } + request->deleteLater(); + }); + request->send(); } void Application::loadErrorDomain(QUrl domainURL) { @@ -4114,16 +4127,7 @@ void Application::loadErrorDomain(QUrl domainURL) { return; } - if (domainURL.isEmpty()) { - return; - } - - auto namedPaths = prepareServerlessDomainContents(domainURL); - auto nodeList = DependencyManager::get(); - - nodeList->getDomainHandler().loadedErrorDomain(namedPaths); - - _fullSceneReceivedCounter++; + loadServerlessDomain(domainURL); } bool Application::importImage(const QString& urlString) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 114bca864d..198f5ef7cf 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -464,7 +464,7 @@ public slots: void setPreferredCursor(const QString& cursor); void setIsServerlessMode(bool serverlessDomain); - std::map prepareServerlessDomainContents(QUrl domainURL); + std::map prepareServerlessDomainContents(QUrl domainURL, QByteArray data); void loadServerlessDomain(QUrl domainURL); void loadErrorDomain(QUrl domainURL); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 50e2657622..5c821bdbf5 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -358,11 +358,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { emit lookupResultsFinished(); return true; - } else if (lookupUrl.scheme() == HIFI_URL_SCHEME_FILE) { - // TODO -- once Octree::readFromURL no-longer takes over the main event-loop, serverless-domain urls can - // be loaded over http(s) - // lookupUrl.scheme() == URL_SCHEME_HTTP || - // lookupUrl.scheme() == HIFI_URL_SCHEME_HTTPS || + } else if (lookupUrl.scheme() == HIFI_URL_SCHEME_FILE || lookupUrl.scheme() == HIFI_URL_SCHEME_HTTPS + || lookupUrl.scheme() == HIFI_URL_SCHEME_HTTP) { // TODO once a file can return a connection refusal if there were to be some kind of load error, we'd // need to store the previous domain tried in _lastVisitedURL. For now , do not store it. diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index df02b54856..aac0de27a1 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -738,7 +738,6 @@ bool Octree::readFromURL( ) { QString trimmedUrl = urlString.trimmed(); QString marketplaceID = getMarketplaceID(trimmedUrl); - qDebug() << "!!!!! going to createResourceRequest " << callerId; auto request = std::unique_ptr( DependencyManager::get()->createResourceRequest( this, trimmedUrl, isObservable, callerId, "Octree::readFromURL")); @@ -770,6 +769,24 @@ bool Octree::readFromURL( return readFromStream(data.size(), inputStream, marketplaceID); } +bool Octree::readFromByteArray( + const QString& urlString, + const QByteArray& data +) { + QString trimmedUrl = urlString.trimmed(); + QString marketplaceID = getMarketplaceID(trimmedUrl); + + QByteArray uncompressedJsonData; + bool wasCompressed = gunzip(data, uncompressedJsonData); + + if (wasCompressed) { + QDataStream inputStream(uncompressedJsonData); + return readFromStream(uncompressedJsonData.size(), inputStream, marketplaceID); + } + + QDataStream inputStream(data); + return readFromStream(data.size(), inputStream, marketplaceID); +} bool Octree::readFromStream( uint64_t streamLength, diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 4f994da60e..45dae3049d 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -217,6 +217,7 @@ public: // Octree importers bool readFromFile(const char* filename); bool readFromURL(const QString& url, const bool isObservable = true, const qint64 callerId = -1); // will support file urls as well... + bool readFromByteArray(const QString& url, const QByteArray& byteArray); bool readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID=""); bool readSVOFromStream(uint64_t streamLength, QDataStream& inputStream); bool readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");