diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 8ab53d3b87..4ca2439996 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -45,25 +45,67 @@ AssetServer::AssetServer(ReceivedMessage& message) : } void AssetServer::run() { + + qDebug() << "Waiting for connection to domain to request settings from domain-server."; + + // wait until we have the domain-server settings, otherwise we bail + DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler(); + connect(&domainHandler, &DomainHandler::settingsReceived, this, &AssetServer::completeSetup); + connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &AssetServer::domainSettingsRequestFailed); + ThreadedAssignment::commonInit(ASSET_SERVER_LOGGING_TARGET_NAME, NodeType::AssetServer); +} +void AssetServer::completeSetup() { auto nodeList = DependencyManager::get<NodeList>(); - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - const QString RESOURCES_PATH = "assets"; + auto& domainHandler = nodeList->getDomainHandler(); + const QJsonObject& settingsObject = domainHandler.getSettingsObject(); - _resourcesDirectory = QDir(ServerPathUtils::getDataDirectory()).filePath(RESOURCES_PATH); + static const QString ASSET_SERVER_SETTINGS_KEY = "asset_server"; + + if (!settingsObject.contains(ASSET_SERVER_SETTINGS_KEY)) { + qCritical() << "Received settings from the domain-server with no asset-server section. Stopping assignment."; + setFinished(true); + return; + } + + auto assetServerObject = settingsObject[ASSET_SERVER_SETTINGS_KEY].toObject(); + + // get the path to the asset folder from the domain server settings + static const QString ASSETS_PATH_OPTION = "assets_path"; + auto assetsJSONValue = assetServerObject[ASSETS_PATH_OPTION]; + + if (!assetsJSONValue.isString()) { + qCritical() << "Received an assets path from the domain-server that could not be parsed. Stopping assignment."; + setFinished(true); + return; + } + + auto assetsPathString = assetsJSONValue.toString(); + QDir assetsPath { assetsPathString }; + QString absoluteFilePath = assetsPath.absolutePath(); + + if (assetsPath.isRelative()) { + // if the domain settings passed us a relative path, make an absolute path that is relative to the + // default data directory + absoluteFilePath = ServerPathUtils::getDataFilePath("assets/" + assetsPathString); + } + + _resourcesDirectory = QDir(absoluteFilePath); qDebug() << "Creating resources directory"; _resourcesDirectory.mkpath("."); - bool noExistingAssets = !_resourcesDirectory.exists() \ - || _resourcesDirectory.entryList(QDir::Files).size() == 0; + bool noExistingAssets = !_resourcesDirectory.exists() || _resourcesDirectory.entryList(QDir::Files).size() == 0; if (noExistingAssets) { - qDebug() << "Asset resources directory not found, searching for existing asset resources"; + qDebug() << "Asset resources directory empty, searching for existing asset resources to migrate"; QString oldDataDirectory = QCoreApplication::applicationDirPath(); - auto oldResourcesDirectory = QDir(oldDataDirectory).filePath("resources/" + RESOURCES_PATH); + + const QString OLD_RESOURCES_PATH = "assets"; + + auto oldResourcesDirectory = QDir(oldDataDirectory).filePath("resources/" + OLD_RESOURCES_PATH); if (QDir(oldResourcesDirectory).exists()) { @@ -111,10 +153,12 @@ void AssetServer::run() { auto hexHash = hash.toHex(); qDebug() << "\tMoving " << filename << " to " << hexHash; - + file.rename(_resourcesDirectory.absoluteFilePath(hexHash) + "." + fileInfo.suffix()); } } + + nodeList->addNodeTypeToInterestSet(NodeType::Agent); } void AssetServer::handleAssetGetInfo(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) { diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index fe83ce92a6..7d6e26af08 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -29,6 +29,8 @@ public slots: void run(); private slots: + void completeSetup(); + void handleAssetGetInfo(QSharedPointer<ReceivedMessage> packet, SharedNodePointer senderNode); void handleAssetGet(QSharedPointer<ReceivedMessage> packet, SharedNodePointer senderNode); void handleAssetUpload(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer senderNode); diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 891c586a6a..014d9f3767 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -168,7 +168,7 @@ }, { "name": "asset_server", - "label": "Asset Server", + "label": "Asset Server (ATP)", "assignment-types": [3], "settings": [ { @@ -178,6 +178,14 @@ "help": "Assigns an asset-server in your domain to serve files to clients via the ATP protocol (over UDP)", "default": true, "advanced": true + }, + { + "name": "assets_path", + "type": "string", + "label": "Assets Path", + "help": "The path to the directory assets are stored in.<br/>If this path is relative, it will be relative to the application data directory.<br/>If you change this path you will need to manually copy any existing assets from the previous directory.", + "default": "", + "advanced": true } ] }, @@ -377,7 +385,7 @@ { "name": "persistFilePath", "label": "Entities File Path", - "help": "The path to the file entities are stored in. If this path is relative it will be relative to the application data directory. The filename must end in .json.gz.", + "help": "The path to the file entities are stored in.<br/>If this path is relative it will be relative to the application data directory.<br/>The filename must end in .json.gz.", "placeholder": "models.json.gz", "default": "models.json.gz", "advanced": true diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9e3b69854f..9e13c8e6fa 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -120,6 +120,14 @@ DomainServer::~DomainServer() { DependencyManager::destroy<LimitedNodeList>(); } +void DomainServer::queuedQuit(QString quitMessage, int exitCode) { + if (!quitMessage.isEmpty()) { + qCritical() << qPrintable(quitMessage); + } + + QCoreApplication::exit(exitCode); +} + void DomainServer::aboutToQuit() { // clear the log handler so that Qt doesn't call the destructor on LogHandler @@ -164,8 +172,11 @@ bool DomainServer::optionallyReadX509KeyAndCertificate() { qDebug() << "TCP server listening for HTTPS connections on" << DOMAIN_SERVER_HTTPS_PORT; } else if (!certPath.isEmpty() || !keyPath.isEmpty()) { - qDebug() << "Missing certificate or private key. domain-server will now quit."; - QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); + static const QString MISSING_CERT_ERROR_MSG = "Missing certificate or private key. domain-server will now quit."; + static const int MISSING_CERT_ERROR_CODE = 3; + + QMetaObject::invokeMethod(this, "queuedQuit", Qt::QueuedConnection, + Q_ARG(QString, MISSING_CERT_ERROR_MSG), Q_ARG(int, MISSING_CERT_ERROR_CODE)); return false; } @@ -199,8 +210,10 @@ bool DomainServer::optionallySetupOAuth() { || _hostname.isEmpty() || _oauthClientID.isEmpty() || _oauthClientSecret.isEmpty()) { - qDebug() << "Missing OAuth provider URL, hostname, client ID, or client secret. domain-server will now quit."; - QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); + static const QString MISSING_OAUTH_INFO_MSG = "Missing OAuth provider URL, hostname, client ID, or client secret. domain-server will now quit."; + static const int MISSING_OAUTH_INFO_ERROR_CODE = 4; + QMetaObject::invokeMethod(this, "queuedQuit", Qt::QueuedConnection, + Q_ARG(QString, MISSING_OAUTH_INFO_MSG), Q_ARG(int, MISSING_OAUTH_INFO_ERROR_CODE)); return false; } else { qDebug() << "OAuth will be used to identify clients using provider at" << _oauthProviderURL.toString(); @@ -404,9 +417,13 @@ bool DomainServer::resetAccountManagerAccessToken() { return true; } else { - qDebug() << "Missing OAuth provider URL, but a domain-server feature was required that requires authentication." << - "domain-server will now quit."; - QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); + static const QString MISSING_OAUTH_PROVIDER_MSG = + QString("Missing OAuth provider URL, but a domain-server feature was required that requires authentication.") + + QString("domain-server will now quit."); + static const int MISSING_OAUTH_PROVIDER_ERROR_CODE = 5; + QMetaObject::invokeMethod(this, "queuedQuit", Qt::QueuedConnection, + Q_ARG(QString, MISSING_OAUTH_PROVIDER_MSG), + Q_ARG(int, MISSING_OAUTH_PROVIDER_ERROR_CODE)); return false; } @@ -517,11 +534,6 @@ void DomainServer::setupICEHeartbeatForFullNetworking() { } } -void DomainServer::loginFailed() { - qDebug() << "Login to data server has failed. domain-server will now quit"; - QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); -} - void DomainServer::parseAssignmentConfigs(QSet<Assignment::Type>& excludedTypes) { // check for configs from the command line, these take precedence const QString ASSIGNMENT_CONFIG_REGEX_STRING = "config-([\\d]+)"; diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index afdd7bd26e..326ca3e1a8 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -65,7 +65,6 @@ public slots: private slots: void aboutToQuit(); - void loginFailed(); void setupPendingAssignmentCredits(); void sendPendingTransactionsToServer(); @@ -77,6 +76,8 @@ private slots: void handleTempDomainSuccess(QNetworkReply& requestReply); void handleTempDomainError(QNetworkReply& requestReply); + + void queuedQuit(QString quitMessage, int exitCode); private: void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid()); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 98bb63241e..49ae03ccd4 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -62,9 +62,14 @@ DomainServerSettingsManager::DomainServerSettingsManager() : } } - qCritical() << "Did not find settings decription in JSON at" << SETTINGS_DESCRIPTION_RELATIVE_PATH - << "- Unable to continue. domain-server will quit."; - QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + static const QString MISSING_SETTINGS_DESC_MSG = + QString("Did not find settings decription in JSON at %1 - Unable to continue. domain-server will quit.") + .arg(SETTINGS_DESCRIPTION_RELATIVE_PATH); + static const int MISSING_SETTINGS_DESC_ERROR_CODE = 6; + + QMetaObject::invokeMethod(QCoreApplication::instance(), "queuedQuit", Qt::QueuedConnection, + Q_ARG(QString, MISSING_SETTINGS_DESC_MSG), + Q_ARG(int, MISSING_SETTINGS_DESC_ERROR_CODE)); } void DomainServerSettingsManager::processSettingsRequestPacket(QSharedPointer<ReceivedMessage> message) {