diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index cbf533bf64..b61fef8525 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -121,9 +121,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : if (_type != NonMetaverse) { // if we have a metaverse domain, we'll use an access token for API calls resetAccountManagerAccessToken(); - } - setupAutomaticNetworking(); + setupAutomaticNetworking(); + } if (!getID().isNull() && _type != NonMetaverse) { // setup periodic heartbeats to metaverse API diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index dd80dadca7..eb9a7c7f6d 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -111,7 +111,7 @@ void DiscoverabilityManager::updateLocation() { } // Update Steam - SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentFacingAddress()); + SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentFacingShareableAddress()); } void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 6760d44244..c9c9d73394 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -63,15 +63,31 @@ QUrl AddressManager::currentAddress() const { } QUrl AddressManager::currentFacingAddress() const { - QUrl hifiURL; + auto hifiURL = currentAddress(); + hifiURL.setPath(currentFacingPath()); - hifiURL.setScheme(HIFI_URL_SCHEME); - hifiURL.setHost(_host); + return hifiURL; +} - if (_port != 0 && _port != DEFAULT_DOMAIN_SERVER_PORT) { - hifiURL.setPort(_port); + +QUrl AddressManager::currentShareableAddress() const { + if (!_shareablePlaceName.isEmpty()) { + // if we have a shareable place name use that instead of whatever the current host is + QUrl hifiURL; + + hifiURL.setScheme(HIFI_URL_SCHEME); + hifiURL.setHost(_shareablePlaceName); + + hifiURL.setPath(currentPath()); + + return hifiURL; + } else { + return currentAddress(); } +} +QUrl AddressManager::currentFacingShareableAddress() const { + auto hifiURL = currentShareableAddress(); hifiURL.setPath(currentFacingPath()); return hifiURL; @@ -360,6 +376,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const LookupTrigger trigger = (LookupTrigger) reply.property(LOOKUP_TRIGGER_KEY).toInt(); + // set our current root place id to the ID that came back const QString PLACE_ID_KEY = "id"; _rootPlaceID = rootMap[PLACE_ID_KEY].toUuid(); @@ -368,6 +385,18 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const const QString PLACE_NAME_KEY = "name"; QString placeName = rootMap[PLACE_NAME_KEY].toString(); + if (placeName.isEmpty()) { + // we didn't get a set place name, check if there is a default or temporary domain name to use + const QString TEMPORARY_DOMAIN_NAME_KEY = "name"; + const QString DEFAULT_DOMAIN_NAME_KEY = "default_place_name"; + + if (domainObject.contains(TEMPORARY_DOMAIN_NAME_KEY)) { + placeName = domainObject[TEMPORARY_DOMAIN_NAME_KEY].toString(); + } else if (domainObject.contains(DEFAULT_DOMAIN_NAME_KEY)) { + placeName = domainObject[DEFAULT_DOMAIN_NAME_KEY].toString(); + } + } + if (!placeName.isEmpty()) { if (setHost(placeName, trigger)) { trigger = LookupTrigger::Internal; @@ -651,6 +680,9 @@ bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16 _port = port; + // any host change should clear the shareable place name + _shareablePlaceName.clear(); + if (host != _host) { _host = host; emit hostChanged(_host); @@ -701,13 +733,67 @@ void AddressManager::refreshPreviousLookup() { } void AddressManager::copyAddress() { - QApplication::clipboard()->setText(currentAddress().toString()); + // assume that the address is being copied because the user wants a shareable address + QApplication::clipboard()->setText(currentShareableAddress().toString()); } void AddressManager::copyPath() { QApplication::clipboard()->setText(currentPath()); } +void AddressManager::handleShareableNameAPIResponse(QNetworkReply& requestReply) { + // make sure that this response is for the domain we're currently connected to + auto domainID = DependencyManager::get()->getDomainHandler().getUUID(); + + if (requestReply.url().toString().contains(uuidStringWithoutCurlyBraces(domainID))) { + // check for a name or default name in the API response + + QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + QJsonObject domainObject = responseObject["domain"].toObject(); + + const QString DOMAIN_NAME_KEY = "name"; + const QString DOMAIN_DEFAULT_PLACE_NAME_KEY = "default_place_name"; + + bool shareableNameChanged { false }; + + if (domainObject[DOMAIN_NAME_KEY].isString()) { + _shareablePlaceName = domainObject[DOMAIN_NAME_KEY].toString(); + shareableNameChanged = true; + } else if (domainObject[DOMAIN_DEFAULT_PLACE_NAME_KEY].isString()) { + _shareablePlaceName = domainObject[DOMAIN_DEFAULT_PLACE_NAME_KEY].toString(); + shareableNameChanged = true; + } + + if (shareableNameChanged) { + qDebug() << "AddressManager shareable name changed to" << _shareablePlaceName; + } + } +} + +void AddressManager::lookupShareableNameForDomainID(const QUuid& domainID) { + + // if we get to a domain via IP/hostname, often the address is only reachable by this client + // and not by other clients on the LAN or Internet + + // to work around this we use the ID to lookup the default place name, and if it exists we + // then use that for Steam join/invite or copiable address + + // it only makes sense to lookup a shareable default name if we don't have a place name + if (_placeName.isEmpty()) { + JSONCallbackParameters callbackParams; + + // no error callback handling + // in the case of an error we simply assume there is no default place name + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "handleShareableNameAPIResponse"; + + DependencyManager::get()->sendRequest(GET_DOMAIN_ID.arg(uuidStringWithoutCurlyBraces(domainID)), + AccountManagerAuth::None, + QNetworkAccessManager::GetOperation, + callbackParams); + } +} + void AddressManager::addCurrentAddressToHistory(LookupTrigger trigger) { // if we're cold starting and this is called for the first address (from settings) we don't do anything diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 23df176d8b..248a1ef435 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -60,6 +60,8 @@ public: QUrl currentAddress() const; QUrl currentFacingAddress() const; + QUrl currentShareableAddress() const; + QUrl currentFacingShareableAddress() const; QString currentPath(bool withOrientation = true) const; QString currentFacingPath() const; @@ -102,6 +104,8 @@ public slots: void copyAddress(); void copyPath(); + void lookupShareableNameForDomainID(const QUuid& domainID); + signals: void lookupResultsFinished(); void lookupResultIsOffline(); @@ -125,6 +129,8 @@ private slots: void handleAPIResponse(QNetworkReply& requestReply); void handleAPIError(QNetworkReply& errorReply); + void handleShareableNameAPIResponse(QNetworkReply& requestReply); + private: void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply& reply); @@ -155,6 +161,8 @@ private: PositionGetter _positionGetter; OrientationGetter _orientationGetter; + QString _shareablePlaceName; + QStack _backStack; QStack _forwardStack; quint64 _lastBackPush = 0; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 781cc00c1c..3a07ea8b54 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -539,6 +539,10 @@ void NodeList::processDomainServerList(QSharedPointer message) if (!_domainHandler.isConnected()) { _domainHandler.setUUID(domainUUID); _domainHandler.setIsConnected(true); + + // in case we didn't use a place name to get to this domain, + // give the address manager a chance to lookup a default one now + DependencyManager::get()->lookupShareableNameForDomainID(domainUUID); } else if (_domainHandler.getUUID() != domainUUID) { // Recieved packet from different domain. qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID();