From 85347e32699cf2ed41ed047081b91c0932f0fe75 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 27 Mar 2017 15:55:05 -0700 Subject: [PATCH 1/8] new location protocol --- interface/src/DiscoverabilityManager.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 8fcc1e5477..ff30bd1585 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -40,9 +40,10 @@ void DiscoverabilityManager::updateLocation() { auto accountManager = DependencyManager::get(); auto addressManager = DependencyManager::get(); auto& domainHandler = DependencyManager::get()->getDomainHandler(); + bool discoverable = (_mode.get() != Discoverability::None); - if (_mode.get() != Discoverability::None && accountManager->isLoggedIn()) { + if (accountManager->isLoggedIn()) { // construct a QJsonObject given the user's current address information QJsonObject rootObject; @@ -54,7 +55,7 @@ void DiscoverabilityManager::updateLocation() { locationObject.insert(PATH_KEY_IN_LOCATION, pathString); const QString CONNECTED_KEY_IN_LOCATION = "connected"; - locationObject.insert(CONNECTED_KEY_IN_LOCATION, domainHandler.isConnected()); + locationObject.insert(CONNECTED_KEY_IN_LOCATION, discoverable && domainHandler.isConnected()); if (!addressManager->getRootPlaceID().isNull()) { const QString PLACE_ID_KEY_IN_LOCATION = "place_id"; @@ -140,13 +141,7 @@ void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discov // update the setting to the new value _mode.set(static_cast(discoverabilityMode)); - if (static_cast(_mode.get()) == Discoverability::None) { - // if we just got set to no discoverability, make sure that we delete our location in DB - removeLocation(); - } else { - // we have a discoverability mode that says we should send a location, do that right away - updateLocation(); - } + updateLocation(); // update right away emit discoverabilityModeChanged(discoverabilityMode); } From c2a49a582e6088c11ebb39b1183f4030e4dd4e28 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 28 Mar 2017 16:44:16 -0700 Subject: [PATCH 2/8] send credentials to local metaverse servers, and initial users data integration. --- .../HFWebEngineRequestInterceptor.cpp | 6 +- scripts/system/pal.js | 84 +++++-------------- 2 files changed, 27 insertions(+), 63 deletions(-) diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index 9c3f0b232e..f6b0914f08 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -10,6 +10,7 @@ // #include "HFWebEngineRequestInterceptor.h" +#include "NetworkingConstants.h" #include @@ -20,8 +21,11 @@ bool isAuthableHighFidelityURL(const QUrl& url) { "highfidelity.com", "highfidelity.io", "metaverse.highfidelity.com", "metaverse.highfidelity.io" }; + const auto& scheme = url.scheme(); + const auto& host = url.host(); - return url.scheme() == "https" && HF_HOSTS.contains(url.host()); + return (scheme == "https" && HF_HOSTS.contains(host)) || + ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host())); } void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { diff --git a/scripts/system/pal.js b/scripts/system/pal.js index a7c4f56ea6..80df8413c3 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -334,75 +334,35 @@ function getProfilePicture(username, callback) { // callback(url) if successfull function getAvailableConnections(domain, callback) { // callback([{usename, location}...]) if successfull. (Logs otherwise) // The back end doesn't do user connections yet. Fake it by getting all users that have made themselves accessible to us, // and pretending that they are all connections. - function getData(cb) { - requestJSON(METAVERSE_BASE + '/api/v1/users?status=online', function (connectionsData) { - - // The above does not include friend status. Fetch that separately. - requestJSON(METAVERSE_BASE + '/api/v1/user/friends', function (friendsData) { - var users = connectionsData.users || [], friends = friendsData.friends || []; - users.forEach(function (user) { - user.connection = (friends.indexOf(user.username) < 0) ? 'connection' : 'friend'; - }); - - // The back end doesn't include the profile picture data, but we can add that here. - // For our current purposes, there's no need to be fancy and try to reduce latency by doing some number of requests in parallel, - // so these requests are all sequential. - function addPicture(index) { - if (index >= users.length) { - return cb(users); - } - var user = users[index]; - getProfilePicture(user.username, function (url) { - user.profileUrl = url; - addPicture(index + 1); - }); - } - addPicture(0); - }); - }); - } - + url = METAVERSE_BASE + '/api/v1/users?' if (domain) { - // The back end doesn't keep sessionUUID in the location data yet. Fake it by finding the avatar closest to the path. - var positions = {}; - AvatarList.getAvatarIdentifiers().forEach(function (id) { - positions[id || ''] = AvatarList.getAvatar(id).position; // Don't use null id as a key. Properties must be a string, and we don't want 'null'. - }); - getData(function (users) { - // The endpoint in getData doesn't take a domain filter. So filter out the unwanted stuff now. - domain = domain.slice(1, -1); // without curly braces - users = users.filter(function (user) { return (user.location.domain || (user.location.root && user.location.root.domain) || {}).id === domain; }); - - // Now fill in the sessionUUID as if it were in the data all along. - users.forEach(function (user) { - var coordinates = user.location.path.match(/\/([^,]+)\,([^,]+),([^\/]+)\//); - if (coordinates) { - var position = {x: Number(coordinates[1]), y: Number(coordinates[2]), z: Number(coordinates[3])}; - var none = 'not found', closestId = none, bestDistance = Infinity, distance, id; - for (id in positions) { - distance = Vec3.distance(position, positions[id]); - if (distance < bestDistance) { - closestId = id; - bestDistance = distance; - } - } - if (closestId !== none) { - user.location.sessionUUID = closestId; - } - } - }); - - callback(users); - }); - } else { // We don't need to filter, nor add any sessionUUID data - getData(callback); + url += 'status=' + domain.slice(1, -1); // without curly braces + } else { + url += 'filter=connections'; // regardless of whether online } + requestJSON(url, function (connectionsData) { + // The back end doesn't include the profile picture data, but we can add that here. + // For our current purposes, there's no need to be fancy and try to reduce latency by doing some number of requests in parallel, + // so these requests are all sequential. + var users = connectionsData.users; + function addPicture(index) { + if (index >= users.length) { + return callback(users); + } + var user = users[index]; + getProfilePicture(user.username, function (url) { + user.profileUrl = url; + addPicture(index + 1); + }); + } + addPicture(0); + }); } function getConnectionData(domain) { // Update all the usernames that I am entitled to see, using my login but not dependent on canKick. function frob(user) { // get into the right format return { - sessionId: user.location.sessionUUID || '', + sessionId: user.location.node_id || '', userName: user.username, connection: user.connection, profileUrl: user.profileUrl, From c795d2ca3be04f8ee4ea4ad043317fcda0307cf1 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 28 Mar 2017 18:31:08 -0700 Subject: [PATCH 3/8] Four-way discoverability. (Needs testing.) --- interface/resources/qml/hifi/Pal.qml | 14 +++----------- interface/src/DiscoverabilityManager.h | 1 + .../scripting/GlobalServicesScriptingInterface.cpp | 6 +++++- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index d5e26e22cf..3b9cbdf48c 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -162,17 +162,8 @@ Rectangle { } HifiControlsUit.TabletComboBox { function determineAvailabilityIndex() { - var globalServicesAvailability = GlobalServices.findableBy; - if (globalServicesAvailability === "all") { - return 0; - } else if (globalServicesAvailability === "friends") { - return 1; - } else if (globalServicesAvailability === "none") { - return 2; - } else { - return 1; - } - } + return ['all', 'connections', 'friends', 'none'].indexOf(GlobalServices.findableBy) + } id: availabilityComboBox; // Anchors anchors.top: parent.top; @@ -184,6 +175,7 @@ Rectangle { model: ListModel { id: availabilityComboBoxListItems ListElement { text: "Everyone"; value: "all"; } + ListElement { text: "All Connections"; value: "connections"; } ListElement { text: "Friends Only"; value: "friends"; } ListElement { text: "Appear Offline"; value: "none" } } diff --git a/interface/src/DiscoverabilityManager.h b/interface/src/DiscoverabilityManager.h index 196b0cdf81..a6c717c93f 100644 --- a/interface/src/DiscoverabilityManager.h +++ b/interface/src/DiscoverabilityManager.h @@ -19,6 +19,7 @@ namespace Discoverability { enum Mode { None, Friends, + Connections, All }; } diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index d7e5bae3f8..bde94e80fa 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -59,7 +59,9 @@ QString GlobalServicesScriptingInterface::findableByString(Discoverability::Mode return "none"; } else if (discoverabilityMode == Discoverability::Friends) { return "friends"; - } else if (discoverabilityMode == Discoverability::All) { + } else if (discoverabilityMode == Discoverability::Connections) { + return "connections"; + } else if (discoverabilityMode == Discoverability::All) { return "all"; } else { qDebug() << "GlobalServices findableByString called with an unrecognized value."; @@ -80,6 +82,8 @@ void GlobalServicesScriptingInterface::setFindableBy(const QString& discoverabil discoverabilityManager->setDiscoverabilityMode(Discoverability::None); } else if (discoverabilityMode.toLower() == "friends") { discoverabilityManager->setDiscoverabilityMode(Discoverability::Friends); + } else if (discoverabilityMode.toLower() == "connections") { + discoverabilityManager->setDiscoverabilityMode(Discoverability::Connections); } else if (discoverabilityMode.toLower() == "all") { discoverabilityManager->setDiscoverabilityMode(Discoverability::All); } else { From b0c97d3a82c3127c83b8474c785eb4684cb95af1 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 29 Mar 2017 12:22:26 -0700 Subject: [PATCH 4/8] putative connection integration for 2-machine testing --- scripts/system/makeUserConnection.js | 136 ++++++++++++++++++++++++--- 1 file changed, 121 insertions(+), 15 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index fe51345233..a2f9b8ea81 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -118,6 +118,59 @@ function debug() { print.apply(null, [].concat.apply([label, stateString, JSON.stringify(waitingList), connecting], [].map.call(arguments, JSON.stringify))); } +function cleanId(guidWithCurlyBraces) { + return guidWithCurlyBraces.slice(1, -1); +} +function request(options, callback) { // cb(error, responseOfCorrectContentType) of url. A subset of npm request. + var httpRequest = new XMLHttpRequest(), key; + // QT bug: apparently doesn't handle onload. Workaround using readyState. + httpRequest.onreadystatechange = function () { + var READY_STATE_DONE = 4; + var HTTP_OK = 200; + if (httpRequest.readyState >= READY_STATE_DONE) { + var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText, + response = !error && httpRequest.responseText, + contentType = !error && httpRequest.getResponseHeader('content-type'); + if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc. + try { + response = JSON.parse(response); + } catch (e) { + error = e; + } + } + callback(error, response); + } + }; + if (typeof options === 'string') { + options = {uri: options}; + } + if (options.url) { + options.uri = options.url; + } + if (!options.method) { + options.method = 'GET'; + } + if (options.body && (options.method === 'GET')) { // add query parameters + var params = [], appender = (-1 === options.uri.search('?')) ? '?' : '&'; + for (key in options.body) { + params.push(key + '=' + options.body[key]); + } + options.uri += appender + params.join('&'); + delete options.body; + } + if (options.json) { + options.headers = options.headers || {}; + options.headers["Content-type"] = "application/json"; + options.body = JSON.stringify(options.body); + } + debug("FIXME final options to send", options); + for (key in options.headers || {}) { + httpRequest.setRequestHeader(key, options.headers[key]); + } + httpRequest.open(options.method, options.uri, true); + httpRequest.send(options.body); +} + function handToString(hand) { if (hand === Controller.Standard.RightHand) { return "RightHand"; @@ -215,6 +268,7 @@ function deleteMakeConnectionParticleEffect() { function stopHandshakeSound() { if (handshakeInjector) { handshakeInjector.stop(); + handshakeInjector = null; } } @@ -393,9 +447,7 @@ function endHandshake() { stopWaiting(); stopConnecting(); stopMakingConnection(); - if (handshakeInjector) { - handshakeInjector.stop(); - } + stopHandshakeSound(); // send done to let connection know you are not making connections now messageSend({ key: "done" @@ -470,6 +522,63 @@ function lookForWaitingAvatar() { }, WAITING_INTERVAL); } +/* There is a mini-state machine after entering STATES.makingConnection. + We make a request (which might immediately succeed, fail, or neither. + If we immediately fail, we tell the user. + Otherwise, we wait MAKING_CONNECTION_TIMEOUT. At that time, we poll until success or fail. + */ +var result, requestBody, pollCount = 0, requestUrl = location.metaverseServerUrl + '/api/v1/user/connection_request'; +function connectionRequestCompleted() { // Final result is in. Do effects. + if (result.status === 'success') { // set earlier + if (!successfulHandshakeInjector) { + successfulHandshakeInjector = Audio.playSound(successfulHandshakeSound, {position: getHandPosition(MyAvatar, currentHand), volume: 0.5, localOnly: true}); + } else { + successfulHandshakeInjector.restart(); + } + Controller.triggerHapticPulse(HAPTIC_DATA.success.strength, HAPTIC_DATA.success.duration, handToHaptic(currentHand)); + // don't change state (so animation continues while gripped) + // but do send a notification, by calling the slot that emits the signal for it + Window.makeConnection(true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" : result.connection.username); + return; + } // failed + endHandshake(); + debug("failing with result data", result); + // IWBNI we also did some fail sound/visual effect. + Window.makeConnection(false, result.connection); +} +function handleConnectionResponseAndMaybeRepeat(error, response) { + // If response is 'pending', set a short timeout to try again. + // If we fail other than pending, set result and immediately call connectionRequestCompleted. + // If we succceed, set result and call connectionRequestCompleted immediately (if we've been polling), and otherwise on a timeout. + if (response && (response.connection === 'pending')) { + debug(response, 'pollLimit', pollLimit); + if (pollCount++ >= 5) { // server will expire, but let's not wait that long. + result = {status: 'error', connection: 'expired'}; + connectionRequestCompleted(); + } else { + Script.setTimeout(function () { + request({ + uri: requestUrl, + json: true, + body: requestBody + }, handleConnectionResponseAndMaybeRepeat); + }, 200); + } + } else if (error || (response.status !== 'success')) { + debug('server fail', error, response.status); + result = error ? {status: 'error', connection: error} : response; + connectionRequestCompleted(); + } else { + debug('server success', result); + result = response; + if (pollCount++) { + connectionRequestCompleted(); + } else { // Wait for other guy, so that final succcess is at roughly the same time. + Script.setTimeout(connectionRequestCompleted, MAKING_CONNECTION_TIMEOUT); + } + } +} + // this should be where we make the appropriate connection call. For now just make the // visualization change. function makeConnection(id) { @@ -484,18 +593,15 @@ function makeConnection(id) { // continue the haptic background until the timeout fires. When we make calls, we will have an interval // probably, in which we do this. Controller.triggerHapticPulse(HAPTIC_DATA.background.strength, MAKING_CONNECTION_TIMEOUT, handToHaptic(currentHand)); - - makingFriendsTimeout = Script.setTimeout(function () { - if (!successfulHandshakeInjector) { - successfulHandshakeInjector = Audio.playSound(successfulHandshakeSound, {position: getHandPosition(MyAvatar, currentHand), volume: 0.5, localOnly: true}); - } else { - successfulHandshakeInjector.restart(); - } - Controller.triggerHapticPulse(HAPTIC_DATA.success.strength, HAPTIC_DATA.success.duration, handToHaptic(currentHand)); - // don't change state (so animation continues while gripped) - // but do send a notification, by calling the slot that emits the signal for it - Window.makeConnection(true, "otherGuy"); // this is successful, unsucessful would be false, errorString - }, MAKING_CONNECTION_TIMEOUT); + requestBody = {node_id: cleanId(MyAvatar.sessionUUID), proposed_node_id: cleanId(id)}; // for use when repeating + // This will immediately set response if successfull (e.g., the other guy got his request in first), or immediate failure, + // and will otherwise poll (using the requestBody we just set). + request({ // + uri: requestUrl, + method: 'POST', + json: true, + body: {user_connection_request: requestbody} + }, handleConnectionResponseAndMaybeRepeat); } // we change states, start the connectionInterval where we check From 53d484c318848c6b6021c9d5200bff0393866899 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 29 Mar 2017 13:23:31 -0700 Subject: [PATCH 5/8] makes connections! --- scripts/system/makeUserConnection.js | 16 +++++++++------- scripts/system/notifications.js | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index a2f9b8ea81..1816f6b5e3 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -131,6 +131,7 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType) var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText, response = !error && httpRequest.responseText, contentType = !error && httpRequest.getResponseHeader('content-type'); + debug('FIXME REMOVE: server response', options, error, response, contentType); if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc. try { response = JSON.parse(response); @@ -163,7 +164,7 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType) options.headers["Content-type"] = "application/json"; options.body = JSON.stringify(options.body); } - debug("FIXME final options to send", options); + debug("FIXME REMOVE: final options to send", options); for (key in options.headers || {}) { httpRequest.setRequestHeader(key, options.headers[key]); } @@ -546,23 +547,24 @@ function connectionRequestCompleted() { // Final result is in. Do effects. // IWBNI we also did some fail sound/visual effect. Window.makeConnection(false, result.connection); } +var POLL_INTERVAL_MS = 200, POLL_LIMIT = 5; function handleConnectionResponseAndMaybeRepeat(error, response) { // If response is 'pending', set a short timeout to try again. // If we fail other than pending, set result and immediately call connectionRequestCompleted. // If we succceed, set result and call connectionRequestCompleted immediately (if we've been polling), and otherwise on a timeout. if (response && (response.connection === 'pending')) { - debug(response, 'pollLimit', pollLimit); - if (pollCount++ >= 5) { // server will expire, but let's not wait that long. + debug(response, 'pollCount', pollCount); + if (pollCount++ >= POLL_LIMIT) { // server will expire, but let's not wait that long. result = {status: 'error', connection: 'expired'}; connectionRequestCompleted(); - } else { + } else { // poll Script.setTimeout(function () { request({ uri: requestUrl, - json: true, + // N.B.: server gives bad request if we specify json content type, so don't do that. body: requestBody }, handleConnectionResponseAndMaybeRepeat); - }, 200); + }, POLL_INTERVAL_MS); } } else if (error || (response.status !== 'success')) { debug('server fail', error, response.status); @@ -600,7 +602,7 @@ function makeConnection(id) { uri: requestUrl, method: 'POST', json: true, - body: {user_connection_request: requestbody} + body: {user_connection_request: requestBody} }, handleConnectionResponseAndMaybeRepeat); } diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 59384114e0..cb898d489d 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -542,7 +542,7 @@ function processingGif() { } function connectionAdded(connectionName) { - createNotification(wordWrap("Successfully connected to " + connectionName), NotificationType.CONNECTION); + createNotification(connectionName, NotificationType.CONNECTION); } function connectionError(error) { From 3a7edebb948e2e68f1acbb16cc509b6f5ce840a9 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 29 Mar 2017 16:12:50 -0700 Subject: [PATCH 6/8] Adjust reporting of availability to metaverse. --- interface/src/DiscoverabilityManager.cpp | 22 ++++++++++++++++--- interface/src/DiscoverabilityManager.h | 3 +++ .../GlobalServicesScriptingInterface.cpp | 22 ++----------------- .../GlobalServicesScriptingInterface.h | 2 -- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index ff30bd1585..31ab8d9a29 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -77,8 +77,8 @@ void DiscoverabilityManager::updateLocation() { const QString NETWORK_ADDRESS_PORT_IN_LOCATION = "network_port"; locationObject.insert(NETWORK_ADDRESS_PORT_IN_LOCATION, domainSockAddr.getPort()); - const QString FRIENDS_ONLY_KEY_IN_LOCATION = "friends_only"; - locationObject.insert(FRIENDS_ONLY_KEY_IN_LOCATION, (_mode.get() == Discoverability::Friends)); + const QString AVAILABILITY_KEY_IN_LOCATION = "availability"; + locationObject.insert(AVAILABILITY_KEY_IN_LOCATION, findableByString(static_cast(_mode.get()))); JSONCallbackParameters callbackParameters; callbackParameters.jsonCallbackReceiver = this; @@ -140,13 +140,29 @@ void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discov // update the setting to the new value _mode.set(static_cast(discoverabilityMode)); - updateLocation(); // update right away emit discoverabilityModeChanged(discoverabilityMode); } } + +QString DiscoverabilityManager::findableByString(Discoverability::Mode discoverabilityMode) { + if (discoverabilityMode == Discoverability::None) { + return "none"; + } else if (discoverabilityMode == Discoverability::Friends) { + return "friends"; + } else if (discoverabilityMode == Discoverability::Connections) { + return "connections"; + } else if (discoverabilityMode == Discoverability::All) { + return "all"; + } else { + qDebug() << "GlobalServices findableByString called with an unrecognized value."; + return ""; + } +} + + void DiscoverabilityManager::setVisibility() { Menu* menu = Menu::getInstance(); diff --git a/interface/src/DiscoverabilityManager.h b/interface/src/DiscoverabilityManager.h index a6c717c93f..96190b25d9 100644 --- a/interface/src/DiscoverabilityManager.h +++ b/interface/src/DiscoverabilityManager.h @@ -43,6 +43,9 @@ public slots: signals: void discoverabilityModeChanged(Discoverability::Mode discoverabilityMode); +public: + static QString findableByString(Discoverability::Mode discoverabilityMode); + private slots: void handleHeartbeatResponse(QNetworkReply& requestReply); diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index bde94e80fa..f4a5ffb39c 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -53,31 +53,13 @@ void GlobalServicesScriptingInterface::loggedOut() { emit GlobalServicesScriptingInterface::disconnected(QString("logout")); } - -QString GlobalServicesScriptingInterface::findableByString(Discoverability::Mode discoverabilityMode) const { - if (discoverabilityMode == Discoverability::None) { - return "none"; - } else if (discoverabilityMode == Discoverability::Friends) { - return "friends"; - } else if (discoverabilityMode == Discoverability::Connections) { - return "connections"; - } else if (discoverabilityMode == Discoverability::All) { - return "all"; - } else { - qDebug() << "GlobalServices findableByString called with an unrecognized value."; - return ""; - } -} - - QString GlobalServicesScriptingInterface::getFindableBy() const { auto discoverabilityManager = DependencyManager::get(); - return findableByString(discoverabilityManager->getDiscoverabilityMode()); + return DiscoverabilityManager::findableByString(discoverabilityManager->getDiscoverabilityMode()); } void GlobalServicesScriptingInterface::setFindableBy(const QString& discoverabilityMode) { auto discoverabilityManager = DependencyManager::get(); - if (discoverabilityMode.toLower() == "none") { discoverabilityManager->setDiscoverabilityMode(Discoverability::None); } else if (discoverabilityMode.toLower() == "friends") { @@ -92,7 +74,7 @@ void GlobalServicesScriptingInterface::setFindableBy(const QString& discoverabil } void GlobalServicesScriptingInterface::discoverabilityModeChanged(Discoverability::Mode discoverabilityMode) { - emit findableByChanged(findableByString(discoverabilityMode)); + emit findableByChanged(DiscoverabilityManager::findableByString(discoverabilityMode)); } DownloadInfoResult::DownloadInfoResult() : diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index 8d8b78e149..63294fc656 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -66,8 +66,6 @@ private: GlobalServicesScriptingInterface(); ~GlobalServicesScriptingInterface(); - QString findableByString(Discoverability::Mode discoverabilityMode) const; - bool _downloading; }; From af25e0e21fbd5a8617487019c726da39417fe962 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 29 Mar 2017 17:55:57 -0700 Subject: [PATCH 7/8] Don't consider changes to location details as update-worthy if we're not discoverable. --- interface/src/DiscoverabilityManager.cpp | 44 +++++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 31ab8d9a29..79a9a34102 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -51,32 +51,34 @@ void DiscoverabilityManager::updateLocation() { QString pathString = addressManager->currentPath(); - const QString PATH_KEY_IN_LOCATION = "path"; - locationObject.insert(PATH_KEY_IN_LOCATION, pathString); - const QString CONNECTED_KEY_IN_LOCATION = "connected"; locationObject.insert(CONNECTED_KEY_IN_LOCATION, discoverable && domainHandler.isConnected()); - if (!addressManager->getRootPlaceID().isNull()) { - const QString PLACE_ID_KEY_IN_LOCATION = "place_id"; - locationObject.insert(PLACE_ID_KEY_IN_LOCATION, - uuidStringWithoutCurlyBraces(addressManager->getRootPlaceID())); + if (discoverable) { // Don't consider changes to these as update-worthy if we're not discoverable. + const QString PATH_KEY_IN_LOCATION = "path"; + locationObject.insert(PATH_KEY_IN_LOCATION, pathString); + + if (!addressManager->getRootPlaceID().isNull()) { + const QString PLACE_ID_KEY_IN_LOCATION = "place_id"; + locationObject.insert(PLACE_ID_KEY_IN_LOCATION, + uuidStringWithoutCurlyBraces(addressManager->getRootPlaceID())); + } + + if (!domainHandler.getUUID().isNull()) { + const QString DOMAIN_ID_KEY_IN_LOCATION = "domain_id"; + locationObject.insert(DOMAIN_ID_KEY_IN_LOCATION, + uuidStringWithoutCurlyBraces(domainHandler.getUUID())); + } + + // in case the place/domain isn't in the database, we send the network address and port + auto& domainSockAddr = domainHandler.getSockAddr(); + const QString NETWORK_ADRESS_KEY_IN_LOCATION = "network_address"; + locationObject.insert(NETWORK_ADRESS_KEY_IN_LOCATION, domainSockAddr.getAddress().toString()); + + const QString NETWORK_ADDRESS_PORT_IN_LOCATION = "network_port"; + locationObject.insert(NETWORK_ADDRESS_PORT_IN_LOCATION, domainSockAddr.getPort()); } - if (!domainHandler.getUUID().isNull()) { - const QString DOMAIN_ID_KEY_IN_LOCATION = "domain_id"; - locationObject.insert(DOMAIN_ID_KEY_IN_LOCATION, - uuidStringWithoutCurlyBraces(domainHandler.getUUID())); - } - - // in case the place/domain isn't in the database, we send the network address and port - auto& domainSockAddr = domainHandler.getSockAddr(); - const QString NETWORK_ADRESS_KEY_IN_LOCATION = "network_address"; - locationObject.insert(NETWORK_ADRESS_KEY_IN_LOCATION, domainSockAddr.getAddress().toString()); - - const QString NETWORK_ADDRESS_PORT_IN_LOCATION = "network_port"; - locationObject.insert(NETWORK_ADDRESS_PORT_IN_LOCATION, domainSockAddr.getPort()); - const QString AVAILABILITY_KEY_IN_LOCATION = "availability"; locationObject.insert(AVAILABILITY_KEY_IN_LOCATION, findableByString(static_cast(_mode.get()))); From 3056bb16a21a3b0b6ef325f5b5892ed393fbfdf5 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 30 Mar 2017 12:40:54 -0700 Subject: [PATCH 8/8] typo, and delete request on abort/fail --- interface/src/DiscoverabilityManager.cpp | 4 ++-- scripts/system/makeUserConnection.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 79a9a34102..d0a706f2a4 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -72,8 +72,8 @@ void DiscoverabilityManager::updateLocation() { // in case the place/domain isn't in the database, we send the network address and port auto& domainSockAddr = domainHandler.getSockAddr(); - const QString NETWORK_ADRESS_KEY_IN_LOCATION = "network_address"; - locationObject.insert(NETWORK_ADRESS_KEY_IN_LOCATION, domainSockAddr.getAddress().toString()); + const QString NETWORK_ADDRESS_KEY_IN_LOCATION = "network_address"; + locationObject.insert(NETWORK_ADDRESS_KEY_IN_LOCATION, domainSockAddr.getAddress().toString()); const QString NETWORK_ADDRESS_PORT_IN_LOCATION = "network_port"; locationObject.insert(NETWORK_ADDRESS_PORT_IN_LOCATION, domainSockAddr.getPort()); diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index 1816f6b5e3..4d8fe6cb8f 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -458,6 +458,8 @@ function endHandshake() { debug("removing animation"); MyAvatar.removeAnimationStateHandler(animHandlerId); } + // No-op if we were successful, but this way we ensure that failures and abandoned handshakes don't leave us in a weird state. + request({uri: requestUrl, method: 'DELETE'}, debug); } function updateTriggers(value, fromKeyboard, hand) {