mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 19:23:28 +02:00
Merge pull request #12510 from sethalves/serverless-domains
Serverless domains
This commit is contained in:
commit
6d9892856d
33 changed files with 484 additions and 228 deletions
|
@ -377,8 +377,6 @@ static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
|||
|
||||
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||
|
||||
static const QString DOMAIN_SPAWNING_POINT = "/0, -10, 0";
|
||||
|
||||
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||
|
@ -513,6 +511,27 @@ std::atomic<uint64_t> DeadlockWatchdogThread::_maxElapsed;
|
|||
std::atomic<int> DeadlockWatchdogThread::_maxElapsedAverage;
|
||||
ThreadSafeMovingAverage<int, DeadlockWatchdogThread::HEARTBEAT_SAMPLES> DeadlockWatchdogThread::_movingAverage;
|
||||
|
||||
bool isDomainURL(QUrl url) {
|
||||
if (!url.isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (url.scheme() == URL_SCHEME_HIFI) {
|
||||
return true;
|
||||
}
|
||||
if (url.scheme() != URL_SCHEME_FILE) {
|
||||
// TODO -- once Octree::readFromURL no-longer takes over the main event-loop, serverless-domain urls can
|
||||
// be loaded over http(s)
|
||||
// && url.scheme() != URL_SCHEME_HTTP &&
|
||||
// url.scheme() != URL_SCHEME_HTTPS
|
||||
return false;
|
||||
}
|
||||
if (url.path().endsWith(".json", Qt::CaseInsensitive) ||
|
||||
url.path().endsWith(".json.gz", Qt::CaseInsensitive)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
class MyNativeEventFilter : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
|
@ -542,7 +561,7 @@ public:
|
|||
if (message->message == WM_COPYDATA) {
|
||||
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam);
|
||||
QUrl url = QUrl((const char*)(pcds->lpData));
|
||||
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
||||
if (isDomainURL(url)) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
|
||||
return true;
|
||||
}
|
||||
|
@ -940,6 +959,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
||||
|
||||
_entityClipboard->setIsServerlessMode(true);
|
||||
|
||||
{
|
||||
const QString TEST_SCRIPT = "--testScript";
|
||||
const QString TRACE_FILE = "--traceFile";
|
||||
|
@ -1035,7 +1056,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// setup a timer for domain-server check ins
|
||||
QTimer* domainCheckInTimer = new QTimer(this);
|
||||
connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
|
||||
connect(domainCheckInTimer, &QTimer::timeout, [this, nodeList] {
|
||||
if (!isServerlessMode()) {
|
||||
nodeList->sendDomainServerCheckIn();
|
||||
}
|
||||
});
|
||||
domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||
connect(this, &QCoreApplication::aboutToQuit, [domainCheckInTimer] {
|
||||
domainCheckInTimer->stop();
|
||||
|
@ -1097,9 +1122,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
const DomainHandler& domainHandler = nodeList->getDomainHandler();
|
||||
|
||||
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
|
||||
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl)));
|
||||
connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
|
||||
connect(&domainHandler, SIGNAL(connectedToDomain(const QString&)), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &Application::clearDomainAvatars);
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() {
|
||||
|
@ -2046,7 +2071,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(&_addAssetToWorldErrorTimer, &QTimer::timeout, this, &Application::addAssetToWorldErrorTimeout);
|
||||
|
||||
connect(this, &QCoreApplication::aboutToQuit, this, &Application::addAssetToWorldMessageClose);
|
||||
connect(&domainHandler, &DomainHandler::hostnameChanged, this, &Application::addAssetToWorldMessageClose);
|
||||
connect(&domainHandler, &DomainHandler::domainURLChanged, this, &Application::addAssetToWorldMessageClose);
|
||||
|
||||
updateSystemTabletMode();
|
||||
|
||||
|
@ -3023,27 +3048,27 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
|
||||
QString sentTo;
|
||||
|
||||
// If this is a first run we short-circuit the address passed in
|
||||
if (firstRun.get()) {
|
||||
// If this is a first run we short-circuit the address passed in
|
||||
if (firstRun.get()) {
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
showHelp();
|
||||
#endif
|
||||
if (sandboxIsRunning) {
|
||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
||||
sentTo = SENT_TO_SANDBOX;
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
}
|
||||
firstRun.set(false);
|
||||
|
||||
showHelp();
|
||||
#endif
|
||||
if (sandboxIsRunning) {
|
||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
||||
sentTo = SENT_TO_SANDBOX;
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
sentTo = SENT_TO_PREVIOUS_LOCATION;
|
||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
}
|
||||
firstRun.set(false);
|
||||
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
sentTo = SENT_TO_PREVIOUS_LOCATION;
|
||||
}
|
||||
|
||||
UserActivityLogger::getInstance().logAction("startup_sent_to", {
|
||||
{ "sent_to", sentTo },
|
||||
|
@ -3083,6 +3108,57 @@ bool Application::importFromZIP(const QString& filePath) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Application::isServerlessMode() const {
|
||||
auto tree = getEntities()->getTree();
|
||||
if (tree) {
|
||||
return tree->isServerlessMode();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Application::setIsServerlessMode(bool serverlessDomain) {
|
||||
auto tree = getEntities()->getTree();
|
||||
if (tree) {
|
||||
tree->setIsServerlessMode(serverlessDomain);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::loadServerlessDomain(QUrl domainURL) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL));
|
||||
return;
|
||||
}
|
||||
|
||||
if (domainURL.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid serverlessSessionID = QUuid::createUuid();
|
||||
getMyAvatar()->setSessionUUID(serverlessSessionID);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->setSessionUUID(serverlessSessionID);
|
||||
|
||||
// there is no domain-server to tell us our permissions, so enable all
|
||||
NodePermissions permissions;
|
||||
permissions.setAll(true);
|
||||
nodeList->setPermissions(permissions);
|
||||
|
||||
// we can't import directly into the main tree because we would need to lock it, and
|
||||
// Octree::readFromURL calls loop.exec which can run code which will also attempt to lock the tree.
|
||||
EntityTreePointer tmpTree(new EntityTree());
|
||||
tmpTree->setIsServerlessMode(true);
|
||||
tmpTree->createRootElement();
|
||||
auto myAvatar = getMyAvatar();
|
||||
tmpTree->setMyAvatar(myAvatar);
|
||||
bool success = tmpTree->readFromURL(domainURL.toString());
|
||||
if (success) {
|
||||
tmpTree->reaverageOctreeElements();
|
||||
tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0);
|
||||
}
|
||||
|
||||
_fullSceneReceivedCounter++;
|
||||
}
|
||||
|
||||
bool Application::importImage(const QString& urlString) {
|
||||
qCDebug(interfaceapp) << "An image file has been dropped in";
|
||||
QString filepath(urlString);
|
||||
|
@ -4583,7 +4659,7 @@ void Application::initDisplay() {
|
|||
}
|
||||
|
||||
void Application::init() {
|
||||
|
||||
|
||||
// Make sure Login state is up to date
|
||||
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
||||
if (!DISABLE_DEFERRED) {
|
||||
|
@ -4608,7 +4684,9 @@ void Application::init() {
|
|||
qCDebug(interfaceapp) << "Loaded settings";
|
||||
|
||||
// fire off an immediate domain-server check in now that settings are loaded
|
||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||
if (!isServerlessMode()) {
|
||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||
}
|
||||
|
||||
// This allows collision to be set up properly for shape entities supported by GeometryCache.
|
||||
// This is before entity setup to ensure that it's ready for whenever instance collision is initialized.
|
||||
|
@ -5742,10 +5820,15 @@ void Application::updateWindowTitle() const {
|
|||
|
||||
QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)";
|
||||
QString username = accountManager->getAccountInfo().getUsername();
|
||||
QString currentPlaceName = DependencyManager::get<AddressManager>()->getHost();
|
||||
|
||||
if (currentPlaceName.isEmpty()) {
|
||||
currentPlaceName = nodeList->getDomainHandler().getHostname();
|
||||
QString currentPlaceName;
|
||||
if (isServerlessMode()) {
|
||||
currentPlaceName = "serverless: " + DependencyManager::get<AddressManager>()->getDomainURL().toString();
|
||||
} else {
|
||||
currentPlaceName = DependencyManager::get<AddressManager>()->getDomainURL().host();
|
||||
if (currentPlaceName.isEmpty()) {
|
||||
currentPlaceName = nodeList->getDomainHandler().getHostname();
|
||||
}
|
||||
}
|
||||
|
||||
QString title = QString() + (!username.isEmpty() ? username + " @ " : QString())
|
||||
|
@ -5758,7 +5841,7 @@ void Application::updateWindowTitle() const {
|
|||
_window->setWindowTitle(title);
|
||||
|
||||
// updateTitleWindow gets called whenever there's a change regarding the domain, so rather
|
||||
// than placing this within domainChanged, it's placed here to cover the other potential cases.
|
||||
// than placing this within domainURLChanged, it's placed here to cover the other potential cases.
|
||||
DependencyManager::get< MessagesClient >()->sendLocalMessage("Toolbar-DomainChanged", "");
|
||||
}
|
||||
|
||||
|
@ -5797,15 +5880,22 @@ void Application::clearDomainAvatars() {
|
|||
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
|
||||
}
|
||||
|
||||
void Application::domainChanged(const QString& domainHostname) {
|
||||
updateWindowTitle();
|
||||
void Application::domainURLChanged(QUrl domainURL) {
|
||||
// disable physics until we have enough information about our new location to not cause craziness.
|
||||
resetPhysicsReadyInformation();
|
||||
setIsServerlessMode(domainURL.scheme() != URL_SCHEME_HIFI);
|
||||
if (isServerlessMode()) {
|
||||
loadServerlessDomain(domainURL);
|
||||
}
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
|
||||
void Application::resettingDomain() {
|
||||
_notifiedPacketVersionMismatchThisDomain = false;
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
clearDomainOctreeDetails();
|
||||
}
|
||||
|
||||
void Application::nodeAdded(SharedNodePointer node) const {
|
||||
|
@ -5922,22 +6012,22 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
|
|||
AABox avatarBox(getMyAvatar()->getWorldPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
|
||||
// create two functions that use avatarBox (entityScan and elementScan), the second calls the first
|
||||
std::function<bool (EntityItemPointer&)> entityScan = [=](EntityItemPointer& entity) {
|
||||
if (entity->shouldBePhysical()) {
|
||||
bool success = false;
|
||||
AABox entityBox = entity->getAABox(success);
|
||||
// important: bail for entities that cannot supply a valid AABox
|
||||
return success && avatarBox.touches(entityBox);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (entity->shouldBePhysical()) {
|
||||
bool success = false;
|
||||
AABox entityBox = entity->getAABox(success);
|
||||
// important: bail for entities that cannot supply a valid AABox
|
||||
return success && avatarBox.touches(entityBox);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
std::function<bool(const OctreeElementPointer&, void*)> elementScan = [&](const OctreeElementPointer& element, void* unused) {
|
||||
if (element->getAACube().touches(avatarBox)) {
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
entityTreeElement->getEntities(entityScan, entities);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (element->getAACube().touches(avatarBox)) {
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
entityTreeElement->getEntities(entityScan, entities);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
entityTree->withReadLock([&] {
|
||||
// Pass the second function to the general-purpose EntityTree::findEntities()
|
||||
|
@ -6173,7 +6263,7 @@ bool Application::canAcceptURL(const QString& urlString) const {
|
|||
QUrl url(urlString);
|
||||
if (url.query().contains(WEB_VIEW_TAG)) {
|
||||
return false;
|
||||
} else if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||
} else if (urlString.startsWith(URL_SCHEME_HIFI)) {
|
||||
return true;
|
||||
}
|
||||
QString lowerPath = url.path().toLower();
|
||||
|
@ -6186,15 +6276,14 @@ bool Application::canAcceptURL(const QString& urlString) const {
|
|||
}
|
||||
|
||||
bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
|
||||
if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||
// this is a hifi URL - have the AddressManager handle it
|
||||
emit receivedHifiSchemeURL(urlString);
|
||||
QUrl url(urlString);
|
||||
if (isDomainURL(url)) {
|
||||
// this is a URL for a domain, either hifi:// or serverless - have the AddressManager handle it
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
||||
Qt::AutoConnection, Q_ARG(const QString&, urlString));
|
||||
return true;
|
||||
}
|
||||
|
||||
QUrl url(urlString);
|
||||
QString lowerPath = url.path().toLower();
|
||||
for (auto& pair : _acceptedExtensions) {
|
||||
if (lowerPath.endsWith(pair.first, Qt::CaseInsensitive)) {
|
||||
|
@ -7033,7 +7122,7 @@ void Application::packageModel() {
|
|||
|
||||
void Application::openUrl(const QUrl& url) const {
|
||||
if (!url.isEmpty()) {
|
||||
if (url.scheme() == HIFI_URL_SCHEME) {
|
||||
if (url.scheme() == URL_SCHEME_HIFI) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
|
||||
} else {
|
||||
// address manager did not handle - ask QDesktopServices to handle
|
||||
|
|
|
@ -284,6 +284,8 @@ public:
|
|||
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
||||
void saveNextPhysicsStats(QString filename);
|
||||
|
||||
bool isServerlessMode() const;
|
||||
|
||||
void replaceDomainContent(const QString& url);
|
||||
|
||||
signals:
|
||||
|
@ -295,7 +297,6 @@ signals:
|
|||
void activeDisplayPluginChanged();
|
||||
|
||||
void uploadRequest(QString path);
|
||||
void receivedHifiSchemeURL(const QString& url);
|
||||
|
||||
public slots:
|
||||
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
||||
|
@ -391,6 +392,9 @@ public slots:
|
|||
const QString getPreferredCursor() const { return _preferredCursor.get(); }
|
||||
void setPreferredCursor(const QString& cursor);
|
||||
|
||||
void setIsServerlessMode(bool serverlessDomain);
|
||||
void loadServerlessDomain(QUrl domainURL);
|
||||
|
||||
Q_INVOKABLE bool askBeforeSetAvatarUrl(const QString& avatarUrl) { return askToSetAvatarUrl(avatarUrl); }
|
||||
|
||||
private slots:
|
||||
|
@ -425,7 +429,7 @@ private slots:
|
|||
|
||||
void setSessionUUID(const QUuid& sessionUUID) const;
|
||||
|
||||
void domainChanged(const QString& domainHostname);
|
||||
void domainURLChanged(QUrl domainURL);
|
||||
void updateWindowTitle() const;
|
||||
void nodeAdded(SharedNodePointer node) const;
|
||||
void nodeActivated(SharedNodePointer node);
|
||||
|
|
|
@ -49,7 +49,7 @@ void DiscoverabilityManager::updateLocation() {
|
|||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
auto& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||
bool discoverable = (_mode.get() != Discoverability::None);
|
||||
bool discoverable = (_mode.get() != Discoverability::None) && !domainHandler.isServerless();
|
||||
|
||||
|
||||
if (accountManager->isLoggedIn()) {
|
||||
|
|
|
@ -129,7 +129,7 @@ int main(int argc, const char* argv[]) {
|
|||
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
|
||||
if (parser.isSet(urlOption)) {
|
||||
QUrl url = QUrl(parser.value(urlOption));
|
||||
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
||||
if (url.isValid() && url.scheme() == URL_SCHEME_HIFI) {
|
||||
qDebug() << "Writing URL to local socket";
|
||||
socket.write(url.toString().toUtf8());
|
||||
if (!socket.waitForBytesWritten(5000)) {
|
||||
|
|
|
@ -124,7 +124,7 @@ void WindowScriptingInterface::promptAsync(const QString& message, const QString
|
|||
}
|
||||
|
||||
void WindowScriptingInterface::disconnectedFromDomain() {
|
||||
emit domainChanged("");
|
||||
emit domainChanged(QUrl());
|
||||
}
|
||||
|
||||
QString fixupPathForMac(const QString& directory) {
|
||||
|
|
|
@ -524,7 +524,7 @@ signals:
|
|||
* Triggered when you change the domain you're visiting. <strong>Warning:</strong> Is not emitted if you go to domain that
|
||||
* isn't running.
|
||||
* @function Window.domainChanged
|
||||
* @param {string} domain - The domain's IP address.
|
||||
* @param {string} domainURL - The domain's URL.
|
||||
* @returns {Signal}
|
||||
* @example <caption>Report when you change domains.</caption>
|
||||
* function onDomainChanged(domain) {
|
||||
|
@ -533,7 +533,7 @@ signals:
|
|||
*
|
||||
* Window.domainChanged.connect(onDomainChanged);
|
||||
*/
|
||||
void domainChanged(const QString& domain);
|
||||
void domainChanged(QUrl domainURL);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when you try to navigate to a *.json, *.svo, or *.svo.json URL in a Web browser within Interface.
|
||||
|
|
|
@ -45,7 +45,6 @@ AddressBarDialog::AddressBarDialog(QQuickItem* parent) : OffscreenQmlDialog(pare
|
|||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &AddressBarDialog::hostChanged);
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &AddressBarDialog::hostChanged);
|
||||
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::setUseFeed, this, &AddressBarDialog::setUseFeed);
|
||||
connect(qApp, &Application::receivedHifiSchemeURL, this, &AddressBarDialog::receivedHifiSchemeURL);
|
||||
}
|
||||
|
||||
void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions) {
|
||||
|
|
|
@ -36,7 +36,6 @@ signals:
|
|||
void backEnabledChanged();
|
||||
void forwardEnabledChanged();
|
||||
void useFeedChanged();
|
||||
void receivedHifiSchemeURL(const QString& url);
|
||||
void hostChanged();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -221,8 +221,12 @@ void Avatar::updateAvatarEntities() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (getID() == QUuid() || getID() == AVATAR_SELF_ID) {
|
||||
return; // wait until MyAvatar gets an ID before doing this.
|
||||
if (getID().isNull() ||
|
||||
getID() == AVATAR_SELF_ID ||
|
||||
DependencyManager::get<NodeList>()->getSessionUUID() == QUuid()) {
|
||||
// wait until MyAvatar and this Node gets an ID before doing this. Otherwise, various things go wrong --
|
||||
// things get their parent fixed up from AVATAR_SELF_ID to a null uuid which means "no parent".
|
||||
return;
|
||||
}
|
||||
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
|
@ -1806,4 +1810,4 @@ scriptable::ScriptableModelBase Avatar::getScriptableModel() {
|
|||
result.appendMaterials(_materials);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,11 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type,
|
|||
return;
|
||||
}
|
||||
|
||||
if (entityTree && entityTree->isServerlessMode()) {
|
||||
// if we are in a serverless domain, don't send edit packets
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray bufferOut(NLPacket::maxPayloadSize(type), 0);
|
||||
|
||||
if (type == PacketType::EntityAdd) {
|
||||
|
|
|
@ -963,7 +963,11 @@ void EntityItem::setHref(QString value) {
|
|||
|
||||
// If the string has something and doesn't start with with "hifi://" it shouldn't be set
|
||||
// We allow the string to be empty, because that's the initial state of this property
|
||||
if ( !(value.toLower().startsWith("hifi://")) && !value.isEmpty()) {
|
||||
if (!value.isEmpty() &&
|
||||
!(value.toLower().startsWith("hifi://")) &&
|
||||
!(value.toLower().startsWith("file://"))
|
||||
// TODO: serverless-domains will eventually support http and https also
|
||||
) {
|
||||
return;
|
||||
}
|
||||
withWriteLock([&] {
|
||||
|
|
|
@ -2864,6 +2864,9 @@ void EntityItemProperties::markAllChanged() {
|
|||
_ambientLight.markAllChanged();
|
||||
_skybox.markAllChanged();
|
||||
|
||||
_keyLightModeChanged = true;
|
||||
_skyboxModeChanged = true;
|
||||
_ambientLightModeChanged = true;
|
||||
_hazeModeChanged = true;
|
||||
|
||||
_animation.markAllChanged();
|
||||
|
|
|
@ -596,7 +596,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) {
|
|||
shouldDelete = false;
|
||||
} else {
|
||||
// only delete local entities, server entities will round trip through the server filters
|
||||
if (entity->getClientOnly()) {
|
||||
if (entity->getClientOnly() || _entityTree->isServerlessMode()) {
|
||||
_entityTree->deleteEntity(entityID);
|
||||
}
|
||||
}
|
||||
|
@ -1285,10 +1285,10 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
|
|||
}
|
||||
|
||||
doTransmit = actor(simulation, entity);
|
||||
_entityTree->entityChanged(entity);
|
||||
if (doTransmit) {
|
||||
properties.setClientOnly(entity->getClientOnly());
|
||||
properties.setOwningAvatarID(entity->getOwningAvatarID());
|
||||
_entityTree->entityChanged(entity);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -493,7 +493,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
|
|||
|
||||
if (!properties.getClientOnly() && getIsClient() &&
|
||||
!nodeList->getThisNodeCanRez() && !nodeList->getThisNodeCanRezTmp() &&
|
||||
!nodeList->getThisNodeCanRezCertified() && !nodeList->getThisNodeCanRezTmpCertified()) {
|
||||
!nodeList->getThisNodeCanRezCertified() && !nodeList->getThisNodeCanRezTmpCertified() && !_serverlessDomain) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1509,7 +1509,8 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
|
|||
}
|
||||
|
||||
if (isAdd && properties.getLocked() && !senderNode->isAllowedEditor()) {
|
||||
// if a node can't change locks, don't allow them to create an already-locked entity
|
||||
// if a node can't change locks, don't allow it to create an already-locked entity -- automatically
|
||||
// clear the locked property and allow the unlocked entity to be created.
|
||||
properties.setLocked(false);
|
||||
bumpTimestamp(properties);
|
||||
}
|
||||
|
@ -2181,23 +2182,25 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
|
|||
localTree->recurseTreeWithOperator(&moveOperator);
|
||||
}
|
||||
|
||||
// send add-entity packets to the server
|
||||
i = map.begin();
|
||||
while (i != map.end()) {
|
||||
EntityItemID newID = i.value();
|
||||
EntityItemPointer entity = localTree->findEntityByEntityItemID(newID);
|
||||
if (entity) {
|
||||
// queue the packet to send to the server
|
||||
entity->updateQueryAACube();
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityAdd, localTree, newID, properties);
|
||||
i++;
|
||||
} else {
|
||||
i = map.erase(i);
|
||||
if (!_serverlessDomain) {
|
||||
// send add-entity packets to the server
|
||||
i = map.begin();
|
||||
while (i != map.end()) {
|
||||
EntityItemID newID = i.value();
|
||||
EntityItemPointer entity = localTree->findEntityByEntityItemID(newID);
|
||||
if (entity) {
|
||||
// queue the packet to send to the server
|
||||
entity->updateQueryAACube();
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityAdd, localTree, newID, properties);
|
||||
i++;
|
||||
} else {
|
||||
i = map.erase(i);
|
||||
}
|
||||
}
|
||||
packetSender->releaseQueuedMessages();
|
||||
}
|
||||
packetSender->releaseQueuedMessages();
|
||||
|
||||
return map.values().toVector();
|
||||
}
|
||||
|
|
|
@ -283,6 +283,9 @@ public:
|
|||
|
||||
void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; }
|
||||
|
||||
void setIsServerlessMode(bool value) { _serverlessDomain = value; }
|
||||
bool isServerlessMode() const { return _serverlessDomain; }
|
||||
|
||||
static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
|
||||
static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; }
|
||||
static bool addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName);
|
||||
|
@ -325,7 +328,7 @@ protected:
|
|||
void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode);
|
||||
|
||||
bool isScriptInWhitelist(const QString& scriptURL);
|
||||
|
||||
|
||||
QReadWriteLock _newlyCreatedHooksLock;
|
||||
QVector<NewlyCreatedEntityHook*> _newlyCreatedHooks;
|
||||
|
||||
|
@ -412,6 +415,8 @@ private:
|
|||
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
|
||||
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToOverlayOperator;
|
||||
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromOverlayOperator;
|
||||
|
||||
bool _serverlessDomain { false };
|
||||
};
|
||||
|
||||
#endif // hifi_EntityTree_h
|
||||
|
|
|
@ -38,11 +38,13 @@
|
|||
#include <NumericalConstants.h>
|
||||
#include <shared/NsightHelpers.h>
|
||||
#include <shared/FileUtils.h>
|
||||
#include <PathUtils.h>
|
||||
#include <Finally.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "NetworkLogging.h"
|
||||
#include "ModelNetworkingLogging.h"
|
||||
#include "NetworkingConstants.h"
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
|
||||
|
@ -467,7 +469,7 @@ void NetworkTexture::makeLocalRequest() {
|
|||
const QString scheme = _url.scheme();
|
||||
QString path;
|
||||
if (scheme == URL_SCHEME_FILE) {
|
||||
path = _url.toLocalFile();
|
||||
path = PathUtils::expandToLocalDataAbsolutePath(_url).toLocalFile();
|
||||
} else {
|
||||
path = ":" + _url.path();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <NumericalConstants.h>
|
||||
#include <SettingHandle.h>
|
||||
#include <UUID.h>
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include "AddressManager.h"
|
||||
#include "NodeList.h"
|
||||
|
@ -40,27 +41,14 @@ const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
|
|||
|
||||
Setting::Handle<QUrl> currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_HIFI_ADDRESS);
|
||||
|
||||
AddressManager::AddressManager() :
|
||||
_port(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool AddressManager::isConnected() {
|
||||
return DependencyManager::get<NodeList>()->getDomainHandler().isConnected();
|
||||
}
|
||||
|
||||
QUrl AddressManager::currentAddress(bool domainOnly) const {
|
||||
QUrl hifiURL;
|
||||
QUrl hifiURL = _domainURL;
|
||||
|
||||
hifiURL.setScheme(HIFI_URL_SCHEME);
|
||||
hifiURL.setHost(_host);
|
||||
|
||||
if (_port != 0 && _port != DEFAULT_DOMAIN_SERVER_PORT) {
|
||||
hifiURL.setPort(_port);
|
||||
}
|
||||
|
||||
if (!domainOnly) {
|
||||
if (!domainOnly && hifiURL.scheme() == URL_SCHEME_HIFI) {
|
||||
hifiURL.setPath(currentPath());
|
||||
}
|
||||
|
||||
|
@ -69,7 +57,9 @@ QUrl AddressManager::currentAddress(bool domainOnly) const {
|
|||
|
||||
QUrl AddressManager::currentFacingAddress() const {
|
||||
auto hifiURL = currentAddress();
|
||||
hifiURL.setPath(currentFacingPath());
|
||||
if (hifiURL.scheme() == URL_SCHEME_HIFI) {
|
||||
hifiURL.setPath(currentFacingPath());
|
||||
}
|
||||
|
||||
return hifiURL;
|
||||
}
|
||||
|
@ -79,7 +69,7 @@ QUrl AddressManager::currentShareableAddress(bool domainOnly) const {
|
|||
// if we have a shareable place name use that instead of whatever the current host is
|
||||
QUrl hifiURL;
|
||||
|
||||
hifiURL.setScheme(HIFI_URL_SCHEME);
|
||||
hifiURL.setScheme(URL_SCHEME_HIFI);
|
||||
hifiURL.setHost(_shareablePlaceName);
|
||||
|
||||
if (!domainOnly) {
|
||||
|
@ -94,7 +84,9 @@ QUrl AddressManager::currentShareableAddress(bool domainOnly) const {
|
|||
|
||||
QUrl AddressManager::currentFacingShareableAddress() const {
|
||||
auto hifiURL = currentShareableAddress();
|
||||
hifiURL.setPath(currentFacingPath());
|
||||
if (hifiURL.scheme() == URL_SCHEME_HIFI) {
|
||||
hifiURL.setPath(currentFacingPath());
|
||||
}
|
||||
|
||||
return hifiURL;
|
||||
}
|
||||
|
@ -139,11 +131,16 @@ void AddressManager::goForward() {
|
|||
|
||||
void AddressManager::storeCurrentAddress() {
|
||||
auto url = currentAddress();
|
||||
|
||||
if (!url.host().isEmpty()) {
|
||||
|
||||
if (url.scheme() == URL_SCHEME_FILE ||
|
||||
(url.scheme() == URL_SCHEME_HIFI && !url.host().isEmpty())) {
|
||||
// TODO -- once Octree::readFromURL no-longer takes over the main event-loop, serverless-domain urls can
|
||||
// be loaded over http(s)
|
||||
// url.scheme() == URL_SCHEME_HTTP ||
|
||||
// url.scheme() == URL_SCHEME_HTTPS ||
|
||||
currentAddressHandle.set(url);
|
||||
} else {
|
||||
qCWarning(networking) << "Ignoring attempt to save current address with an empty host" << url;
|
||||
qCWarning(networking) << "Ignoring attempt to save current address with an invalid url:" << url;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +206,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
|||
static QString URL_TYPE_DOMAIN_ID = "domain_id";
|
||||
static QString URL_TYPE_PLACE = "place";
|
||||
static QString URL_TYPE_NETWORK_ADDRESS = "network_address";
|
||||
if (lookupUrl.scheme() == HIFI_URL_SCHEME) {
|
||||
if (lookupUrl.scheme() == URL_SCHEME_HIFI) {
|
||||
|
||||
qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString();
|
||||
|
||||
|
@ -289,12 +286,36 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
|||
handlePath(lookupUrl.path(), trigger, true);
|
||||
emit lookupResultsFinished();
|
||||
|
||||
return true;
|
||||
} else if (lookupUrl.scheme() == URL_SCHEME_FILE) {
|
||||
// TODO -- once Octree::readFromURL no-longer takes over the main event-loop, serverless-domain urls can
|
||||
// be loaded over http(s)
|
||||
// lookupUrl.scheme() == URL_SCHEME_HTTP ||
|
||||
// lookupUrl.scheme() == URL_SCHEME_HTTPS ||
|
||||
_previousLookup.clear();
|
||||
QUrl domainURL = PathUtils::expandToLocalDataAbsolutePath(lookupUrl);
|
||||
setDomainInfo(domainURL, trigger);
|
||||
emit lookupResultsFinished();
|
||||
handlePath(DOMAIN_SPAWNING_POINT, LookupTrigger::Internal, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isPossiblePlaceName(QString possiblePlaceName) {
|
||||
bool result { false };
|
||||
int length = possiblePlaceName.length();
|
||||
static const int MINIMUM_PLACENAME_LENGTH = 1;
|
||||
static const int MAXIMUM_PLACENAME_LENGTH = 64;
|
||||
if (possiblePlaceName.toLower() != "localhost" &&
|
||||
length >= MINIMUM_PLACENAME_LENGTH && length <= MAXIMUM_PLACENAME_LENGTH) {
|
||||
const QRegExp PLACE_NAME_REGEX = QRegExp("^[0-9A-Za-z](([0-9A-Za-z]|-(?!-))*[^\\W_]$|$)");
|
||||
result = PLACE_NAME_REGEX.indexIn(possiblePlaceName) == 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void AddressManager::handleLookupString(const QString& lookupString, bool fromSuggestions) {
|
||||
if (!lookupString.isEmpty()) {
|
||||
// make this a valid hifi URL and handle it off to handleUrl
|
||||
|
@ -302,12 +323,16 @@ void AddressManager::handleLookupString(const QString& lookupString, bool fromSu
|
|||
QUrl lookupURL;
|
||||
|
||||
if (!lookupString.startsWith('/')) {
|
||||
const QRegExp HIFI_SCHEME_REGEX = QRegExp(HIFI_URL_SCHEME + ":\\/{1,2}", Qt::CaseInsensitive);
|
||||
// sometimes we need to handle lookupStrings like hifi:/somewhere
|
||||
const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/{1,2}", Qt::CaseInsensitive);
|
||||
sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX);
|
||||
|
||||
lookupURL = QUrl(HIFI_URL_SCHEME + "://" + sanitizedString);
|
||||
lookupURL = QUrl(sanitizedString);
|
||||
if (lookupURL.scheme().isEmpty()) {
|
||||
lookupURL = QUrl("hifi://" + sanitizedString);
|
||||
}
|
||||
} else {
|
||||
lookupURL = QUrl(lookupString);
|
||||
lookupURL = QUrl(sanitizedString);
|
||||
}
|
||||
|
||||
handleUrl(lookupURL, fromSuggestions ? Suggestions : UserInput);
|
||||
|
@ -385,7 +410,11 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
|
|||
|
||||
qCDebug(networking) << "Possible domain change required to connect to" << domainHostname
|
||||
<< "on" << domainPort;
|
||||
emit possibleDomainChangeRequired(domainHostname, domainPort, domainID);
|
||||
QUrl domainURL;
|
||||
domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
domainURL.setHost(domainHostname);
|
||||
domainURL.setPort(domainPort);
|
||||
emit possibleDomainChangeRequired(domainURL, domainID);
|
||||
} else {
|
||||
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
|
||||
|
||||
|
@ -422,15 +451,10 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
|
|||
if (setHost(placeName, trigger)) {
|
||||
trigger = LookupTrigger::Internal;
|
||||
}
|
||||
|
||||
_placeName = placeName;
|
||||
} else {
|
||||
if (setHost(domainIDString, trigger)) {
|
||||
trigger = LookupTrigger::Internal;
|
||||
}
|
||||
|
||||
// this isn't a place, so clear the place name
|
||||
_placeName.clear();
|
||||
}
|
||||
|
||||
// check if we had a path to override the path returned
|
||||
|
@ -551,13 +575,17 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri
|
|||
if (ipAddressRegex.indexIn(lookupString) != -1) {
|
||||
QString domainIPString = ipAddressRegex.cap(1);
|
||||
|
||||
qint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
|
||||
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
|
||||
if (!ipAddressRegex.cap(2).isEmpty()) {
|
||||
domainPort = (qint16) ipAddressRegex.cap(2).toInt();
|
||||
domainPort = (quint16) ipAddressRegex.cap(2).toInt();
|
||||
}
|
||||
|
||||
emit lookupResultsFinished();
|
||||
hostChanged = setDomainInfo(domainIPString, domainPort, trigger);
|
||||
QUrl domainURL;
|
||||
domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
domainURL.setHost(domainIPString);
|
||||
domainURL.setPort(domainPort);
|
||||
hostChanged = setDomainInfo(domainURL, trigger);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -570,11 +598,15 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri
|
|||
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
|
||||
|
||||
if (!hostnameRegex.cap(2).isEmpty()) {
|
||||
domainPort = (qint16)hostnameRegex.cap(2).toInt();
|
||||
domainPort = (quint16)hostnameRegex.cap(2).toInt();
|
||||
}
|
||||
|
||||
emit lookupResultsFinished();
|
||||
hostChanged = setDomainInfo(domainHostname, domainPort, trigger);
|
||||
QUrl domainURL;
|
||||
domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
domainURL.setHost(domainHostname);
|
||||
domainURL.setPort(domainPort);
|
||||
hostChanged = setDomainInfo(domainURL, trigger);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -643,7 +675,7 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should
|
|||
addCurrentAddressToHistory(trigger);
|
||||
}
|
||||
|
||||
if (!isNaN(newPosition.x) && !isNaN(newPosition.y) && !isNaN(newPosition.z)) {
|
||||
if (!isNaN(newPosition)) {
|
||||
glm::quat newOrientation;
|
||||
|
||||
QRegExp orientationRegex(QUAT_REGEX_STRING);
|
||||
|
@ -663,11 +695,11 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should
|
|||
&& !isNaN(newOrientation.w)) {
|
||||
orientationChanged = true;
|
||||
} else {
|
||||
qCDebug(networking) << "Orientation parsed from lookup string is invalid. Will not use for location change.";
|
||||
qCDebug(networking) << "Orientation parsed from lookup string is invalid. Won't use for location change.";
|
||||
}
|
||||
}
|
||||
|
||||
emit locationChangeRequired(newPosition, orientationChanged,
|
||||
|
||||
emit locationChangeRequired(newPosition, orientationChanged,
|
||||
trigger == LookupTrigger::VisitUserFromPAL ? cancelOutRollAndPitch(newOrientation): newOrientation,
|
||||
shouldFace
|
||||
);
|
||||
|
@ -698,18 +730,20 @@ bool AddressManager::handleUsername(const QString& lookupString) {
|
|||
}
|
||||
|
||||
bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16 port) {
|
||||
if (host != _host || port != _port) {
|
||||
|
||||
if (host != _domainURL.host() || port != _domainURL.port()) {
|
||||
addCurrentAddressToHistory(trigger);
|
||||
|
||||
_port = port;
|
||||
bool emitHostChanged = host != _domainURL.host();
|
||||
_domainURL = QUrl();
|
||||
_domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
_domainURL.setHost(host);
|
||||
_domainURL.setPort(port);
|
||||
|
||||
// any host change should clear the shareable place name
|
||||
_shareablePlaceName.clear();
|
||||
|
||||
if (host != _host) {
|
||||
_host = host;
|
||||
emit hostChanged(_host);
|
||||
if (emitHostChanged) {
|
||||
emit hostChanged(host);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -718,20 +752,43 @@ bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AddressManager::setDomainInfo(const QString& hostname, quint16 port, LookupTrigger trigger) {
|
||||
bool hostChanged = setHost(hostname, trigger, port);
|
||||
QString AddressManager::getHost() const {
|
||||
if (isPossiblePlaceName(_domainURL.host())) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return _domainURL.host();
|
||||
}
|
||||
|
||||
bool AddressManager::setDomainInfo(const QUrl& domainURL, LookupTrigger trigger) {
|
||||
const QString hostname = domainURL.host();
|
||||
quint16 port = domainURL.port();
|
||||
bool emitHostChanged { false };
|
||||
|
||||
if (domainURL != _domainURL) {
|
||||
addCurrentAddressToHistory(trigger);
|
||||
emitHostChanged = true;
|
||||
}
|
||||
|
||||
_domainURL = domainURL;
|
||||
|
||||
// clear any current place information
|
||||
_rootPlaceID = QUuid();
|
||||
_placeName.clear();
|
||||
|
||||
qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port;
|
||||
if (_domainURL.scheme() == URL_SCHEME_HIFI) {
|
||||
qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port;
|
||||
} else {
|
||||
qCDebug(networking) << "Possible domain change required to serverless domain: " << domainURL.toString();
|
||||
}
|
||||
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::HandleAddress);
|
||||
|
||||
emit possibleDomainChangeRequired(hostname, port, QUuid());
|
||||
if (emitHostChanged) {
|
||||
emit hostChanged(domainURL.host());
|
||||
}
|
||||
emit possibleDomainChangeRequired(_domainURL, QUuid());
|
||||
|
||||
return hostChanged;
|
||||
return emitHostChanged;
|
||||
}
|
||||
|
||||
void AddressManager::goToUser(const QString& username, bool shouldMatchOrientation) {
|
||||
|
@ -820,7 +877,7 @@ void AddressManager::lookupShareableNameForDomainID(const QUuid& domainID) {
|
|||
// 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()) {
|
||||
if (getPlaceName().isEmpty()) {
|
||||
JSONCallbackParameters callbackParams;
|
||||
|
||||
// no error callback handling
|
||||
|
@ -872,3 +929,12 @@ void AddressManager::addCurrentAddressToHistory(LookupTrigger trigger) {
|
|||
}
|
||||
}
|
||||
|
||||
QString AddressManager::getPlaceName() const {
|
||||
if (!_shareablePlaceName.isEmpty()) {
|
||||
return _shareablePlaceName;
|
||||
}
|
||||
if (isPossiblePlaceName(_domainURL.host())) {
|
||||
return _domainURL.host();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#include "AccountManager.h"
|
||||
|
||||
const QString HIFI_URL_SCHEME = "hifi";
|
||||
|
||||
extern const QString DEFAULT_HIFI_ADDRESS;
|
||||
|
||||
const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost";
|
||||
|
@ -147,7 +145,7 @@ public:
|
|||
};
|
||||
|
||||
bool isConnected();
|
||||
const QString& getProtocol() { return HIFI_URL_SCHEME; };
|
||||
const QString& getProtocol() { return URL_SCHEME_HIFI; };
|
||||
|
||||
QUrl currentAddress(bool domainOnly = false) const;
|
||||
QUrl currentFacingAddress() const;
|
||||
|
@ -157,10 +155,10 @@ public:
|
|||
QString currentFacingPath() const;
|
||||
|
||||
const QUuid& getRootPlaceID() const { return _rootPlaceID; }
|
||||
const QString& getPlaceName() const { return _shareablePlaceName.isEmpty() ? _placeName : _shareablePlaceName; }
|
||||
QString getPlaceName() const;
|
||||
QString getDomainID() const;
|
||||
|
||||
const QString& getHost() const { return _host; }
|
||||
QString getHost() const;
|
||||
|
||||
void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; }
|
||||
void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
|
||||
|
@ -170,6 +168,8 @@ public:
|
|||
const QStack<QUrl>& getBackStack() const { return _backStack; }
|
||||
const QStack<QUrl>& getForwardStack() const { return _forwardStack; }
|
||||
|
||||
QUrl getDomainURL() { return _domainURL; }
|
||||
|
||||
public slots:
|
||||
/**jsdoc
|
||||
* Go to a specified metaverse address.
|
||||
|
@ -302,13 +302,12 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered when a request is made to go to an IP address.
|
||||
* @function location.possibleDomainChangeRequired
|
||||
* @param {string} hostName - The name of the domain to go do.
|
||||
* @param {number} port - The integer number of the network port to connect to.
|
||||
* @param {Url} domainURL - URL for domain
|
||||
* @param {Uuid} domainID - The UUID of the domain to go to.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
// No example because this function isn't typically used in scripts.
|
||||
void possibleDomainChangeRequired(const QString& newHostname, quint16 newPort, const QUuid& domainID);
|
||||
void possibleDomainChangeRequired(QUrl domainURL, QUuid domainID);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a request is made to go to a named domain or user.
|
||||
|
@ -360,7 +359,7 @@ signals:
|
|||
* location.pathChangeRequired.connect(onPathChangeRequired);
|
||||
*/
|
||||
void pathChangeRequired(const QString& newPath);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when you navigate to a new domain.
|
||||
* @function location.hostChanged
|
||||
|
@ -392,7 +391,7 @@ signals:
|
|||
void goBackPossible(bool isPossible);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when there's a change in whether or not there's a forward location that can be navigated to using
|
||||
* Triggered when there's a change in whether or not there's a forward location that can be navigated to using
|
||||
* {@link location.goForward|goForward}. (Reflects changes in the state of the "Goto" dialog's forward arrow.)
|
||||
* @function location.goForwardPossible
|
||||
* @param {boolean} isPossible - <code>true</code> if there's a forward location to navigate to, otherwise
|
||||
|
@ -407,8 +406,6 @@ signals:
|
|||
*/
|
||||
void goForwardPossible(bool isPossible);
|
||||
|
||||
protected:
|
||||
AddressManager();
|
||||
private slots:
|
||||
void handleAPIResponse(QNetworkReply& requestReply);
|
||||
void handleAPIError(QNetworkReply& errorReply);
|
||||
|
@ -420,7 +417,7 @@ private:
|
|||
|
||||
// Set host and port, and return `true` if it was changed.
|
||||
bool setHost(const QString& host, LookupTrigger trigger, quint16 port = 0);
|
||||
bool setDomainInfo(const QString& hostname, quint16 port, LookupTrigger trigger);
|
||||
bool setDomainInfo(const QUrl& domainURL, LookupTrigger trigger);
|
||||
|
||||
const JSONCallbackParameters& apiCallbackParameters();
|
||||
|
||||
|
@ -438,9 +435,8 @@ private:
|
|||
|
||||
void addCurrentAddressToHistory(LookupTrigger trigger);
|
||||
|
||||
QString _host;
|
||||
quint16 _port;
|
||||
QString _placeName;
|
||||
QUrl _domainURL;
|
||||
|
||||
QUuid _rootPlaceID;
|
||||
PositionGetter _positionGetter;
|
||||
OrientationGetter _orientationGetter;
|
||||
|
@ -452,7 +448,7 @@ private:
|
|||
quint64 _lastBackPush = 0;
|
||||
|
||||
QString _newHostLookupPath;
|
||||
|
||||
|
||||
QUrl _previousLookup;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "NetworkAccessManager.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include "NetworkingConstants.h"
|
||||
|
||||
#include "ResourceManager.h"
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ DomainHandler::DomainHandler(QObject* parent) :
|
|||
|
||||
// if we get a socket that make sure our NetworkPeer ping timer stops
|
||||
connect(this, &DomainHandler::completedSocketDiscovery, &_icePeer, &NetworkPeer::stopPingTimer);
|
||||
|
||||
|
||||
// setup a timeout for failure on settings requests
|
||||
static const int DOMAIN_SETTINGS_TIMEOUT_MS = 5000;
|
||||
_settingsTimer.setInterval(DOMAIN_SETTINGS_TIMEOUT_MS); // 5s, Qt::CoarseTimer acceptable
|
||||
|
@ -60,11 +60,11 @@ void DomainHandler::disconnect() {
|
|||
if (_isConnected) {
|
||||
sendDisconnectPacket();
|
||||
}
|
||||
|
||||
|
||||
// clear member variables that hold the connection state to a domain
|
||||
_uuid = QUuid();
|
||||
_connectionToken = QUuid();
|
||||
|
||||
|
||||
_icePeer.reset();
|
||||
|
||||
if (requiresICE()) {
|
||||
|
@ -78,10 +78,10 @@ void DomainHandler::disconnect() {
|
|||
void DomainHandler::sendDisconnectPacket() {
|
||||
// The DomainDisconnect packet is not verified - we're relying on the eventual addition of DTLS to the
|
||||
// domain-server connection to stop greifing here
|
||||
|
||||
|
||||
// construct the disconnect packet once (an empty packet but sourced with our current session UUID)
|
||||
static auto disconnectPacket = NLPacket::create(PacketType::DomainDisconnectRequest, 0);
|
||||
|
||||
|
||||
// send the disconnect packet to the current domain server
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->sendUnreliablePacket(*disconnectPacket, _sockAddr);
|
||||
|
@ -94,7 +94,7 @@ void DomainHandler::clearSettings() {
|
|||
void DomainHandler::softReset() {
|
||||
qCDebug(networking) << "Resetting current domain connection information.";
|
||||
disconnect();
|
||||
|
||||
|
||||
clearSettings();
|
||||
|
||||
_connectionDenialsSinceKeypairRegen = 0;
|
||||
|
@ -115,8 +115,8 @@ void DomainHandler::hardReset() {
|
|||
qCDebug(networking) << "Hard reset in NodeList DomainHandler.";
|
||||
_pendingDomainID = QUuid();
|
||||
_iceServerSockAddr = HifiSockAddr();
|
||||
_hostname = QString();
|
||||
_sockAddr.clear();
|
||||
_domainURL = QUrl();
|
||||
|
||||
_domainConnectionRefusals.clear();
|
||||
|
||||
|
@ -139,7 +139,10 @@ void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hos
|
|||
}
|
||||
|
||||
// some callers may pass a hostname, this is not to be used for lookup but for DTLS certificate verification
|
||||
_hostname = hostname;
|
||||
_domainURL = QUrl();
|
||||
_domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
_domainURL.setHost(hostname);
|
||||
_domainURL.setPort(_sockAddr.getPort());
|
||||
}
|
||||
|
||||
void DomainHandler::setUUID(const QUuid& uuid) {
|
||||
|
@ -149,36 +152,45 @@ void DomainHandler::setUUID(const QUuid& uuid) {
|
|||
}
|
||||
}
|
||||
|
||||
void DomainHandler::setSocketAndID(const QString& hostname, quint16 port, const QUuid& domainID) {
|
||||
|
||||
void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) {
|
||||
_pendingDomainID = domainID;
|
||||
|
||||
if (hostname != _hostname || _sockAddr.getPort() != port) {
|
||||
if (domainURL.scheme() != URL_SCHEME_HIFI) {
|
||||
_sockAddr.clear();
|
||||
}
|
||||
|
||||
if (_domainURL != domainURL || _sockAddr.getPort() != domainURL.port()) {
|
||||
// re-set the domain info so that auth information is reloaded
|
||||
hardReset();
|
||||
|
||||
if (hostname != _hostname) {
|
||||
// set the new hostname
|
||||
_hostname = hostname;
|
||||
QString previousHost = _domainURL.host();
|
||||
_domainURL = domainURL;
|
||||
|
||||
qCDebug(networking) << "Updated domain hostname to" << _hostname;
|
||||
if (domainURL.scheme() != URL_SCHEME_HIFI) {
|
||||
setIsConnected(true);
|
||||
} else if (previousHost != domainURL.host()) {
|
||||
qCDebug(networking) << "Updated domain hostname to" << domainURL.host();
|
||||
|
||||
// re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname
|
||||
qCDebug(networking, "Looking up DS hostname %s.", _hostname.toLocal8Bit().constData());
|
||||
QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup(const QHostInfo&)));
|
||||
if (!domainURL.host().isEmpty()) {
|
||||
// re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname
|
||||
qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData());
|
||||
QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&)));
|
||||
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetDomainHostname);
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(
|
||||
LimitedNodeList::ConnectionStep::SetDomainHostname);
|
||||
|
||||
UserActivityLogger::getInstance().changedDomain(_hostname);
|
||||
emit hostnameChanged(_hostname);
|
||||
UserActivityLogger::getInstance().changedDomain(domainURL.host());
|
||||
}
|
||||
}
|
||||
|
||||
if (_sockAddr.getPort() != port) {
|
||||
qCDebug(networking) << "Updated domain port to" << port;
|
||||
emit domainURLChanged(_domainURL);
|
||||
|
||||
if (_sockAddr.getPort() != domainURL.port()) {
|
||||
qCDebug(networking) << "Updated domain port to" << domainURL.port();
|
||||
}
|
||||
|
||||
// grab the port by reading the string after the colon
|
||||
_sockAddr.setPort(port);
|
||||
_sockAddr.setPort(domainURL.port());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,10 +199,10 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname,
|
|||
if (_iceServerSockAddr.getAddress().toString() != iceServerHostname || id != _pendingDomainID) {
|
||||
// re-set the domain info to connect to new domain
|
||||
hardReset();
|
||||
|
||||
|
||||
// refresh our ICE client UUID to something new
|
||||
_iceClientID = QUuid::createUuid();
|
||||
|
||||
|
||||
_pendingDomainID = id;
|
||||
|
||||
HifiSockAddr* replaceableSockAddr = &_iceServerSockAddr;
|
||||
|
@ -216,14 +228,18 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname,
|
|||
void DomainHandler::activateICELocalSocket() {
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetDomainSocket);
|
||||
_sockAddr = _icePeer.getLocalSocket();
|
||||
_hostname = _sockAddr.getAddress().toString();
|
||||
_domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
_domainURL.setHost(_sockAddr.getAddress().toString());
|
||||
emit domainURLChanged(_domainURL);
|
||||
emit completedSocketDiscovery();
|
||||
}
|
||||
|
||||
void DomainHandler::activateICEPublicSocket() {
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetDomainSocket);
|
||||
_sockAddr = _icePeer.getPublicSocket();
|
||||
_hostname = _sockAddr.getAddress().toString();
|
||||
_domainURL.setScheme(URL_SCHEME_HIFI);
|
||||
_domainURL.setHost(_sockAddr.getAddress().toString());
|
||||
emit domainURLChanged(_domainURL);
|
||||
emit completedSocketDiscovery();
|
||||
}
|
||||
|
||||
|
@ -234,7 +250,7 @@ void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
|
|||
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetDomainSocket);
|
||||
|
||||
qCDebug(networking, "DS at %s is at %s", _hostname.toLocal8Bit().constData(),
|
||||
qCDebug(networking, "DS at %s is at %s", _domainURL.host().toLocal8Bit().constData(),
|
||||
_sockAddr.getAddress().toString().toLocal8Bit().constData());
|
||||
|
||||
emit completedSocketDiscovery();
|
||||
|
@ -261,10 +277,12 @@ void DomainHandler::setIsConnected(bool isConnected) {
|
|||
_isConnected = isConnected;
|
||||
|
||||
if (_isConnected) {
|
||||
emit connectedToDomain(_hostname);
|
||||
emit connectedToDomain(_domainURL);
|
||||
|
||||
// we've connected to new domain - time to ask it for global settings
|
||||
requestDomainSettings();
|
||||
if (_domainURL.scheme() == URL_SCHEME_HIFI && !_domainURL.host().isEmpty()) {
|
||||
// we've connected to new domain - time to ask it for global settings
|
||||
requestDomainSettings();
|
||||
}
|
||||
|
||||
} else {
|
||||
emit disconnectedFromDomain();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "NLPacketList.h"
|
||||
#include "Node.h"
|
||||
#include "ReceivedMessage.h"
|
||||
#include "NetworkingConstants.h"
|
||||
|
||||
const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102;
|
||||
const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT = 40103;
|
||||
|
@ -37,14 +38,14 @@ class DomainHandler : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
DomainHandler(QObject* parent = 0);
|
||||
|
||||
|
||||
void disconnect();
|
||||
void clearSettings();
|
||||
|
||||
const QUuid& getUUID() const { return _uuid; }
|
||||
void setUUID(const QUuid& uuid);
|
||||
|
||||
const QString& getHostname() const { return _hostname; }
|
||||
QString getHostname() const { return _domainURL.host(); }
|
||||
|
||||
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
|
||||
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
|
||||
|
@ -57,7 +58,7 @@ public:
|
|||
|
||||
const QUuid& getConnectionToken() const { return _connectionToken; }
|
||||
void setConnectionToken(const QUuid& connectionToken) { _connectionToken = connectionToken; }
|
||||
|
||||
|
||||
const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
|
||||
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
|
||||
|
||||
|
@ -73,11 +74,12 @@ public:
|
|||
|
||||
bool isConnected() const { return _isConnected; }
|
||||
void setIsConnected(bool isConnected);
|
||||
bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; }
|
||||
|
||||
bool hasSettings() const { return !_settingsObject.isEmpty(); }
|
||||
void requestDomainSettings();
|
||||
const QJsonObject& getSettingsObject() const { return _settingsObject; }
|
||||
|
||||
|
||||
void setPendingPath(const QString& pendingPath) { _pendingPath = pendingPath; }
|
||||
const QString& getPendingPath() { return _pendingPath; }
|
||||
void clearPendingPath() { _pendingPath.clear(); }
|
||||
|
@ -139,7 +141,7 @@ public:
|
|||
};
|
||||
|
||||
public slots:
|
||||
void setSocketAndID(const QString& hostname, quint16 port = DEFAULT_DOMAIN_SERVER_PORT, const QUuid& id = QUuid());
|
||||
void setURLAndID(QUrl domainURL, QUuid id);
|
||||
void setIceServerHostnameAndID(const QString& iceServerHostname, const QUuid& id);
|
||||
|
||||
void processSettingsPacketList(QSharedPointer<ReceivedMessage> packetList);
|
||||
|
@ -153,14 +155,14 @@ private slots:
|
|||
void completedIceServerHostnameLookup();
|
||||
|
||||
signals:
|
||||
void hostnameChanged(const QString& hostname);
|
||||
void domainURLChanged(QUrl domainURL);
|
||||
|
||||
// NOTE: the emission of completedSocketDiscovery does not mean a connection to DS is established
|
||||
// It means that, either from DNS lookup or ICE, we think we have a socket we can talk to DS on
|
||||
void completedSocketDiscovery();
|
||||
|
||||
void resetting();
|
||||
void connectedToDomain(const QString& hostname);
|
||||
void connectedToDomain(QUrl domainURL);
|
||||
void disconnectedFromDomain();
|
||||
|
||||
void iceSocketAndIDReceived();
|
||||
|
@ -179,7 +181,7 @@ private:
|
|||
void hardReset();
|
||||
|
||||
QUuid _uuid;
|
||||
QString _hostname;
|
||||
QUrl _domainURL;
|
||||
HifiSockAddr _sockAddr;
|
||||
QUuid _assignmentUUID;
|
||||
QUuid _connectionToken;
|
||||
|
@ -200,4 +202,7 @@ private:
|
|||
QTimer _apiRefreshTimer;
|
||||
};
|
||||
|
||||
const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" };
|
||||
|
||||
|
||||
#endif // hifi_DomainHandler_h
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
|
||||
#include <StatTracker.h>
|
||||
#include <shared/FileUtils.h>
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include "NetworkLogging.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "NetworkingConstants.h"
|
||||
|
||||
void FileResourceRequest::doSend() {
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
|
@ -29,7 +31,7 @@ void FileResourceRequest::doSend() {
|
|||
if (_url.scheme() == URL_SCHEME_QRC) {
|
||||
filename = ":/" + _url.path();
|
||||
} else {
|
||||
filename = _url.toLocalFile();
|
||||
filename = PathUtils::expandToLocalDataAbsolutePath(_url).toLocalFile();
|
||||
// sometimes on windows, we see the toLocalFile() return null,
|
||||
// in this case we will attempt to simply use the url as a string
|
||||
if (filename.isEmpty()) {
|
||||
|
|
24
libraries/networking/src/NetworkingConstants.cpp
Normal file
24
libraries/networking/src/NetworkingConstants.cpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// NetworkingConstants.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Seth Alves on 2018-2-28.
|
||||
// Copyright 2018 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 "NetworkingConstants.h"
|
||||
|
||||
namespace NetworkingConstants {
|
||||
// You can change the return of this function if you want to use a custom metaverse URL at compile time
|
||||
// or you can pass a custom URL via the env variable
|
||||
QUrl METAVERSE_SERVER_URL() {
|
||||
const QString HIFI_METAVERSE_URL_ENV = "HIFI_METAVERSE_URL";
|
||||
const QUrl serverURL = QProcessEnvironment::systemEnvironment().contains(HIFI_METAVERSE_URL_ENV)
|
||||
? QUrl(QProcessEnvironment::systemEnvironment().value(HIFI_METAVERSE_URL_ENV))
|
||||
: METAVERSE_SERVER_URL_STABLE;
|
||||
return serverURL;
|
||||
};
|
||||
}
|
|
@ -25,18 +25,17 @@ namespace NetworkingConstants {
|
|||
// if you manually generate a personal access token for the domains scope
|
||||
// at https://staging.highfidelity.com/user/tokens/new?for_domain_server=true
|
||||
|
||||
const QUrl METAVERSE_SERVER_URL_STABLE("https://metaverse.highfidelity.com");
|
||||
const QUrl METAVERSE_SERVER_URL_STAGING("https://staging.highfidelity.com");
|
||||
|
||||
// You can change the return of this function if you want to use a custom metaverse URL at compile time
|
||||
// or you can pass a custom URL via the env variable
|
||||
static const QUrl METAVERSE_SERVER_URL() {
|
||||
static const QString HIFI_METAVERSE_URL_ENV = "HIFI_METAVERSE_URL";
|
||||
static const QUrl serverURL = QProcessEnvironment::systemEnvironment().contains(HIFI_METAVERSE_URL_ENV)
|
||||
? QUrl(QProcessEnvironment::systemEnvironment().value(HIFI_METAVERSE_URL_ENV))
|
||||
: METAVERSE_SERVER_URL_STABLE;
|
||||
return serverURL;
|
||||
};
|
||||
const QUrl METAVERSE_SERVER_URL_STABLE { "https://metaverse.highfidelity.com" };
|
||||
const QUrl METAVERSE_SERVER_URL_STAGING { "https://staging.highfidelity.com" };
|
||||
QUrl METAVERSE_SERVER_URL();
|
||||
}
|
||||
|
||||
const QString URL_SCHEME_HIFI = "hifi";
|
||||
const QString URL_SCHEME_QRC = "qrc";
|
||||
const QString URL_SCHEME_FILE = "file";
|
||||
const QString URL_SCHEME_HTTP = "http";
|
||||
const QString URL_SCHEME_HTTPS = "https";
|
||||
const QString URL_SCHEME_FTP = "ftp";
|
||||
const QString URL_SCHEME_ATP = "atp";
|
||||
|
||||
#endif // hifi_NetworkingConstants_h
|
||||
|
|
|
@ -55,7 +55,7 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
|||
|
||||
// handle domain change signals from AddressManager
|
||||
connect(addressManager.data(), &AddressManager::possibleDomainChangeRequired,
|
||||
&_domainHandler, &DomainHandler::setSocketAndID);
|
||||
&_domainHandler, &DomainHandler::setURLAndID);
|
||||
|
||||
connect(addressManager.data(), &AddressManager::possibleDomainChangeRequiredViaICEForID,
|
||||
&_domainHandler, &DomainHandler::setIceServerHostnameAndID);
|
||||
|
@ -91,7 +91,7 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
|||
connect(accountManager.data(), &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn);
|
||||
|
||||
// clear out NodeList when login is finished
|
||||
connect(accountManager.data(), SIGNAL(loginComplete()) , this, SLOT(reset()));
|
||||
connect(accountManager.data(), SIGNAL(loginComplete(const QUrl&)) , this, SLOT(reset()));
|
||||
|
||||
// clear our NodeList when logout is requested
|
||||
connect(accountManager.data(), SIGNAL(logoutComplete()) , this, SLOT(reset()));
|
||||
|
@ -106,7 +106,7 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
|||
// setup our timer to send keepalive pings (it's started and stopped on domain connect/disconnect)
|
||||
_keepAlivePingTimer.setInterval(KEEPALIVE_PING_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable
|
||||
connect(&_keepAlivePingTimer, &QTimer::timeout, this, &NodeList::sendKeepAlivePings);
|
||||
connect(&_domainHandler, SIGNAL(connectedToDomain(QString)), &_keepAlivePingTimer, SLOT(start()));
|
||||
connect(&_domainHandler, SIGNAL(connectedToDomain(QUrl)), &_keepAlivePingTimer, SLOT(start()));
|
||||
connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, &_keepAlivePingTimer, &QTimer::stop);
|
||||
|
||||
// set our sockAddrBelongsToDomainOrNode method as the connection creation filter for the udt::Socket
|
||||
|
|
|
@ -22,13 +22,6 @@
|
|||
|
||||
#include "ResourceRequest.h"
|
||||
|
||||
const QString URL_SCHEME_QRC = "qrc";
|
||||
const QString URL_SCHEME_FILE = "file";
|
||||
const QString URL_SCHEME_HTTP = "http";
|
||||
const QString URL_SCHEME_HTTPS = "https";
|
||||
const QString URL_SCHEME_FTP = "ftp";
|
||||
const QString URL_SCHEME_ATP = "atp";
|
||||
|
||||
class ResourceManager: public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
|
|
@ -1685,6 +1685,15 @@ bool Octree::readFromURL(const QString& urlString) {
|
|||
}
|
||||
|
||||
auto data = request->getData();
|
||||
|
||||
QByteArray uncompressedJsonData;
|
||||
bool wasCompressed = gunzip(data, uncompressedJsonData);
|
||||
|
||||
if (wasCompressed) {
|
||||
QDataStream inputStream(uncompressedJsonData);
|
||||
return readFromStream(uncompressedJsonData.size(), inputStream, marketplaceID);
|
||||
}
|
||||
|
||||
QDataStream inputStream(data);
|
||||
return readFromStream(data.size(), inputStream, marketplaceID);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ const QString& PathUtils::resourcesPath() {
|
|||
#else
|
||||
staticResourcePath = ":/";
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(Q_OS_ANDROID) && defined(DEV_BUILD)
|
||||
if (USE_SOURCE_TREE_RESOURCES()) {
|
||||
// For dev builds, optionally load content from the Git source tree
|
||||
|
@ -120,6 +120,31 @@ QUrl PathUtils::resourcesUrl(const QString& relativeUrl) {
|
|||
return QUrl(resourcesUrl() + relativeUrl);
|
||||
}
|
||||
|
||||
QUrl PathUtils::expandToLocalDataAbsolutePath(const QUrl& fileUrl) {
|
||||
QString path = fileUrl.path();
|
||||
|
||||
if (path.startsWith("/~/")) {
|
||||
// this results in a qrc:// url...
|
||||
// return resourcesUrl(path.mid(3));
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/";
|
||||
#elif defined (ANDROID)
|
||||
static const QString staticResourcePath =
|
||||
QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/resources/";
|
||||
#else
|
||||
static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/";
|
||||
#endif
|
||||
path.replace(0, 3, staticResourcePath);
|
||||
QUrl expandedURL = QUrl::fromLocalFile(path);
|
||||
return expandedURL;
|
||||
}
|
||||
|
||||
QUrl::fromLocalFile(resourcesPath()).toString();
|
||||
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
const QString& PathUtils::qmlBaseUrl() {
|
||||
static const QString staticResourcePath = resourcesUrl() + "qml/";
|
||||
return staticResourcePath;
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
static QUrl resourcesUrl(const QString& relative);
|
||||
static const QString& resourcesPath();
|
||||
static const QString& qmlBaseUrl();
|
||||
static QUrl expandToLocalDataAbsolutePath(const QUrl& fileUrl);
|
||||
static QUrl qmlUrl(const QString& relative);
|
||||
#ifdef DEV_BUILD
|
||||
static const QString& projectRootPath();
|
||||
|
|
|
@ -119,7 +119,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
|
|||
nodeList->startThread();
|
||||
|
||||
const DomainHandler& domainHandler = nodeList->getDomainHandler();
|
||||
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
|
||||
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainChanged(QUrl)));
|
||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ACClientApp::domainConnectionRefused);
|
||||
|
||||
connect(nodeList.data(), &NodeList::nodeAdded, this, &ACClientApp::nodeAdded);
|
||||
|
@ -169,7 +169,7 @@ void ACClientApp::domainConnectionRefused(const QString& reasonMessage, int reas
|
|||
qDebug() << "domainConnectionRefused";
|
||||
}
|
||||
|
||||
void ACClientApp::domainChanged(const QString& domainHostname) {
|
||||
void ACClientApp::domainChanged(QUrl domainURL) {
|
||||
if (_verbose) {
|
||||
qDebug() << "domainChanged";
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
private slots:
|
||||
void domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo);
|
||||
void domainChanged(const QString& domainHostname);
|
||||
void domainChanged(QUrl domainURL);
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeActivated(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
|
|
|
@ -158,7 +158,7 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) :
|
|||
nodeList->startThread();
|
||||
|
||||
const DomainHandler& domainHandler = nodeList->getDomainHandler();
|
||||
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
|
||||
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainChanged(QUrl)));
|
||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::domainConnectionRefused);
|
||||
|
||||
connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPClientApp::nodeAdded);
|
||||
|
@ -227,7 +227,7 @@ void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int rea
|
|||
}
|
||||
}
|
||||
|
||||
void ATPClientApp::domainChanged(const QString& domainHostname) {
|
||||
void ATPClientApp::domainChanged(QUrl domainURL) {
|
||||
if (_verbose) {
|
||||
qDebug() << "domainChanged";
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
|
||||
private slots:
|
||||
void domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo);
|
||||
void domainChanged(const QString& domainHostname);
|
||||
void domainChanged(QUrl domainURL);
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeActivated(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
|
|
Loading…
Reference in a new issue