From 1df0dce971d066dc3b6b42d021b616753ae71c01 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Apr 2016 14:38:26 -0700 Subject: [PATCH 1/3] use ResourceRequest in Agent to handle ATP scripts --- assignment-client/src/Agent.cpp | 53 +++++++++++--------- assignment-client/src/Agent.h | 2 +- libraries/networking/src/ResourceRequest.cpp | 1 + 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 740f456595..dc35885f8d 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -164,52 +164,57 @@ void Agent::requestScript() { scriptURL = QUrl(_payload); } - // setup a network access manager and - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + // make sure this is not a script request for the file scheme + if (scriptURL.scheme() == URL_SCHEME_FILE) { + qWarning() << "Cannot load script for Agent from local filesystem."; + scriptRequestFinished(); + return; + } - QNetworkDiskCache* cache = new QNetworkDiskCache(); - QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache"); - networkAccessManager.setCache(cache); + auto request = ResourceManager::createResourceRequest(this, scriptURL); - QNetworkRequest networkRequest = QNetworkRequest(scriptURL); - networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + if (!request) { + qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString(); + scriptRequestFinished(); + return; + } // setup a timeout for script request static const int SCRIPT_TIMEOUT_MS = 10000; - _scriptRequestTimeout = new QTimer(this); - connect(_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); - _scriptRequestTimeout->start(SCRIPT_TIMEOUT_MS); + connect(&_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); + _scriptRequestTimeout.start(SCRIPT_TIMEOUT_MS); + + connect(request, &ResourceRequest::finished, this, &Agent::scriptRequestFinished); - qDebug() << "Downloading script at" << scriptURL.toString(); - QNetworkReply* reply = networkAccessManager.get(networkRequest); - connect(reply, &QNetworkReply::finished, this, &Agent::scriptRequestFinished); + qInfo() << "Requesting script at URL" << qPrintable(request->getUrl().toString()); + + request->send(); } void Agent::scriptRequestFinished() { - auto reply = qobject_cast(sender()); + auto request = qobject_cast(sender()); - _scriptRequestTimeout->stop(); + _scriptRequestTimeout.stop(); - if (reply && reply->error() == QNetworkReply::NoError) { - _scriptContents = reply->readAll(); - qDebug() << "Downloaded script:" << _scriptContents; + if (request && request->getResult() == ResourceRequest::Success) { + _scriptContents = request->getData(); + qInfo() << "Downloaded script:" << _scriptContents; // we could just call executeScript directly - we use a QueuedConnection to allow scriptRequestFinished // to return before calling executeScript QMetaObject::invokeMethod(this, "executeScript", Qt::QueuedConnection); } else { - if (reply) { - qDebug() << "Failed to download script at" << reply->url().toString() << " - bailing on assignment."; - qDebug() << "QNetworkReply error was" << reply->errorString(); + if (request) { + qWarning() << "Failed to download script at" << request->getUrl().toString() << " - bailing on assignment."; + qWarning() << "ResourceRequest error was" << request->getResult(); } else { - qDebug() << "Failed to download script - request timed out. Bailing on assignment."; + qWarning() << "Failed to download script - request timed out. Bailing on assignment."; } setFinished(true); } - reply->deleteLater(); + request->deleteLater(); } void Agent::executeScript() { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index d86b99db33..8fb6c10f0b 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -83,7 +83,7 @@ private: void sendAvatarBillboardPacket(); QString _scriptContents; - QTimer* _scriptRequestTimeout { nullptr }; + QTimer _scriptRequestTimeout; bool _isListeningToAudioStream = false; SharedSoundPointer _avatarSound; int _numAvatarSoundSentBytes = 0; diff --git a/libraries/networking/src/ResourceRequest.cpp b/libraries/networking/src/ResourceRequest.cpp index e6402d6b25..bce6af7091 100644 --- a/libraries/networking/src/ResourceRequest.cpp +++ b/libraries/networking/src/ResourceRequest.cpp @@ -20,6 +20,7 @@ void ResourceRequest::send() { QMetaObject::invokeMethod(this, "send", Qt::QueuedConnection); return; } + Q_ASSERT(_state == NotStarted); _state = InProgress; From bf3324fc6bad5e0cbfac6a6a4803b8766a1ba485 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Apr 2016 15:28:12 -0700 Subject: [PATCH 2/3] hold download of ATP script if Asset Server isn't ready --- assignment-client/src/Agent.cpp | 39 +++++++++++++++++++++++++++++---- assignment-client/src/Agent.h | 5 ++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index dc35885f8d..3305beae35 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -144,6 +144,9 @@ void Agent::run() { connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); messagesThread->start(); + // make sure we hear about connected nodes so we can grab an ATP script if a request is pending + connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &Agent::nodeActivated); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer }); @@ -181,20 +184,48 @@ void Agent::requestScript() { // setup a timeout for script request static const int SCRIPT_TIMEOUT_MS = 10000; - connect(&_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); - _scriptRequestTimeout.start(SCRIPT_TIMEOUT_MS); - + _scriptRequestTimeout = new QTimer; + connect(_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); + _scriptRequestTimeout->start(SCRIPT_TIMEOUT_MS); + connect(request, &ResourceRequest::finished, this, &Agent::scriptRequestFinished); + if (scriptURL.scheme() == URL_SCHEME_ATP) { + // we have an ATP URL for the script - if we're not currently connected to the AssetServer + // then wait for the nodeConnected signal to fire off the request + + auto assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); + if (!assetServer || assetServer->getActiveSocket()) { + qDebug() << "Waiting to connect to Asset Server for ATP script download."; + _pendingScriptRequest = request; + + return; + } + } + qInfo() << "Requesting script at URL" << qPrintable(request->getUrl().toString()); request->send(); } +void Agent::nodeActivated(SharedNodePointer activatedNode) { + if (_pendingScriptRequest) { + qInfo() << "Requesting script at URL" << qPrintable(_pendingScriptRequest->getUrl().toString()); + + _pendingScriptRequest->send(); + + _pendingScriptRequest = nullptr; + } +} + void Agent::scriptRequestFinished() { auto request = qobject_cast(sender()); - _scriptRequestTimeout.stop(); + // stop the script request timeout, if it's running + if (_scriptRequestTimeout) { + QMetaObject::invokeMethod(_scriptRequestTimeout, "stop"); + _scriptRequestTimeout->deleteLater(); + } if (request && request->getResult() == ResourceRequest::Success) { _scriptContents = request->getData(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 8fb6c10f0b..2b0d22385d 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -69,6 +69,8 @@ private slots: void processAgentAvatarAndAudio(float deltaTime); + void nodeActivated(SharedNodePointer activatedNode); + private: std::unique_ptr _scriptEngine; EntityEditPacketSender _entityEditSender; @@ -83,7 +85,8 @@ private: void sendAvatarBillboardPacket(); QString _scriptContents; - QTimer _scriptRequestTimeout; + QTimer* _scriptRequestTimeout { nullptr }; + ResourceRequest* _pendingScriptRequest { nullptr }; bool _isListeningToAudioStream = false; SharedSoundPointer _avatarSound; int _numAvatarSoundSentBytes = 0; From 76af3efe73eb29a8601d44329b10477d65d3b8b3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 17:59:27 -0700 Subject: [PATCH 3/3] fix for active socket check on ATP script download --- assignment-client/src/Agent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 3305beae35..d0433b5d60 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -195,7 +195,7 @@ void Agent::requestScript() { // then wait for the nodeConnected signal to fire off the request auto assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - if (!assetServer || assetServer->getActiveSocket()) { + if (!assetServer || !assetServer->getActiveSocket()) { qDebug() << "Waiting to connect to Asset Server for ATP script download."; _pendingScriptRequest = request;