From e9a8c3f5e816620d168d14b8a166d056c6d3728e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 15:52:03 -0700 Subject: [PATCH 1/7] rename atp-get to atp-client. add ability to list atp file mappings and to upload new files --- tools/CMakeLists.txt | 4 +- tools/{atp-get => atp-client}/CMakeLists.txt | 2 +- .../src/ATPClientApp.cpp} | 201 +++++++++++++----- .../src/ATPClientApp.h} | 29 ++- tools/{atp-get => atp-client}/src/main.cpp | 6 +- 5 files changed, 179 insertions(+), 63 deletions(-) rename tools/{atp-get => atp-client}/CMakeLists.txt (77%) rename tools/{atp-get/src/ATPGetApp.cpp => atp-client/src/ATPClientApp.cpp} (52%) rename tools/{atp-get/src/ATPGetApp.h => atp-client/src/ATPClientApp.h} (64%) rename tools/{atp-get => atp-client}/src/main.cpp (89%) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 0561956709..5de44e8897 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -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") diff --git a/tools/atp-get/CMakeLists.txt b/tools/atp-client/CMakeLists.txt similarity index 77% rename from tools/atp-get/CMakeLists.txt rename to tools/atp-client/CMakeLists.txt index 75f92b787d..4cee30bcc3 100644 --- a/tools/atp-get/CMakeLists.txt +++ b/tools/atp-client/CMakeLists.txt @@ -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) diff --git a/tools/atp-get/src/ATPGetApp.cpp b/tools/atp-client/src/ATPClientApp.cpp similarity index 52% rename from tools/atp-get/src/ATPGetApp.cpp rename to tools/atp-client/src/ATPClientApp.cpp index 4125582c21..ac69da7e96 100644 --- a/tools/atp-get/src/ATPGetApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -1,6 +1,6 @@ // -// ATPGetApp.cpp -// tools/atp-get/src +// ATPClientApp.cpp +// tools/atp-client/src // // Created by Seth Alves on 2017-3-15 // Copyright 2017 High Fidelity, Inc. @@ -15,26 +15,36 @@ #include #include #include + #include #include #include #include #include +#include -#include "ATPGetApp.h" +#include "ATPClientApp.h" -ATPGetApp::ATPGetApp(int argc, char* argv[]) : +#define HIGH_FIDELITY_ATP_CLIENT_USER_AGENT "Mozilla/5.0 (HighFidelityATPClient)" + +ATPClientApp::ATPClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; - parser.setApplicationDescription("High Fidelity ATP-Get"); + 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 outputFilenameOption("o", "output filename", "output-file-name"); + parser.addOption(outputFilenameOption); + const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); @@ -70,67 +80,94 @@ ATPGetApp::ATPGetApp(int argc, char* argv[]) : } - QStringList filenames = parser.positionalArguments(); - if (filenames.empty() || filenames.size() > 2) { - qDebug() << "give remote url and optional local filename as arguments"; + QStringList posArgs = parser.positionalArguments(); + if (posArgs.size() != 1) { + qDebug() << "give remote url argument"; parser.showHelp(); Q_UNREACHABLE(); } - _url = QUrl(filenames[0]); + _url = QUrl(posArgs[0]); if (_url.scheme() != "atp") { qDebug() << "url should start with atp:"; parser.showHelp(); Q_UNREACHABLE(); } - if (filenames.size() == 2) { - _localOutputFile = filenames[1]; + int domainPort = 40103; + if (_url.port() != -1) { + domainPort = _url.port(); } - QString domainServerAddress = "127.0.0.1:40103"; + if (parser.isSet(outputFilenameOption)) { + _localOutputFile = parser.value(outputFilenameOption); + } + + if (parser.isSet(uploadOption)) { + _localUploadFile = parser.value(uploadOption); + } + + + if (parser.isSet(listenPortOption)) { + _listenPort = parser.value(listenPortOption).toInt(); + } + + QString domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { domainServerAddress = parser.value(domainAddressOption); + qDebug() << "domainServerAddress is " << domainServerAddress; + connectToDomain(domainServerAddress); + } else if (!_url.host().isEmpty()) { + QUrl domainURL; + domainURL.setScheme("hifi"); + domainURL.setHost(_url.host()); + connectToDomain(domainURL.toString()); + } else { + qDebug() << "domainServerAddress is default " << domainServerAddress; + connectToDomain(domainServerAddress); } +} + + +void ATPClientApp::connectToDomain(QString domainServerAddress) { if (_verbose) { qDebug() << "domain-server address is" << domainServerAddress; } - int listenPort = INVALID_PORT; - if (parser.isSet(listenPortOption)) { - listenPort = parser.value(listenPortOption).toInt(); - } + DependencyManager::set(); + auto accountManager = DependencyManager::get(); + QString username = accountManager->getAccountInfo().getUsername(); + qDebug() << "username is" << username; Setting::init(); DependencyManager::registerInheritance(); - DependencyManager::set([&]{ return QString("Mozilla/5.0 (HighFidelityATPGet)"); }); + DependencyManager::set([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); }); DependencyManager::set(); - DependencyManager::set(NodeType::Agent, listenPort); - + DependencyManager::set(NodeType::Agent, _listenPort); auto nodeList = DependencyManager::get(); 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); + _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(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::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::nodeAdded, this, &ATPClientApp::nodeAdded); + connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPClientApp::nodeKilled); + connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPClientApp::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); + // connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPClientApp::setSessionUUID); + connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); @@ -140,63 +177,131 @@ ATPGetApp::ATPGetApp(int argc, char* argv[]) : auto assetClient = DependencyManager::set(); assetClient->init(); - QTimer* doTimer = new QTimer(this); - doTimer->setSingleShot(true); - connect(doTimer, &QTimer::timeout, this, &ATPGetApp::timedOut); - doTimer->start(4000); + QTimer* _timeoutTimer = new QTimer(this); + _timeoutTimer->setSingleShot(true); + connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); + _timeoutTimer->start(4000); } -ATPGetApp::~ATPGetApp() { +ATPClientApp::~ATPClientApp() { + delete _domainCheckInTimer; + delete _timeoutTimer; } -void ATPGetApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { +void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { qDebug() << "domainConnectionRefused"; } -void ATPGetApp::domainChanged(const QString& domainHostname) { +void ATPClientApp::domainChanged(const QString& domainHostname) { if (_verbose) { qDebug() << "domainChanged"; } } -void ATPGetApp::nodeAdded(SharedNodePointer node) { +void ATPClientApp::nodeAdded(SharedNodePointer node) { if (_verbose) { qDebug() << "node added: " << node->getType(); } } -void ATPGetApp::nodeActivated(SharedNodePointer node) { +void ATPClientApp::nodeActivated(SharedNodePointer node) { if (node->getType() == NodeType::AssetServer) { - lookup(); + auto path = _url.path(); + + if (_verbose) { + qDebug() << "path is " << path; + } + + qDebug() << "_localUploadFile =" << _localUploadFile; + + if (!_localUploadFile.isEmpty()) { + uploadAsset(); + } else if (path == "/") { + listAssets(); + } else { + lookupAsset(); + } } } -void ATPGetApp::nodeKilled(SharedNodePointer node) { +void ATPClientApp::nodeKilled(SharedNodePointer node) { qDebug() << "nodeKilled"; } -void ATPGetApp::timedOut() { +void ATPClientApp::timedOut() { finish(1); } -void ATPGetApp::notifyPacketVersionMismatch() { +void ATPClientApp::notifyPacketVersionMismatch() { if (_verbose) { qDebug() << "packet version mismatch"; } finish(1); } -void ATPGetApp::lookup() { - +void ATPClientApp::uploadAsset() { auto path = _url.path(); - qDebug() << "path is " << path; + if (path == "/") { + qDebug() << "cannot upload to path of /"; + QCoreApplication::exit(1); + } + auto upload = DependencyManager::get()->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(); + 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(); + } + request->deleteLater(); + }); + + request->start(); +} + +void ATPClientApp::listAssets() { + auto request = DependencyManager::get()->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(); + }); + request->start(); +} + +void ATPClientApp::lookupAsset() { + auto path = _url.path(); auto request = DependencyManager::get()->createGetMappingRequest(path); QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable { auto result = request->getError(); if (result == GetMappingRequest::NotFound) { - qDebug() << "not found"; + qDebug() << "not found: " << request->getErrorString(); } else if (result == GetMappingRequest::NoError) { qDebug() << "found, hash is " << request->getHash(); download(request->getHash()); @@ -208,7 +313,7 @@ void ATPGetApp::lookup() { request->start(); } -void ATPGetApp::download(AssetHash hash) { +void ATPClientApp::download(AssetHash hash) { auto assetClient = DependencyManager::get(); auto assetRequest = new AssetRequest(hash); @@ -217,7 +322,7 @@ void ATPGetApp::download(AssetHash hash) { if (request->getError() == AssetRequest::Error::NoError) { QString data = QString::fromUtf8(request->getData()); - if (_localOutputFile == "") { + if (_localOutputFile == "" || _localOutputFile == "-") { QTextStream cout(stdout); cout << data; } else { @@ -238,7 +343,7 @@ void ATPGetApp::download(AssetHash hash) { assetRequest->start(); } -void ATPGetApp::finish(int exitCode) { +void ATPClientApp::finish(int exitCode) { auto nodeList = DependencyManager::get(); // send the domain a disconnect packet, force stoppage of domain-server check-ins diff --git a/tools/atp-get/src/ATPGetApp.h b/tools/atp-client/src/ATPClientApp.h similarity index 64% rename from tools/atp-get/src/ATPGetApp.h rename to tools/atp-client/src/ATPClientApp.h index 5507d2aa62..ce85d2700e 100644 --- a/tools/atp-get/src/ATPGetApp.h +++ b/tools/atp-client/src/ATPClientApp.h @@ -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 #include @@ -23,11 +23,11 @@ #include -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,26 @@ private slots: void notifyPacketVersionMismatch(); private: + void connectToDomain(QString domainServerAddress); + 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 }; + + QTimer* _domainCheckInTimer { nullptr }; + QTimer* _timeoutTimer { nullptr }; }; -#endif // hifi_ATPGetApp_h +#endif // hifi_ATPClientApp_h diff --git a/tools/atp-get/src/main.cpp b/tools/atp-client/src/main.cpp similarity index 89% rename from tools/atp-get/src/main.cpp rename to tools/atp-client/src/main.cpp index bddf30c666..88119604cf 100644 --- a/tools/atp-get/src/main.cpp +++ b/tools/atp-client/src/main.cpp @@ -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 -#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(); } From a6af6015a4de2618aa9f1b791314e266ce2f1011 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:00:25 -0700 Subject: [PATCH 2/7] add a way to login on command-line --- tools/atp-client/src/ATPClientApp.cpp | 45 ++++++++++++++++++++++----- tools/atp-client/src/ATPClientApp.h | 3 ++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index ac69da7e96..76bf706205 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -42,15 +43,15 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : 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 cacheSTUNOption("s", "cache stun-server response"); - parser.addOption(cacheSTUNOption); - const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); @@ -107,6 +108,18 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : _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]; + } + if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); @@ -135,11 +148,6 @@ void ATPClientApp::connectToDomain(QString domainServerAddress) { qDebug() << "domain-server address is" << domainServerAddress; } - DependencyManager::set(); - auto accountManager = DependencyManager::get(); - QString username = accountManager->getAccountInfo().getUsername(); - qDebug() << "username is" << username; - Setting::init(); DependencyManager::registerInheritance(); @@ -177,6 +185,27 @@ void ATPClientApp::connectToDomain(QString domainServerAddress) { auto assetClient = DependencyManager::set(); assetClient->init(); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + + if (_verbose) { + QString username = accountManager->getAccountInfo().getUsername(); + qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); + } + + if (!_username.isEmpty()) { + connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ + if (_verbose) { + qDebug() << "login successful"; + } + }); + connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ + qDebug() << "login failed."; + }); + accountManager->requestAccessToken(_username, _password); + } + QTimer* _timeoutTimer = new QTimer(this); _timeoutTimer->setSingleShot(true); connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); diff --git a/tools/atp-client/src/ATPClientApp.h b/tools/atp-client/src/ATPClientApp.h index ce85d2700e..c2401e54af 100644 --- a/tools/atp-client/src/ATPClientApp.h +++ b/tools/atp-client/src/ATPClientApp.h @@ -56,6 +56,9 @@ private: int _listenPort { INVALID_PORT }; + QString _username; + QString _password; + QTimer* _domainCheckInTimer { nullptr }; QTimer* _timeoutTimer { nullptr }; }; From 1192e8649431872942b9bf34804218f25e2b0b9c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:11:53 -0700 Subject: [PATCH 3/7] add a way to login on command-line --- tools/ac-client/src/ACClientApp.cpp | 38 +++++++++++++++++++++++++++ tools/ac-client/src/ACClientApp.h | 3 +++ tools/atp-client/src/ATPClientApp.cpp | 5 ---- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index b81d092662..0842a66346 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -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(); @@ -117,6 +133,28 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : DependencyManager::get()->handleLookupString(domainServerAddress, false); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + + if (_verbose) { + QString username = accountManager->getAccountInfo().getUsername(); + qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); + } + + if (!_username.isEmpty()) { + connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ + if (_verbose) { + qDebug() << "login successful"; + } + }); + connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ + qDebug() << "login failed."; + }); + accountManager->requestAccessToken(_username, _password); + } + + QTimer* doTimer = new QTimer(this); doTimer->setSingleShot(true); connect(doTimer, &QTimer::timeout, this, &ACClientApp::timedOut); diff --git a/tools/ac-client/src/ACClientApp.h b/tools/ac-client/src/ACClientApp.h index 29d571688e..e295b17654 100644 --- a/tools/ac-client/src/ACClientApp.h +++ b/tools/ac-client/src/ACClientApp.h @@ -47,6 +47,9 @@ private: bool _sawAvatarMixer { false }; bool _sawAssetServer { false }; bool _sawMessagesMixer { false }; + + QString _username; + QString _password; }; #endif //hifi_ACClientApp_h diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 76bf706205..cfa0cc81ad 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -55,7 +55,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); - if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -80,7 +79,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : const_cast(&shared())->setEnabled(QtWarningMsg, false); } - QStringList posArgs = parser.positionalArguments(); if (posArgs.size() != 1) { qDebug() << "give remote url argument"; @@ -120,7 +118,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : _password = pieces[1]; } - if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); } @@ -141,7 +138,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : } } - void ATPClientApp::connectToDomain(QString domainServerAddress) { if (_verbose) { @@ -217,7 +213,6 @@ ATPClientApp::~ATPClientApp() { delete _timeoutTimer; } - void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { qDebug() << "domainConnectionRefused"; } From bdbfe25a5380233c19e5302f5645788a417fffa6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:46:35 -0700 Subject: [PATCH 4/7] remove some debug prints --- tools/atp-client/src/ATPClientApp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index cfa0cc81ad..d859346ae2 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -125,7 +125,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : QString domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { domainServerAddress = parser.value(domainAddressOption); - qDebug() << "domainServerAddress is " << domainServerAddress; connectToDomain(domainServerAddress); } else if (!_url.host().isEmpty()) { QUrl domainURL; @@ -133,7 +132,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : domainURL.setHost(_url.host()); connectToDomain(domainURL.toString()); } else { - qDebug() << "domainServerAddress is default " << domainServerAddress; connectToDomain(domainServerAddress); } } From a05e9e12c15ab7b31ede11095d8cd577bd4bdf73 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:59:56 -0700 Subject: [PATCH 5/7] remove some debug prints --- tools/atp-client/src/ATPClientApp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index d859346ae2..5029bcd5b3 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -235,8 +235,6 @@ void ATPClientApp::nodeActivated(SharedNodePointer node) { qDebug() << "path is " << path; } - qDebug() << "_localUploadFile =" << _localUploadFile; - if (!_localUploadFile.isEmpty()) { uploadAsset(); } else if (path == "/") { From f7131027e020c89ce38a492119022216c060d4ff Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 17:26:15 -0700 Subject: [PATCH 6/7] if user has provided login credentials, wait for the keypair to be ready before proceeding --- tools/atp-client/src/ATPClientApp.cpp | 119 ++++++++++++++++---------- tools/atp-client/src/ATPClientApp.h | 8 +- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 5029bcd5b3..a0856dbff1 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -27,6 +27,7 @@ #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) @@ -116,30 +117,21 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : _username = pieces[0]; _password = pieces[1]; + _waitingForLogin = true; } if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); } - QString domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); + _domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { - domainServerAddress = parser.value(domainAddressOption); - connectToDomain(domainServerAddress); + _domainServerAddress = parser.value(domainAddressOption); } else if (!_url.host().isEmpty()) { QUrl domainURL; domainURL.setScheme("hifi"); domainURL.setHost(_url.host()); - connectToDomain(domainURL.toString()); - } else { - connectToDomain(domainServerAddress); - } -} - -void ATPClientApp::connectToDomain(QString domainServerAddress) { - - if (_verbose) { - qDebug() << "domain-server address is" << domainServerAddress; + _domainServerAddress = domainURL.toString(); } Setting::init(); @@ -149,70 +141,90 @@ void ATPClientApp::connectToDomain(QString domainServerAddress) { DependencyManager::set(); DependencyManager::set(NodeType::Agent, _listenPort); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + auto nodeList = DependencyManager::get(); - nodeList->startThread(); // 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); - const DomainHandler& domainHandler = nodeList->getDomainHandler(); + // 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, &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::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID); - // connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPClientApp::setSessionUUID); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch); - nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); - DependencyManager::get()->handleLookupString(domainServerAddress, false); - - auto assetClient = DependencyManager::set(); - assetClient->init(); - - auto accountManager = DependencyManager::get(); - accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); - 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->init(); + + if (_verbose) { + qDebug() << "domain-server address is" << _domainServerAddress; + } + + + DependencyManager::get()->handleLookupString(_domainServerAddress, false); + QTimer* _timeoutTimer = new QTimer(this); _timeoutTimer->setSingleShot(true); connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); - _timeoutTimer->start(4000); + _timeoutTimer->start(TIMEOUT_MILLISECONDS); } ATPClientApp::~ATPClientApp() { - delete _domainCheckInTimer; - delete _timeoutTimer; + 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) { - qDebug() << "domainConnectionRefused"; + // 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) { @@ -228,25 +240,36 @@ void ATPClientApp::nodeAdded(SharedNodePointer node) { } void ATPClientApp::nodeActivated(SharedNodePointer node) { - if (node->getType() == NodeType::AssetServer) { - auto path = _url.path(); + if (!_waitingForLogin && node->getType() == NodeType::AssetServer) { + _waitingForNode = false; + go(); + } +} - if (_verbose) { - qDebug() << "path is " << path; - } +void ATPClientApp::go() { + if (_waitingForLogin || _waitingForNode) { + return; + } - if (!_localUploadFile.isEmpty()) { - uploadAsset(); - } else if (path == "/") { - listAssets(); - } else { - lookupAsset(); - } + 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) { - qDebug() << "nodeKilled"; + if (_verbose) { + qDebug() << "nodeKilled" << node->getType(); + } } void ATPClientApp::timedOut() { @@ -289,8 +312,11 @@ void ATPClientApp::setMapping(QString 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(); @@ -311,6 +337,7 @@ void ATPClientApp::listAssets() { qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString(); } request->deleteLater(); + finish(0); }); request->start(); } diff --git a/tools/atp-client/src/ATPClientApp.h b/tools/atp-client/src/ATPClientApp.h index c2401e54af..a3904d6e50 100644 --- a/tools/atp-client/src/ATPClientApp.h +++ b/tools/atp-client/src/ATPClientApp.h @@ -38,8 +38,7 @@ private slots: void notifyPacketVersionMismatch(); private: - void connectToDomain(QString domainServerAddress); - + void go(); NodeList* _nodeList; void timedOut(); void uploadAsset(); @@ -56,9 +55,14 @@ private: int _listenPort { INVALID_PORT }; + QString _domainServerAddress; + QString _username; QString _password; + bool _waitingForLogin { false }; + bool _waitingForNode { true }; + QTimer* _domainCheckInTimer { nullptr }; QTimer* _timeoutTimer { nullptr }; }; From 98ac2ccb908f04795736b23ddc5eb606544178e9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 17:36:25 -0700 Subject: [PATCH 7/7] rearrange code so authed connection works better --- tools/ac-client/src/ACClientApp.cpp | 25 ++++++++++++------------- tools/atp-client/src/ATPClientApp.cpp | 1 - 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index c44d4aa24c..2b92bb744b 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -104,6 +104,9 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : DependencyManager::set(); DependencyManager::set(NodeType::Agent, listenPort); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); auto nodeList = DependencyManager::get(); @@ -112,39 +115,34 @@ 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); - DependencyManager::get()->handleLookupString(domainServerAddress, false); - - auto accountManager = DependencyManager::get(); - accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); - 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"; @@ -156,6 +154,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : accountManager->requestAccessToken(_username, _password); } + DependencyManager::get()->handleLookupString(domainServerAddress, false); QTimer* doTimer = new QTimer(this); doTimer->setSingleShot(true); diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index a0856dbff1..3e2f8ca71d 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -202,7 +202,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : qDebug() << "domain-server address is" << _domainServerAddress; } - DependencyManager::get()->handleLookupString(_domainServerAddress, false); QTimer* _timeoutTimer = new QTimer(this);