Merge pull request #10877 from sethalves/atp-client

Atp client
This commit is contained in:
Andrew Meadows 2017-07-07 14:04:50 -07:00 committed by GitHub
commit 665aa92da2
8 changed files with 486 additions and 277 deletions

View file

@ -17,8 +17,8 @@ set_target_properties(ac-client PROPERTIES FOLDER "Tools")
add_subdirectory(skeleton-dump)
set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools")
add_subdirectory(atp-get)
set_target_properties(atp-get PROPERTIES FOLDER "Tools")
add_subdirectory(atp-client)
set_target_properties(atp-client PROPERTIES FOLDER "Tools")
add_subdirectory(oven)
set_target_properties(oven PROPERTIES FOLDER "Tools")

View file

@ -14,6 +14,7 @@
#include <QLoggingCategory>
#include <QCommandLineParser>
#include <NetworkLogging.h>
#include <NetworkingConstants.h>
#include <SharedLogging.h>
#include <AddressManager.h>
#include <DependencyManager.h>
@ -33,6 +34,9 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
const QCommandLineOption verboseOutput("v", "verbose output");
parser.addOption(verboseOutput);
const QCommandLineOption authOption("u", "set usename and pass", "username:password");
parser.addOption(authOption);
const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1");
parser.addOption(domainAddressOption);
@ -81,6 +85,18 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
listenPort = parser.value(listenPortOption).toInt();
}
if (parser.isSet(authOption)) {
QStringList pieces = parser.value(authOption).split(":");
if (pieces.size() != 2) {
qDebug() << "-u should be followed by username:password";
parser.showHelp();
Q_UNREACHABLE();
}
_username = pieces[0];
_password = pieces[1];
}
Setting::init();
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
@ -88,6 +104,9 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
DependencyManager::set<AddressManager>();
DependencyManager::set<NodeList>(NodeType::Agent, listenPort);
auto accountManager = DependencyManager::get<AccountManager>();
accountManager->setIsAgent(true);
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
auto nodeList = DependencyManager::get<NodeList>();
@ -96,27 +115,45 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
// start the nodeThread so its event loop is running
// start the nodeThread so its event loop is running
// (must happen after the checkin timer is created with the nodelist as it's parent)
nodeList->startThread();
const DomainHandler& domainHandler = nodeList->getDomainHandler();
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
// connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
// connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails()));
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ACClientApp::domainConnectionRefused);
connect(nodeList.data(), &NodeList::nodeAdded, this, &ACClientApp::nodeAdded);
connect(nodeList.data(), &NodeList::nodeKilled, this, &ACClientApp::nodeKilled);
connect(nodeList.data(), &NodeList::nodeActivated, this, &ACClientApp::nodeActivated);
// connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID);
// connect(nodeList.data(), &NodeList::uuidChanged, this, &ACClientApp::setSessionUUID);
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ACClientApp::notifyPacketVersionMismatch);
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer
<< NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer);
if (_verbose) {
QString username = accountManager->getAccountInfo().getUsername();
qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn();
}
if (!_username.isEmpty()) {
connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){
if (_verbose) {
qDebug() << "new keypair has been created.";
}
});
connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){
if (_verbose) {
qDebug() << "login successful";
}
});
connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){
qDebug() << "login failed.";
});
accountManager->requestAccessToken(_username, _password);
}
DependencyManager::get<AddressManager>()->handleLookupString(domainServerAddress, false);
QTimer* doTimer = new QTimer(this);

View file

@ -47,6 +47,9 @@ private:
bool _sawAvatarMixer { false };
bool _sawAssetServer { false };
bool _sawMessagesMixer { false };
QString _username;
QString _password;
};
#endif //hifi_ACClientApp_h

View file

@ -1,4 +1,4 @@
set(TARGET_NAME atp-get)
set(TARGET_NAME atp-client)
setup_hifi_project(Core Widgets)
setup_memory_debugger()
link_hifi_libraries(shared networking)

View file

@ -0,0 +1,406 @@
//
// ATPClientApp.cpp
// tools/atp-client/src
//
// Created by Seth Alves on 2017-3-15
// Copyright 2017 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 <QDataStream>
#include <QTextStream>
#include <QThread>
#include <QFile>
#include <QLoggingCategory>
#include <QCommandLineParser>
#include <NetworkLogging.h>
#include <NetworkingConstants.h>
#include <SharedLogging.h>
#include <AddressManager.h>
#include <DependencyManager.h>
#include <SettingHandle.h>
#include <AssetUpload.h>
#include "ATPClientApp.h"
#define HIGH_FIDELITY_ATP_CLIENT_USER_AGENT "Mozilla/5.0 (HighFidelityATPClient)"
#define TIMEOUT_MILLISECONDS 8000
ATPClientApp::ATPClientApp(int argc, char* argv[]) :
QCoreApplication(argc, argv)
{
// parse command-line
QCommandLineParser parser;
parser.setApplicationDescription("High Fidelity ATP-Client");
const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption verboseOutput("v", "verbose output");
parser.addOption(verboseOutput);
const QCommandLineOption uploadOption("T", "upload local file", "local-file-to-send");
parser.addOption(uploadOption);
const QCommandLineOption authOption("u", "set usename and pass", "username:password");
parser.addOption(authOption);
const QCommandLineOption outputFilenameOption("o", "output filename", "output-file-name");
parser.addOption(outputFilenameOption);
const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1");
parser.addOption(domainAddressOption);
const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT));
parser.addOption(listenPortOption);
if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl;
parser.showHelp();
Q_UNREACHABLE();
}
if (parser.isSet(helpOption)) {
parser.showHelp();
Q_UNREACHABLE();
}
_verbose = parser.isSet(verboseOutput);
if (!_verbose) {
QLoggingCategory::setFilterRules("qt.network.ssl.warning=false");
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, false);
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, false);
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtWarningMsg, false);
const_cast<QLoggingCategory*>(&shared())->setEnabled(QtDebugMsg, false);
const_cast<QLoggingCategory*>(&shared())->setEnabled(QtInfoMsg, false);
const_cast<QLoggingCategory*>(&shared())->setEnabled(QtWarningMsg, false);
}
QStringList posArgs = parser.positionalArguments();
if (posArgs.size() != 1) {
qDebug() << "give remote url argument";
parser.showHelp();
Q_UNREACHABLE();
}
_url = QUrl(posArgs[0]);
if (_url.scheme() != "atp") {
qDebug() << "url should start with atp:";
parser.showHelp();
Q_UNREACHABLE();
}
int domainPort = 40103;
if (_url.port() != -1) {
domainPort = _url.port();
}
if (parser.isSet(outputFilenameOption)) {
_localOutputFile = parser.value(outputFilenameOption);
}
if (parser.isSet(uploadOption)) {
_localUploadFile = parser.value(uploadOption);
}
if (parser.isSet(authOption)) {
QStringList pieces = parser.value(authOption).split(":");
if (pieces.size() != 2) {
qDebug() << "-u should be followed by username:password";
parser.showHelp();
Q_UNREACHABLE();
}
_username = pieces[0];
_password = pieces[1];
_waitingForLogin = true;
}
if (parser.isSet(listenPortOption)) {
_listenPort = parser.value(listenPortOption).toInt();
}
_domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort);
if (parser.isSet(domainAddressOption)) {
_domainServerAddress = parser.value(domainAddressOption);
} else if (!_url.host().isEmpty()) {
QUrl domainURL;
domainURL.setScheme("hifi");
domainURL.setHost(_url.host());
_domainServerAddress = domainURL.toString();
}
Setting::init();
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::set<AccountManager>([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); });
DependencyManager::set<AddressManager>();
DependencyManager::set<NodeList>(NodeType::Agent, _listenPort);
auto accountManager = DependencyManager::get<AccountManager>();
accountManager->setIsAgent(true);
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
auto nodeList = DependencyManager::get<NodeList>();
// setup a timer for domain-server check ins
_domainCheckInTimer = new QTimer(nodeList.data());
connect(_domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
_domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
// start the nodeThread so its event loop is running
// (must happen after the checkin timer is created with the nodelist as it's parent)
nodeList->startThread();
const DomainHandler& domainHandler = nodeList->getDomainHandler();
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::domainConnectionRefused);
connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPClientApp::nodeAdded);
connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPClientApp::nodeKilled);
connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPClientApp::nodeActivated);
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch);
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer
<< NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer);
if (_verbose) {
QString username = accountManager->getAccountInfo().getUsername();
qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn();
}
if (!_username.isEmpty()) {
connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){
if (_verbose) {
qDebug() << "new keypair has been created.";
}
});
connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){
if (_verbose) {
qDebug() << "login successful";
}
_waitingForLogin = false;
go();
});
connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){
qDebug() << "login failed.";
_waitingForLogin = false;
go();
});
accountManager->requestAccessToken(_username, _password);
}
auto assetClient = DependencyManager::set<AssetClient>();
assetClient->init();
if (_verbose) {
qDebug() << "domain-server address is" << _domainServerAddress;
}
DependencyManager::get<AddressManager>()->handleLookupString(_domainServerAddress, false);
QTimer* _timeoutTimer = new QTimer(this);
_timeoutTimer->setSingleShot(true);
connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut);
_timeoutTimer->start(TIMEOUT_MILLISECONDS);
}
ATPClientApp::~ATPClientApp() {
if (_domainCheckInTimer) {
QMetaObject::invokeMethod(_domainCheckInTimer, "deleteLater", Qt::QueuedConnection);
}
if (_timeoutTimer) {
QMetaObject::invokeMethod(_timeoutTimer, "deleteLater", Qt::QueuedConnection);
}
}
void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
// this is non-fatal if we are trying to get an authenticated connection -- it will be retried.
if (_verbose) {
qDebug() << "domainConnectionRefused";
}
}
void ATPClientApp::domainChanged(const QString& domainHostname) {
if (_verbose) {
qDebug() << "domainChanged";
}
}
void ATPClientApp::nodeAdded(SharedNodePointer node) {
if (_verbose) {
qDebug() << "node added: " << node->getType();
}
}
void ATPClientApp::nodeActivated(SharedNodePointer node) {
if (!_waitingForLogin && node->getType() == NodeType::AssetServer) {
_waitingForNode = false;
go();
}
}
void ATPClientApp::go() {
if (_waitingForLogin || _waitingForNode) {
return;
}
auto path = _url.path();
if (_verbose) {
qDebug() << "path is " << path;
}
if (!_localUploadFile.isEmpty()) {
uploadAsset();
} else if (path == "/") {
listAssets();
} else {
lookupAsset();
}
}
void ATPClientApp::nodeKilled(SharedNodePointer node) {
if (_verbose) {
qDebug() << "nodeKilled" << node->getType();
}
}
void ATPClientApp::timedOut() {
finish(1);
}
void ATPClientApp::notifyPacketVersionMismatch() {
if (_verbose) {
qDebug() << "packet version mismatch";
}
finish(1);
}
void ATPClientApp::uploadAsset() {
auto path = _url.path();
if (path == "/") {
qDebug() << "cannot upload to path of /";
QCoreApplication::exit(1);
}
auto upload = DependencyManager::get<AssetClient>()->createUpload(_localUploadFile);
QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable {
if (upload->getError() != AssetUpload::NoError) {
qDebug() << "upload failed: " << upload->getErrorString();
} else {
setMapping(hash);
}
upload->deleteLater();
});
upload->start();
}
void ATPClientApp::setMapping(QString hash) {
auto path = _url.path();
auto assetClient = DependencyManager::get<AssetClient>();
auto request = assetClient->createSetMappingRequest(path, hash);
connect(request, &SetMappingRequest::finished, this, [=](SetMappingRequest* request) mutable {
if (request->getError() != SetMappingRequest::NoError) {
qDebug() << "upload succeeded, but couldn't set mapping: " << request->getErrorString();
} else if (_verbose) {
qDebug() << "mapping set.";
}
request->deleteLater();
finish(0);
});
request->start();
}
void ATPClientApp::listAssets() {
auto request = DependencyManager::get<AssetClient>()->createGetAllMappingsRequest();
QObject::connect(request, &GetAllMappingsRequest::finished, this, [=](GetAllMappingsRequest* request) mutable {
auto result = request->getError();
if (result == GetAllMappingsRequest::NotFound) {
qDebug() << "not found: " << request->getErrorString();
} else if (result == GetAllMappingsRequest::NoError) {
auto mappings = request->getMappings();
for (auto& kv : mappings ) {
qDebug() << kv.first << kv.second;
}
} else {
qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString();
}
request->deleteLater();
finish(0);
});
request->start();
}
void ATPClientApp::lookupAsset() {
auto path = _url.path();
auto request = DependencyManager::get<AssetClient>()->createGetMappingRequest(path);
QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable {
auto result = request->getError();
if (result == GetMappingRequest::NotFound) {
qDebug() << "not found: " << request->getErrorString();
} else if (result == GetMappingRequest::NoError) {
qDebug() << "found, hash is " << request->getHash();
download(request->getHash());
} else {
qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString();
}
request->deleteLater();
});
request->start();
}
void ATPClientApp::download(AssetHash hash) {
auto assetClient = DependencyManager::get<AssetClient>();
auto assetRequest = new AssetRequest(hash);
connect(assetRequest, &AssetRequest::finished, this, [this](AssetRequest* request) mutable {
Q_ASSERT(request->getState() == AssetRequest::Finished);
if (request->getError() == AssetRequest::Error::NoError) {
QString data = QString::fromUtf8(request->getData());
if (_localOutputFile == "" || _localOutputFile == "-") {
QTextStream cout(stdout);
cout << data;
} else {
QFile outputHandle(_localOutputFile);
if (outputHandle.open(QIODevice::ReadWrite)) {
QTextStream stream( &outputHandle );
stream << data;
} else {
qDebug() << "couldn't open output file:" << _localOutputFile;
}
}
}
request->deleteLater();
finish(0);
});
assetRequest->start();
}
void ATPClientApp::finish(int exitCode) {
auto nodeList = DependencyManager::get<NodeList>();
// send the domain a disconnect packet, force stoppage of domain-server check-ins
nodeList->getDomainHandler().disconnect();
nodeList->setIsShuttingDown(true);
// tell the packet receiver we're shutting down, so it can drop packets
nodeList->getPacketReceiver().setShouldDropPackets(true);
// remove the NodeList from the DependencyManager
DependencyManager::destroy<NodeList>();
QCoreApplication::exit(exitCode);
}

View file

@ -1,6 +1,6 @@
//
// ATPGetApp.h
// tools/atp-get/src
// ATPClientApp.h
// tools/atp-client/src
//
// Created by Seth Alves on 2017-3-15
// Copyright 2017 High Fidelity, Inc.
@ -10,8 +10,8 @@
//
#ifndef hifi_ATPGetApp_h
#define hifi_ATPGetApp_h
#ifndef hifi_ATPClientApp_h
#define hifi_ATPClientApp_h
#include <QApplication>
#include <udt/Constants.h>
@ -23,11 +23,11 @@
#include <MappingRequest.h>
class ATPGetApp : public QCoreApplication {
class ATPClientApp : public QCoreApplication {
Q_OBJECT
public:
ATPGetApp(int argc, char* argv[]);
~ATPGetApp();
ATPClientApp(int argc, char* argv[]);
~ATPClientApp();
private slots:
void domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo);
@ -38,15 +38,33 @@ private slots:
void notifyPacketVersionMismatch();
private:
void go();
NodeList* _nodeList;
void timedOut();
void lookup();
void uploadAsset();
void setMapping(QString hash);
void lookupAsset();
void listAssets();
void download(AssetHash hash);
void finish(int exitCode);
bool _verbose;
QUrl _url;
QString _localOutputFile;
QString _localUploadFile;
int _listenPort { INVALID_PORT };
QString _domainServerAddress;
QString _username;
QString _password;
bool _waitingForLogin { false };
bool _waitingForNode { true };
QTimer* _domainCheckInTimer { nullptr };
QTimer* _timeoutTimer { nullptr };
};
#endif // hifi_ATPGetApp_h
#endif // hifi_ATPClientApp_h

View file

@ -1,6 +1,6 @@
//
// main.cpp
// tools/atp-get/src
// tools/atp-client/src
//
// Created by Seth Alves on 2017-3-15
// Copyright 2017 High Fidelity, Inc.
@ -15,7 +15,7 @@
#include <BuildInfo.h>
#include "ATPGetApp.h"
#include "ATPClientApp.h"
using namespace std;
@ -25,7 +25,7 @@ int main(int argc, char * argv[]) {
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
ATPGetApp app(argc, argv);
ATPClientApp app(argc, argv);
return app.exec();
}

View file

@ -1,255 +0,0 @@
//
// ATPGetApp.cpp
// tools/atp-get/src
//
// Created by Seth Alves on 2017-3-15
// Copyright 2017 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 <QDataStream>
#include <QTextStream>
#include <QThread>
#include <QFile>
#include <QLoggingCategory>
#include <QCommandLineParser>
#include <NetworkLogging.h>
#include <SharedLogging.h>
#include <AddressManager.h>
#include <DependencyManager.h>
#include <SettingHandle.h>
#include "ATPGetApp.h"
ATPGetApp::ATPGetApp(int argc, char* argv[]) :
QCoreApplication(argc, argv)
{
// parse command-line
QCommandLineParser parser;
parser.setApplicationDescription("High Fidelity ATP-Get");
const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption verboseOutput("v", "verbose output");
parser.addOption(verboseOutput);
const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1");
parser.addOption(domainAddressOption);
const QCommandLineOption cacheSTUNOption("s", "cache stun-server response");
parser.addOption(cacheSTUNOption);
const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT));
parser.addOption(listenPortOption);
if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl;
parser.showHelp();
Q_UNREACHABLE();
}
if (parser.isSet(helpOption)) {
parser.showHelp();
Q_UNREACHABLE();
}
_verbose = parser.isSet(verboseOutput);
if (!_verbose) {
QLoggingCategory::setFilterRules("qt.network.ssl.warning=false");
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, false);
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, false);
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtWarningMsg, false);
const_cast<QLoggingCategory*>(&shared())->setEnabled(QtDebugMsg, false);
const_cast<QLoggingCategory*>(&shared())->setEnabled(QtInfoMsg, false);
const_cast<QLoggingCategory*>(&shared())->setEnabled(QtWarningMsg, false);
}
QStringList filenames = parser.positionalArguments();
if (filenames.empty() || filenames.size() > 2) {
qDebug() << "give remote url and optional local filename as arguments";
parser.showHelp();
Q_UNREACHABLE();
}
_url = QUrl(filenames[0]);
if (_url.scheme() != "atp") {
qDebug() << "url should start with atp:";
parser.showHelp();
Q_UNREACHABLE();
}
if (filenames.size() == 2) {
_localOutputFile = filenames[1];
}
QString domainServerAddress = "127.0.0.1:40103";
if (parser.isSet(domainAddressOption)) {
domainServerAddress = parser.value(domainAddressOption);
}
if (_verbose) {
qDebug() << "domain-server address is" << domainServerAddress;
}
int listenPort = INVALID_PORT;
if (parser.isSet(listenPortOption)) {
listenPort = parser.value(listenPortOption).toInt();
}
Setting::init();
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityATPGet)"); });
DependencyManager::set<AddressManager>();
DependencyManager::set<NodeList>(NodeType::Agent, listenPort);
auto nodeList = DependencyManager::get<NodeList>();
nodeList->startThread();
// setup a timer for domain-server check ins
QTimer* domainCheckInTimer = new QTimer(nodeList.data());
connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
const DomainHandler& domainHandler = nodeList->getDomainHandler();
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
// connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
// connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails()));
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPGetApp::domainConnectionRefused);
connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPGetApp::nodeAdded);
connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPGetApp::nodeKilled);
connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPGetApp::nodeActivated);
// connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID);
// connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPGetApp::setSessionUUID);
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPGetApp::notifyPacketVersionMismatch);
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer
<< NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer);
DependencyManager::get<AddressManager>()->handleLookupString(domainServerAddress, false);
auto assetClient = DependencyManager::set<AssetClient>();
assetClient->init();
QTimer* doTimer = new QTimer(this);
doTimer->setSingleShot(true);
connect(doTimer, &QTimer::timeout, this, &ATPGetApp::timedOut);
doTimer->start(4000);
}
ATPGetApp::~ATPGetApp() {
}
void ATPGetApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
qDebug() << "domainConnectionRefused";
}
void ATPGetApp::domainChanged(const QString& domainHostname) {
if (_verbose) {
qDebug() << "domainChanged";
}
}
void ATPGetApp::nodeAdded(SharedNodePointer node) {
if (_verbose) {
qDebug() << "node added: " << node->getType();
}
}
void ATPGetApp::nodeActivated(SharedNodePointer node) {
if (node->getType() == NodeType::AssetServer) {
lookup();
}
}
void ATPGetApp::nodeKilled(SharedNodePointer node) {
qDebug() << "nodeKilled";
}
void ATPGetApp::timedOut() {
finish(1);
}
void ATPGetApp::notifyPacketVersionMismatch() {
if (_verbose) {
qDebug() << "packet version mismatch";
}
finish(1);
}
void ATPGetApp::lookup() {
auto path = _url.path();
qDebug() << "path is " << path;
auto request = DependencyManager::get<AssetClient>()->createGetMappingRequest(path);
QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable {
auto result = request->getError();
if (result == GetMappingRequest::NotFound) {
qDebug() << "not found";
} else if (result == GetMappingRequest::NoError) {
qDebug() << "found, hash is " << request->getHash();
download(request->getHash());
} else {
qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString();
}
request->deleteLater();
});
request->start();
}
void ATPGetApp::download(AssetHash hash) {
auto assetClient = DependencyManager::get<AssetClient>();
auto assetRequest = new AssetRequest(hash);
connect(assetRequest, &AssetRequest::finished, this, [this](AssetRequest* request) mutable {
Q_ASSERT(request->getState() == AssetRequest::Finished);
if (request->getError() == AssetRequest::Error::NoError) {
QString data = QString::fromUtf8(request->getData());
if (_localOutputFile == "") {
QTextStream cout(stdout);
cout << data;
} else {
QFile outputHandle(_localOutputFile);
if (outputHandle.open(QIODevice::ReadWrite)) {
QTextStream stream( &outputHandle );
stream << data;
} else {
qDebug() << "couldn't open output file:" << _localOutputFile;
}
}
}
request->deleteLater();
finish(0);
});
assetRequest->start();
}
void ATPGetApp::finish(int exitCode) {
auto nodeList = DependencyManager::get<NodeList>();
// send the domain a disconnect packet, force stoppage of domain-server check-ins
nodeList->getDomainHandler().disconnect();
nodeList->setIsShuttingDown(true);
// tell the packet receiver we're shutting down, so it can drop packets
nodeList->getPacketReceiver().setShouldDropPackets(true);
// remove the NodeList from the DependencyManager
DependencyManager::destroy<NodeList>();
QCoreApplication::exit(exitCode);
}