From b09ed1dff117a33a7340864db6c1b1f2b7acb2c9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 10:53:13 -0800 Subject: [PATCH 1/3] present a login window on app start --- assignment-client/src/AssignmentClient.cpp | 2 +- domain-server/src/DomainServer.cpp | 2 +- interface/src/Application.cpp | 7 +++++- libraries/shared/src/AccountManager.cpp | 26 +++++++++++----------- libraries/shared/src/AccountManager.h | 16 ++++++------- libraries/shared/src/NodeList.cpp | 4 ++-- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index a7a66b933c..978f090ec2 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -185,7 +185,7 @@ void AssignmentClient::handleAuthenticationRequest() { // ask the account manager to log us in from the env variables accountManager.requestAccessToken(username, password); } else { - qDebug() << "Authentication was requested against" << qPrintable(accountManager.getRootURL().toString()) + qDebug() << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString()) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) << "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate."; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 2ee343f268..6eb59bb3df 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -64,7 +64,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV); AccountManager& accountManager = AccountManager::getInstance(); - accountManager.setRootURL(_nodeAuthenticationURL); + accountManager.setAuthURL(_nodeAuthenticationURL); if (!username.isEmpty() && !password.isEmpty()) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a8fad55b6e..035845eda4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -232,6 +232,12 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : AccountManager& accountManager = AccountManager::getInstance(); connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain); connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); + + // set the account manager's root URL and trigger a login request if we don't have the access token + accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL); + + // once the event loop has started, check and signal for an access token + QMetaObject::invokeMethod(&accountManager, "checkAndSignalForAccessToken", Qt::QueuedConnection); _settings = new QSettings(this); @@ -311,7 +317,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _overlays.init(_glWidget); // do this before scripts load - // do this as late as possible so that all required subsystems are inialized loadScripts(); } diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index a4f14f3fc8..b8fc1061f8 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -34,7 +34,7 @@ Q_DECLARE_METATYPE(JSONCallbackParameters) const QString ACCOUNTS_GROUP = "accounts"; AccountManager::AccountManager() : - _rootURL(), + _authURL(), _networkAccessManager(), _pendingCallbackMap(), _accounts() @@ -67,15 +67,15 @@ const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; void AccountManager::logout() { // a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file - _accounts.remove(_rootURL); + _accounts.remove(_authURL); QSettings settings; settings.beginGroup(ACCOUNTS_GROUP); - QString keyURLString(_rootURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE)); + QString keyURLString(_authURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE)); settings.remove(keyURLString); - qDebug() << "Removed account info for" << _rootURL << "from in-memory accounts and .ini file"; + qDebug() << "Removed account info for" << _authURL << "from in-memory accounts and .ini file"; emit logoutComplete(); // the username has changed to blank @@ -83,11 +83,11 @@ void AccountManager::logout() { } -void AccountManager::setRootURL(const QUrl& rootURL) { - if (_rootURL != rootURL) { - _rootURL = rootURL; +void AccountManager::setAuthURL(const QUrl& authURL) { + if (_authURL != authURL) { + _authURL = authURL; - qDebug() << "URL for node authentication has been changed to" << qPrintable(_rootURL.toString()); + qDebug() << "URL for node authentication has been changed to" << qPrintable(_authURL.toString()); qDebug() << "Re-setting authentication flow."; // tell listeners that the auth endpoint has changed @@ -109,9 +109,9 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager:: if (hasValidAccessToken()) { QNetworkRequest authenticatedRequest; - QUrl requestURL = _rootURL; + QUrl requestURL = _authURL; requestURL.setPath(path); - requestURL.setQuery("access_token=" + _accounts.value(_rootURL).getAccessToken().token); + requestURL.setQuery("access_token=" + _accounts.value(_authURL).getAccessToken().token); authenticatedRequest.setUrl(requestURL); @@ -202,11 +202,11 @@ void AccountManager::passErrorToCallback(QNetworkReply::NetworkError errorCode) } bool AccountManager::hasValidAccessToken() { - DataServerAccountInfo accountInfo = _accounts.value(_rootURL); + DataServerAccountInfo accountInfo = _accounts.value(_authURL); if (accountInfo.getAccessToken().token.isEmpty() || accountInfo.getAccessToken().isExpired()) { if (VERBOSE_HTTP_REQUEST_DEBUGGING) { - qDebug() << "An access token is required for requests to" << qPrintable(_rootURL.toString()); + qDebug() << "An access token is required for requests to" << qPrintable(_authURL.toString()); } return false; @@ -229,7 +229,7 @@ bool AccountManager::checkAndSignalForAccessToken() { void AccountManager::requestAccessToken(const QString& login, const QString& password) { QNetworkRequest request; - QUrl grantURL = _rootURL; + QUrl grantURL = _authURL; grantURL.setPath("/oauth/token"); QByteArray postData; diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index 0018a6bba0..35819f2c9a 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -41,17 +41,17 @@ public: const JSONCallbackParameters& callbackParams = JSONCallbackParameters(), const QByteArray& dataByteArray = QByteArray()); - const QUrl& getRootURL() const { return _rootURL; } - void setRootURL(const QUrl& rootURL); - bool hasAuthEndpoint() { return !_rootURL.isEmpty(); } + const QUrl& getAuthURL() const { return _authURL; } + void setAuthURL(const QUrl& authURL); + bool hasAuthEndpoint() { return !_authURL.isEmpty(); } - bool isLoggedIn() { return !_rootURL.isEmpty() && hasValidAccessToken(); } + bool isLoggedIn() { return !_authURL.isEmpty() && hasValidAccessToken(); } bool hasValidAccessToken(); - bool checkAndSignalForAccessToken(); + Q_INVOKABLE bool checkAndSignalForAccessToken(); void requestAccessToken(const QString& login, const QString& password); - QString getUsername() const { return _accounts[_rootURL].getUsername(); } + QString getUsername() const { return _accounts[_authURL].getUsername(); } public slots: void requestFinished(); @@ -61,7 +61,7 @@ signals: void authRequired(); void authEndpointChanged(); void usernameChanged(const QString& username); - void loginComplete(const QUrl& rootURL); + void loginComplete(const QUrl& authURL); void logoutComplete(); private slots: void passSuccessToCallback(); @@ -74,7 +74,7 @@ private: Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation, const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray); - QUrl _rootURL; + QUrl _authURL; QNetworkAccessManager _networkAccessManager; QMap _pendingCallbackMap; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 89b04e00cf..36e22e2a77 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -120,7 +120,7 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { // we also know this domain-server requires no authentication // so set the account manager root URL empty - AccountManager::getInstance().setRootURL(QUrl()); + AccountManager::getInstance().setAuthURL(QUrl()); } if (_domainInfo.getUUID() == uuidFromPacketHeader(packet)) { @@ -644,7 +644,7 @@ void NodeList::processDomainServerAuthRequest(const QByteArray& packet) { QUrl authenticationRootURL; authPacketStream >> authenticationRootURL; - accountManager.setRootURL(authenticationRootURL); + accountManager.setAuthURL(authenticationRootURL); _domainInfo.setRootAuthenticationURL(authenticationRootURL); if (AccountManager::getInstance().checkAndSignalForAccessToken()) { From 1163cfd07e3f7312920e33c56f0e3e40ece2af83 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 10:58:32 -0800 Subject: [PATCH 2/3] if the domain-server provides no auth, assume default --- interface/src/Menu.cpp | 12 +----------- libraries/shared/src/NodeList.cpp | 4 ++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index dc8116c09f..a0710cf463 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -96,7 +96,6 @@ Menu::Menu() : // connect to the appropriate slots of the AccountManager so that we can change the Login/Logout menu item connect(&accountManager, &AccountManager::loginComplete, this, &Menu::toggleLoginMenuItem); connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem); - connect(&accountManager, &AccountManager::authEndpointChanged, this, &Menu::toggleLoginMenuItem); addDisabledActionAndSeparator(fileMenu, "Scripts"); addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog())); @@ -1125,20 +1124,11 @@ void Menu::toggleLoginMenuItem() { // change the menu item to logout _loginAction->setText("Logout " + accountManager.getUsername()); connect(_loginAction, &QAction::triggered, &accountManager, &AccountManager::logout); - - _loginAction->setEnabled(true); } else { // change the menu item to login _loginAction->setText("Login"); - // if we don't have a rootURL in the AccountManager we're in a domain that doesn't use auth - // so setup the menu item according to the presence of that root URL - if (accountManager.hasAuthEndpoint()) { - connect(_loginAction, &QAction::triggered, this, &Menu::loginForCurrentDomain); - _loginAction->setEnabled(true); - } else { - _loginAction->setEnabled(false); - } + connect(_loginAction, &QAction::triggered, this, &Menu::loginForCurrentDomain); } } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 36e22e2a77..98387ce420 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -119,8 +119,8 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { _domainInfo.setUUID(uuidFromPacketHeader(packet)); // we also know this domain-server requires no authentication - // so set the account manager root URL empty - AccountManager::getInstance().setAuthURL(QUrl()); + // so set the account manager root URL to the default one + AccountManager::getInstance().setAuthURL(DEFAULT_NODE_AUTH_URL); } if (_domainInfo.getUUID() == uuidFromPacketHeader(packet)) { From a24366fcd7cab6b9ed5d1f44d56f891b6811d018 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 11:16:19 -0800 Subject: [PATCH 3/3] populate packet header only once session UUID is received --- assignment-client/src/audio/AudioMixer.cpp | 20 +++++++++----------- assignment-client/src/audio/AudioMixer.h | 3 +++ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 91b932a36c..900de817fa 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -61,9 +61,10 @@ void attachNewBufferToNode(Node *newNode) { } AudioMixer::AudioMixer(const QByteArray& packet) : - ThreadedAssignment(packet) + ThreadedAssignment(packet), + _clientMixBuffer(NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio), 0) { - + connect(NodeList::getInstance(), &NodeList::uuidChanged, this, &AudioMixer::receivedSessionUUID); } void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, @@ -229,6 +230,10 @@ void AudioMixer::readPendingDatagrams() { } } +void AudioMixer::receivedSessionUUID(const QUuid& sessionUUID) { + populatePacketHeader(_clientMixBuffer, PacketTypeMixedAudio); +} + void AudioMixer::run() { commonInit(AUDIO_MIXER_LOGGING_TARGET_NAME, NodeType::AudioMixer); @@ -245,13 +250,6 @@ void AudioMixer::run() { gettimeofday(&startTime, NULL); int numBytesPacketHeader = numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio); - // note: Visual Studio 2010 doesn't support variable sized local arrays - #ifdef _WIN32 - unsigned char clientPacket[MAX_PACKET_SIZE]; - #else - unsigned char clientPacket[NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader]; - #endif - populatePacketHeader(reinterpret_cast(clientPacket), PacketTypeMixedAudio); while (!_isFinished) { @@ -272,8 +270,8 @@ void AudioMixer::run() { && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); - memcpy(clientPacket + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); - nodeList->writeDatagram((char*) clientPacket, sizeof(clientPacket), node); + memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); + nodeList->writeDatagram(_clientMixBuffer, node); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index e120d19d32..ae5998100f 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -26,6 +26,8 @@ public slots: void run(); void readPendingDatagrams(); +private slots: + void receivedSessionUUID(const QUuid& sessionUUID); private: /// adds one buffer to the mix for a listening node void addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, @@ -34,6 +36,7 @@ private: /// prepares and sends a mix to one Node void prepareMixForListeningNode(Node* node); + QByteArray _clientMixBuffer; int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; };