mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:58:27 +02:00
Merge pull request #4847 from birarda/domain-paths
add initial support for local paths in domain
This commit is contained in:
commit
349886c146
20 changed files with 1169 additions and 818 deletions
|
@ -1,7 +1,7 @@
|
|||
[
|
||||
{
|
||||
"name": "metaverse",
|
||||
"label": "Metaverse Registration",
|
||||
"label": "Metaverse / Networking",
|
||||
"settings": [
|
||||
{
|
||||
"name": "access_token",
|
||||
|
@ -44,6 +44,29 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Paths",
|
||||
"settings": [
|
||||
{
|
||||
"name": "paths",
|
||||
"label": "",
|
||||
"help": "Clients can enter a path to reach an exact viewpoint in your domain.<br/>Add rows to the table below to map a path to a viewpoint.<br/>The index path ( / ) is where clients will enter if they do not enter an explicit path.",
|
||||
"type": "table",
|
||||
"key": {
|
||||
"name": "path",
|
||||
"label": "Path",
|
||||
"placeholder": "/"
|
||||
},
|
||||
"columns": [
|
||||
{
|
||||
"name": "viewpoint",
|
||||
"label": "Viewpoint",
|
||||
"placeholder": "/512,512,512"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "security",
|
||||
"label": "Security",
|
||||
|
|
|
@ -21,34 +21,34 @@ var Settings = {
|
|||
};
|
||||
|
||||
var viewHelpers = {
|
||||
getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) {
|
||||
setting_name = groupName + "." + setting.name
|
||||
getFormGroup: function(keypath, setting, values, isAdvanced, isLocked) {
|
||||
form_group = "<div class='form-group " + (isAdvanced ? Settings.ADVANCED_CLASS : "") + "'>";
|
||||
|
||||
form_group = "<div class='form-group " + (isAdvanced ? Settings.ADVANCED_CLASS : "") + "'>"
|
||||
setting_value = _(values).valueForKeyPath(keypath);
|
||||
|
||||
if (_.has(values, groupName) && _.has(values[groupName], setting.name)) {
|
||||
setting_value = values[groupName][setting.name]
|
||||
} else if (_.has(setting, 'default')) {
|
||||
setting_value = setting.default
|
||||
if (!setting_value) {
|
||||
if (_.has(setting, 'default')) {
|
||||
setting_value = setting.default;
|
||||
} else {
|
||||
setting_value = ""
|
||||
setting_value = "";
|
||||
}
|
||||
}
|
||||
|
||||
label_class = 'control-label'
|
||||
label_class = 'control-label';
|
||||
if (isLocked) {
|
||||
label_class += ' locked'
|
||||
label_class += ' locked';
|
||||
}
|
||||
|
||||
common_attrs = " class='" + (setting.type !== 'checkbox' ? 'form-control' : '')
|
||||
+ " " + Settings.TRIGGER_CHANGE_CLASS + "' data-short-name='" + setting.name + "' name='" + setting_name + "' "
|
||||
+ "id='" + setting_name + "'"
|
||||
+ " " + Settings.TRIGGER_CHANGE_CLASS + "' data-short-name='" + setting.name + "' name='" + keypath + "' "
|
||||
+ "id='" + keypath + "'";
|
||||
|
||||
if (setting.type === 'checkbox') {
|
||||
if (setting.label) {
|
||||
form_group += "<label class='" + label_class + "'>" + setting.label + "</label>"
|
||||
}
|
||||
form_group += "<div class='checkbox" + (isLocked ? " disabled" : "") + "'>"
|
||||
form_group += "<label for='" + setting_name + "'>"
|
||||
form_group += "<label for='" + keypath + "'>"
|
||||
form_group += "<input type='checkbox'" + common_attrs + (setting_value ? "checked" : "") + (isLocked ? " disabled" : "") + "/>"
|
||||
form_group += " " + setting.help + "</label>";
|
||||
form_group += "</div>"
|
||||
|
@ -56,14 +56,14 @@ var viewHelpers = {
|
|||
input_type = _.has(setting, 'type') ? setting.type : "text"
|
||||
|
||||
if (setting.label) {
|
||||
form_group += "<label for='" + setting_name + "' class='" + label_class + "'>" + setting.label + "</label>";
|
||||
form_group += "<label for='" + keypath + "' class='" + label_class + "'>" + setting.label + "</label>";
|
||||
}
|
||||
|
||||
if (input_type === 'table') {
|
||||
form_group += makeTable(setting, setting_name, setting_value, isLocked)
|
||||
form_group += makeTable(setting, keypath, setting_value, isLocked)
|
||||
} else {
|
||||
if (input_type === 'select') {
|
||||
form_group += "<select class='form-control' data-hidden-input='" + setting_name + "'>'"
|
||||
form_group += "<select class='form-control' data-hidden-input='" + keypath + "'>'"
|
||||
|
||||
_.each(setting.options, function(option) {
|
||||
form_group += "<option value='" + option.value + "'" +
|
||||
|
@ -186,7 +186,7 @@ $(document).ready(function(){
|
|||
|
||||
// $('body').scrollspy({ target: '#setup-sidebar'})
|
||||
|
||||
reloadSettings()
|
||||
reloadSettings();
|
||||
})
|
||||
|
||||
function reloadSettings() {
|
||||
|
@ -258,16 +258,21 @@ $('body').on('click', '.save-button', function(e){
|
|||
return false;
|
||||
});
|
||||
|
||||
function makeTable(setting, setting_name, setting_value, isLocked) {
|
||||
function makeTable(setting, keypath, setting_value, isLocked) {
|
||||
var isArray = !_.has(setting, 'key')
|
||||
|
||||
if (!isArray && setting.can_order) {
|
||||
setting.can_order = false;
|
||||
}
|
||||
|
||||
var html = "<span class='help-block'>" + setting.help + "</span>"
|
||||
html += "<table class='table table-bordered " + (isLocked ? "locked-table" : "") + "' data-short-name='" + setting.name + "' name='" + setting_name
|
||||
+ "' data-setting-type='" + (isArray ? 'array' : 'hash') + "'>"
|
||||
var html = "";
|
||||
|
||||
if (setting.help) {
|
||||
html += "<span class='help-block'>" + setting.help + "</span>"
|
||||
}
|
||||
|
||||
html += "<table class='table table-bordered " + (isLocked ? "locked-table" : "") + "' data-short-name='" + setting.name
|
||||
+ "' name='" + keypath + "' data-setting-type='" + (isArray ? 'array' : 'hash') + "'>"
|
||||
|
||||
// Column names
|
||||
html += "<tr class='headers'>"
|
||||
|
@ -296,7 +301,7 @@ function makeTable(setting, setting_name, setting_value, isLocked) {
|
|||
var row_num = 1
|
||||
|
||||
_.each(setting_value, function(row, indexOrName) {
|
||||
html += "<tr class='" + Settings.DATA_ROW_CLASS + "'" + (isArray ? "" : "name='" + setting_name + "." + indexOrName + "'") + ">"
|
||||
html += "<tr class='" + Settings.DATA_ROW_CLASS + "'" + (isArray ? "" : "name='" + keypath + "." + indexOrName + "'") + ">"
|
||||
|
||||
if (setting.numbered === true) {
|
||||
html += "<td class='numbered'>" + row_num + "</td>"
|
||||
|
@ -315,7 +320,7 @@ function makeTable(setting, setting_name, setting_value, isLocked) {
|
|||
html += colValue
|
||||
|
||||
// for arrays we add a hidden input to this td so that values can be posted appropriately
|
||||
html += "<input type='hidden' name='" + setting_name + "[" + indexOrName + "]"
|
||||
html += "<input type='hidden' name='" + keypath + "[" + indexOrName + "]"
|
||||
+ (rowIsObject ? "." + col.name : "") + "' value='" + colValue + "'/>"
|
||||
} else if (row.hasOwnProperty(col.name)) {
|
||||
html += row[col.name]
|
||||
|
@ -382,9 +387,20 @@ function badgeSidebarForDifferences(changedElement) {
|
|||
// figure out which group this input is in
|
||||
var panelParentID = changedElement.closest('.panel').attr('id')
|
||||
|
||||
// if the panel contains non-grouped settings, the initial value is Settings.initialValues
|
||||
var isGrouped = $(panelParentID).hasClass('grouped');
|
||||
|
||||
if (isGrouped) {
|
||||
var initialPanelJSON = Settings.initialValues[panelParentID];
|
||||
|
||||
// get a JSON representation of that section
|
||||
var panelJSON = form2js(panelParentID, ".", false, cleanupFormValues, true)[panelParentID]
|
||||
var initialPanelJSON = Settings.initialValues[panelParentID]
|
||||
var panelJSON = form2js(panelParentID, ".", false, cleanupFormValues, true)[panelParentID];
|
||||
} else {
|
||||
var initialPanelJSON = Settings.initialValues;
|
||||
|
||||
// get a JSON representation of that section
|
||||
var panelJSON = form2js(panelParentID, ".", false, cleanupFormValues, true);
|
||||
}
|
||||
|
||||
var badgeValue = 0
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
<div id="setup-sidebar" data-clampedwidth="#setup-sidebar-col" class="hidden-xs" data-spy="affix" data-offset-top="55">
|
||||
<script id="list-group-template" type="text/template">
|
||||
<% _.each(descriptions, function(group){ %>
|
||||
<% panelID = group.name ? group.name : group.label %>
|
||||
<li>
|
||||
<a href="#<%-group.name %>" class="list-group-item">
|
||||
<a href="#<%- panelID %>" class="list-group-item">
|
||||
<span class="badge"></span>
|
||||
<%- group.label %>
|
||||
</a>
|
||||
|
@ -37,24 +38,32 @@
|
|||
<% if (isAdvanced) { %>
|
||||
<% $("a[href=#" + group.name + "]").addClass('advanced-setting').hide() %>
|
||||
<% } %>
|
||||
<div class="panel panel-default <%- (isAdvanced) ? 'advanced-setting' : '' %>" id="<%- group.name %>">
|
||||
|
||||
<% isGrouped = !!group.name %>
|
||||
<% panelID = isGrouped ? group.name : group.label %>
|
||||
|
||||
<div class="panel panel-default<%- (isAdvanced) ? ' advanced-setting' : '' %><%- (isGrouped) ? ' grouped' : '' %>"
|
||||
id="<%- panelID %>">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"><%- group.label %></h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<% _.each(split_settings[0], function(setting) { %>
|
||||
<%= getFormGroup(group.name, setting, values, false,
|
||||
<% keypath = isGrouped ? group.name + "." + setting.name : setting.name %>
|
||||
<%= getFormGroup(keypath, setting, values, false,
|
||||
(_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %>
|
||||
<% }); %>
|
||||
<% if (!_.isEmpty(split_settings[1])) { %>
|
||||
<% $("#advanced-toggle-button").show() %>
|
||||
<% _.each(split_settings[1], function(setting) { %>
|
||||
<%= getFormGroup(group.name, setting, values, true,
|
||||
<% keypath = isGrouped ? group.name + "." + setting.name : setting.name %>
|
||||
<%= getFormGroup(keypath, setting, values, true,
|
||||
(_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %>
|
||||
<% }); %>
|
||||
<% }%>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% }); %>
|
||||
</script>
|
||||
|
||||
|
@ -83,6 +92,7 @@
|
|||
|
||||
<!--#include virtual="footer.html"-->
|
||||
<script src='/js/underscore-min.js'></script>
|
||||
<script src='/js/underscore-keypath.min.js'></script>
|
||||
<script src='/js/bootbox.min.js'></script>
|
||||
<script src='/js/sweet-alert.min.js'></script>
|
||||
<script src='/js/settings.js'></script>
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
<script src='js/json.human.js'></script>
|
||||
<script src='js/highcharts-custom.js'></script>
|
||||
<script src='/js/underscore-min.js'></script>
|
||||
<script src='js/underscore-keypath.min.js'></script>
|
||||
<script src='/js/underscore-keypath.min.js'></script>
|
||||
<script src='/js/bootbox.min.js'></script>
|
||||
<!--#include virtual="page-end.html"-->
|
||||
|
|
|
@ -1399,6 +1399,11 @@ void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiS
|
|||
|
||||
break;
|
||||
}
|
||||
case PacketTypeDomainServerPathQuery: {
|
||||
// have our private method attempt to respond to this path query
|
||||
respondToPathQuery(receivedPacket, senderSockAddr);
|
||||
break;
|
||||
}
|
||||
case PacketTypeNodeJsonStats: {
|
||||
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
|
||||
if (matchingNode) {
|
||||
|
@ -2191,3 +2196,75 @@ void DomainServer::addStaticAssignmentsToQueue() {
|
|||
++staticAssignment;
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::respondToPathQuery(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) {
|
||||
// this is a query for the viewpoint resulting from a path
|
||||
// first pull the query path from the packet
|
||||
|
||||
int numHeaderBytes = numBytesForPacketHeaderGivenPacketType(PacketTypeDomainServerPathQuery);
|
||||
const char* packetDataStart = receivedPacket.data() + numHeaderBytes;
|
||||
|
||||
// figure out how many bytes the sender said this path is
|
||||
quint16 numPathBytes = *packetDataStart;
|
||||
|
||||
if (numPathBytes <= receivedPacket.size() - numHeaderBytes - sizeof(numPathBytes)) {
|
||||
// the number of path bytes makes sense for the sent packet - pull out the path
|
||||
QString pathQuery = QString::fromUtf8(packetDataStart + sizeof(numPathBytes), numPathBytes);
|
||||
|
||||
// our settings contain paths that start with a leading slash, so make sure this query has that
|
||||
if (!pathQuery.startsWith("/")) {
|
||||
pathQuery.prepend("/");
|
||||
}
|
||||
|
||||
const QString PATHS_SETTINGS_KEYPATH_FORMAT = "%1.%2";
|
||||
const QString PATH_VIEWPOINT_KEY = "viewpoint";
|
||||
|
||||
// check out paths in the _configMap to see if we have a match
|
||||
const QVariant* pathMatch = valueForKeyPath(_settingsManager.getSettingsMap(),
|
||||
QString(PATHS_SETTINGS_KEYPATH_FORMAT).arg(SETTINGS_PATHS_KEY)
|
||||
.arg(pathQuery));
|
||||
if (pathMatch) {
|
||||
// we got a match, respond with the resulting viewpoint
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
QString responseViewpoint = pathMatch->toMap()[PATH_VIEWPOINT_KEY].toString();
|
||||
|
||||
if (!responseViewpoint.isEmpty()) {
|
||||
QByteArray viewpointUTF8 = responseViewpoint.toUtf8();
|
||||
|
||||
// prepare a packet for the response
|
||||
QByteArray pathResponsePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeDomainServerPathResponse);
|
||||
|
||||
// check the number of bytes the viewpoint is
|
||||
quint16 numViewpointBytes = responseViewpoint.toUtf8().size();
|
||||
|
||||
// are we going to be able to fit this response viewpoint in a packet?
|
||||
if (numPathBytes + numViewpointBytes + pathResponsePacket.size() + sizeof(numViewpointBytes)
|
||||
< MAX_PACKET_SIZE) {
|
||||
// append the number of bytes this path is
|
||||
pathResponsePacket.append(reinterpret_cast<char*>(&numPathBytes), sizeof(numPathBytes));
|
||||
|
||||
// append the path itself
|
||||
pathResponsePacket.append(pathQuery.toUtf8());
|
||||
|
||||
// append the number of bytes the resulting viewpoint is
|
||||
pathResponsePacket.append(reinterpret_cast<char*>(&numViewpointBytes), sizeof(numViewpointBytes));
|
||||
|
||||
// append the viewpoint itself
|
||||
pathResponsePacket.append(viewpointUTF8);
|
||||
|
||||
qDebug() << "Sending a viewpoint response for path query" << pathQuery << "-" << viewpointUTF8;
|
||||
|
||||
// send off the packet - see if we can associate this outbound data to a particular node
|
||||
// TODO: does this senderSockAddr always work for a punched DS client?
|
||||
nodeList->writeUnverifiedDatagram(pathResponsePacket, senderSockAddr);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// we don't respond if there is no match - this may need to change once this packet
|
||||
// query/response is made reliable
|
||||
qDebug() << "No match for path query" << pathQuery << "- refusing to respond.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,8 @@ private:
|
|||
void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment);
|
||||
void addStaticAssignmentsToQueue();
|
||||
|
||||
void respondToPathQuery(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr);
|
||||
|
||||
QUrl oauthRedirectURL();
|
||||
QUrl oauthAuthorizationURL(const QUuid& stateUUID = QUuid::createUuid());
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ const QString DESCRIPTION_NAME_KEY = "name";
|
|||
const QString SETTING_DESCRIPTION_TYPE_KEY = "type";
|
||||
const QString DESCRIPTION_COLUMNS_KEY = "columns";
|
||||
|
||||
const QString SETTINGS_VIEWPOINT_KEY = "viewpoint";
|
||||
|
||||
DomainServerSettingsManager::DomainServerSettingsManager() :
|
||||
_descriptionArray(),
|
||||
_configMap()
|
||||
|
@ -130,10 +132,10 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
|
|||
QJsonDocument postedDocument = QJsonDocument::fromJson(connection->requestContent());
|
||||
QJsonObject postedObject = postedDocument.object();
|
||||
|
||||
qDebug() << "The postedObject is" << postedObject;
|
||||
qDebug() << "DomainServerSettingsManager postedObject -" << postedObject;
|
||||
|
||||
// we recurse one level deep below each group for the appropriate setting
|
||||
recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig(), _descriptionArray);
|
||||
recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig());
|
||||
|
||||
// store whatever the current _settingsMap is to file
|
||||
persistToFile();
|
||||
|
@ -201,31 +203,45 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
|||
|
||||
// we need to check if the settings map has a value for this setting
|
||||
QVariant variantValue;
|
||||
QVariant settingsMapGroupValue = _configMap.getMergedConfig()
|
||||
.value(groupObject[DESCRIPTION_NAME_KEY].toString());
|
||||
|
||||
if (!groupKey.isEmpty()) {
|
||||
QVariant settingsMapGroupValue = _configMap.getMergedConfig().value(groupKey);
|
||||
|
||||
if (!settingsMapGroupValue.isNull()) {
|
||||
variantValue = settingsMapGroupValue.toMap().value(settingName);
|
||||
}
|
||||
} else {
|
||||
variantValue = _configMap.getMergedConfig().value(settingName);
|
||||
}
|
||||
|
||||
QJsonValue result;
|
||||
|
||||
if (variantValue.isNull()) {
|
||||
// no value for this setting, pass the default
|
||||
if (settingObject.contains(SETTING_DEFAULT_KEY)) {
|
||||
groupResponseObject[settingName] = settingObject[SETTING_DEFAULT_KEY];
|
||||
result = settingObject[SETTING_DEFAULT_KEY];
|
||||
} else {
|
||||
// users are allowed not to provide a default for string values
|
||||
// if so we set to the empty string
|
||||
groupResponseObject[settingName] = QString("");
|
||||
result = QString("");
|
||||
}
|
||||
|
||||
} else {
|
||||
groupResponseObject[settingName] = QJsonValue::fromVariant(variantValue);
|
||||
result = QJsonValue::fromVariant(variantValue);
|
||||
}
|
||||
|
||||
if (!groupKey.isEmpty()) {
|
||||
// this belongs in the group object
|
||||
groupResponseObject[settingName] = result;
|
||||
} else {
|
||||
// this is a value that should be at the root
|
||||
responseObject[settingName] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!groupResponseObject.isEmpty()) {
|
||||
if (!groupKey.isEmpty() && !groupResponseObject.isEmpty()) {
|
||||
// set this group's object to the constructed object
|
||||
responseObject[groupKey] = groupResponseObject;
|
||||
}
|
||||
|
@ -236,25 +252,6 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
|||
return responseObject;
|
||||
}
|
||||
|
||||
bool DomainServerSettingsManager::settingExists(const QString& groupName, const QString& settingName,
|
||||
const QJsonArray& descriptionArray, QJsonObject& settingDescription) {
|
||||
foreach(const QJsonValue& groupValue, descriptionArray) {
|
||||
QJsonObject groupObject = groupValue.toObject();
|
||||
if (groupObject[DESCRIPTION_NAME_KEY].toString() == groupName) {
|
||||
|
||||
foreach(const QJsonValue& settingValue, groupObject[DESCRIPTION_SETTINGS_KEY].toArray()) {
|
||||
QJsonObject settingObject = settingValue.toObject();
|
||||
if (settingObject[DESCRIPTION_NAME_KEY].toString() == settingName) {
|
||||
settingDescription = settingObject;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settingDescription = QJsonObject();
|
||||
return false;
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
|
||||
const QJsonObject& settingDescription) {
|
||||
if (newValue.isString()) {
|
||||
|
@ -272,7 +269,15 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
|||
} else if (settingType == INPUT_INTEGER_TYPE) {
|
||||
settingMap[key] = newValue.toString().toInt();
|
||||
} else {
|
||||
settingMap[key] = newValue.toString();
|
||||
QString sanitizedValue = newValue.toString();
|
||||
|
||||
// we perform special handling for viewpoints here
|
||||
// we do not want them to be prepended with a slash
|
||||
if (key == SETTINGS_VIEWPOINT_KEY && !sanitizedValue.startsWith('/')) {
|
||||
sanitizedValue.prepend('/');
|
||||
}
|
||||
|
||||
settingMap[key] = sanitizedValue;
|
||||
}
|
||||
}
|
||||
} else if (newValue.isBool()) {
|
||||
|
@ -302,7 +307,15 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
|||
}
|
||||
}
|
||||
|
||||
updateSetting(childKey, newValue.toObject()[childKey], thisMap, childDescriptionObject);
|
||||
QString sanitizedKey = childKey;
|
||||
|
||||
if (key == SETTINGS_PATHS_KEY && !sanitizedKey.startsWith('/')) {
|
||||
// We perform special handling for paths here.
|
||||
// If we got sent a path without a leading slash then we add it.
|
||||
sanitizedKey.prepend("/");
|
||||
}
|
||||
|
||||
updateSetting(sanitizedKey, newValue.toObject()[childKey], thisMap, childDescriptionObject);
|
||||
}
|
||||
|
||||
if (settingMap[key].toMap().isEmpty()) {
|
||||
|
@ -316,32 +329,89 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
|||
}
|
||||
}
|
||||
|
||||
QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJsonObject& groupObject, const QString& settingName) {
|
||||
foreach(const QJsonValue& settingValue, groupObject[DESCRIPTION_SETTINGS_KEY].toArray()) {
|
||||
QJsonObject settingObject = settingValue.toObject();
|
||||
if (settingObject[DESCRIPTION_NAME_KEY].toString() == settingName) {
|
||||
return settingObject;
|
||||
}
|
||||
}
|
||||
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject,
|
||||
QVariantMap& settingsVariant,
|
||||
const QJsonArray& descriptionArray) {
|
||||
QVariantMap& settingsVariant) {
|
||||
// Iterate on the setting groups
|
||||
foreach(const QString& groupKey, postedObject.keys()) {
|
||||
QJsonValue groupValue = postedObject[groupKey];
|
||||
foreach(const QString& rootKey, postedObject.keys()) {
|
||||
QJsonValue rootValue = postedObject[rootKey];
|
||||
|
||||
if (!settingsVariant.contains(groupKey)) {
|
||||
if (!settingsVariant.contains(rootKey)) {
|
||||
// we don't have a map below this key yet, so set it up now
|
||||
settingsVariant[groupKey] = QVariantMap();
|
||||
settingsVariant[rootKey] = QVariantMap();
|
||||
}
|
||||
|
||||
// Iterate on the settings
|
||||
foreach(const QString& settingKey, groupValue.toObject().keys()) {
|
||||
QJsonValue settingValue = groupValue.toObject()[settingKey];
|
||||
QVariantMap& thisMap = settingsVariant;
|
||||
|
||||
QJsonObject thisDescription;
|
||||
if (settingExists(groupKey, settingKey, descriptionArray, thisDescription)) {
|
||||
QVariantMap& thisMap = *reinterpret_cast<QVariantMap*>(settingsVariant[groupKey].data());
|
||||
updateSetting(settingKey, settingValue, thisMap, thisDescription);
|
||||
QJsonObject groupDescriptionObject;
|
||||
|
||||
// we need to check the description array to see if this is a root setting or a group setting
|
||||
foreach(const QJsonValue& groupValue, _descriptionArray) {
|
||||
if (groupValue.toObject()[DESCRIPTION_NAME_KEY] == rootKey) {
|
||||
// we matched a group - keep this since we'll use it below to update the settings
|
||||
groupDescriptionObject = groupValue.toObject();
|
||||
|
||||
// change the map we will update to be the map for this group
|
||||
thisMap = *reinterpret_cast<QVariantMap*>(settingsVariant[rootKey].data());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsVariant[groupKey].toMap().empty()) {
|
||||
if (groupDescriptionObject.isEmpty()) {
|
||||
// this is a root value, so we can call updateSetting for it directly
|
||||
// first we need to find our description value for it
|
||||
|
||||
QJsonObject matchingDescriptionObject;
|
||||
|
||||
foreach(const QJsonValue& groupValue, _descriptionArray) {
|
||||
// find groups with root values (they don't have a group name)
|
||||
QJsonObject groupObject = groupValue.toObject();
|
||||
if (!groupObject.contains(DESCRIPTION_NAME_KEY)) {
|
||||
// this is a group with root values - check if our setting is in here
|
||||
matchingDescriptionObject = settingDescriptionFromGroup(groupObject, rootKey);
|
||||
|
||||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
updateSetting(rootKey, rootValue, thisMap, matchingDescriptionObject);
|
||||
} else {
|
||||
qDebug() << "Setting for root key" << rootKey << "does not exist - cannot update setting.";
|
||||
}
|
||||
} else {
|
||||
// this is a group - iterate on the settings in the group
|
||||
foreach(const QString& settingKey, rootValue.toObject().keys()) {
|
||||
// make sure this particular setting exists and we have a description object for it
|
||||
QJsonObject matchingDescriptionObject = settingDescriptionFromGroup(groupDescriptionObject, settingKey);
|
||||
|
||||
// if we matched the setting then update the value
|
||||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
QJsonValue settingValue = rootValue.toObject()[settingKey];
|
||||
updateSetting(settingKey, settingValue, thisMap, matchingDescriptionObject);
|
||||
} else {
|
||||
qDebug() << "Could not find description for setting" << settingKey << "in group" << rootKey <<
|
||||
"- cannot update setting.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsVariant[rootKey].toMap().empty()) {
|
||||
// we've cleared all of the settings below this value, so remove this one too
|
||||
settingsVariant.remove(groupKey);
|
||||
settingsVariant.remove(rootKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <HifiConfigVariantMap.h>
|
||||
#include <HTTPManager.h>
|
||||
|
||||
const QString SETTINGS_PATHS_KEY = "paths";
|
||||
|
||||
class DomainServerSettingsManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -31,12 +33,11 @@ public:
|
|||
QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); }
|
||||
private:
|
||||
QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false);
|
||||
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant,
|
||||
const QJsonArray& descriptionArray);
|
||||
bool settingExists(const QString& groupName, const QString& settingName,
|
||||
const QJsonArray& descriptionArray, QJsonObject& settingDescription);
|
||||
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant);
|
||||
|
||||
void updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
|
||||
const QJsonObject& settingDescription);
|
||||
QJsonObject settingDescriptionFromGroup(const QJsonObject& groupObject, const QString& settingName);
|
||||
void persistToFile();
|
||||
|
||||
QJsonArray _descriptionArray;
|
||||
|
|
|
@ -120,12 +120,11 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
|
|||
if (handleNetworkAddress(lookupUrl.host()
|
||||
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) {
|
||||
// we may have a path that defines a relative viewpoint - if so we should jump to that now
|
||||
handleRelativeViewpoint(lookupUrl.path());
|
||||
handlePath(lookupUrl.path());
|
||||
} else {
|
||||
// wasn't an address - lookup the place name
|
||||
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
|
||||
attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +133,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
|
|||
qCDebug(networking) << "Going to relative path" << lookupUrl.path();
|
||||
|
||||
// if this is a relative path then handle it as a relative viewpoint
|
||||
handleRelativeViewpoint(lookupUrl.path());
|
||||
handlePath(lookupUrl.path());
|
||||
emit lookupResultsFinished();
|
||||
}
|
||||
|
||||
|
@ -239,9 +238,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
|
|||
QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString();
|
||||
|
||||
if (!overridePath.isEmpty()) {
|
||||
if (!handleRelativeViewpoint(overridePath)){
|
||||
qCDebug(networking) << "User entered path could not be handled as a viewpoint - " << overridePath;
|
||||
}
|
||||
handlePath(overridePath);
|
||||
} else {
|
||||
// take the path that came back
|
||||
const QString PLACE_PATH_KEY = "path";
|
||||
|
@ -251,12 +248,16 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
|
|||
|
||||
if (!returnedPath.isEmpty()) {
|
||||
// try to parse this returned path as a viewpoint, that's the only thing it could be for now
|
||||
if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) {
|
||||
qCDebug(networking) << "Received a location path that was could not be handled as a viewpoint -" << returnedPath;
|
||||
if (!handleViewpoint(returnedPath, shouldFaceViewpoint)) {
|
||||
qCDebug(networking) << "Received a location path that was could not be handled as a viewpoint -"
|
||||
<< returnedPath;
|
||||
}
|
||||
} else {
|
||||
// we didn't override the path or get one back - ask the DS for the viewpoint of its index path
|
||||
// which we will jump to if it exists
|
||||
emit pathChangeRequired(INDEX_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
qCDebug(networking) << "Received an address manager API response with no domain key. Cannot parse.";
|
||||
|
@ -342,7 +343,15 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AddressManager::handleRelativeViewpoint(const QString& lookupString, bool shouldFace) {
|
||||
void AddressManager::handlePath(const QString& path) {
|
||||
if (!handleViewpoint(path)) {
|
||||
qCDebug(networking) << "User entered path could not be handled as a viewpoint - " << path <<
|
||||
"- wll attempt to ask domain-server to resolve.";
|
||||
emit pathChangeRequired(path);
|
||||
}
|
||||
}
|
||||
|
||||
bool AddressManager::handleViewpoint(const QString& viewpointString, bool shouldFace) {
|
||||
const QString FLOAT_REGEX_STRING = "([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)";
|
||||
const QString SPACED_COMMA_REGEX_STRING = "\\s*,\\s*";
|
||||
const QString POSITION_REGEX_STRING = QString("\\/") + FLOAT_REGEX_STRING + SPACED_COMMA_REGEX_STRING +
|
||||
|
@ -353,7 +362,7 @@ bool AddressManager::handleRelativeViewpoint(const QString& lookupString, bool s
|
|||
|
||||
QRegExp positionRegex(POSITION_REGEX_STRING);
|
||||
|
||||
if (positionRegex.indexIn(lookupString) != -1) {
|
||||
if (positionRegex.indexIn(viewpointString) != -1) {
|
||||
// we have at least a position, so emit our signal to say we need to change position
|
||||
glm::vec3 newPosition(positionRegex.cap(1).toFloat(),
|
||||
positionRegex.cap(2).toFloat(),
|
||||
|
@ -365,8 +374,8 @@ bool AddressManager::handleRelativeViewpoint(const QString& lookupString, bool s
|
|||
QRegExp orientationRegex(QUAT_REGEX_STRING);
|
||||
|
||||
// we may also have an orientation
|
||||
if (lookupString[positionRegex.matchedLength() - 1] == QChar('/')
|
||||
&& orientationRegex.indexIn(lookupString, positionRegex.matchedLength() - 1) != -1) {
|
||||
if (viewpointString[positionRegex.matchedLength() - 1] == QChar('/')
|
||||
&& orientationRegex.indexIn(viewpointString, positionRegex.matchedLength() - 1) != -1) {
|
||||
|
||||
glm::quat newOrientation = glm::normalize(glm::quat(orientationRegex.cap(4).toFloat(),
|
||||
orientationRegex.cap(1).toFloat(),
|
||||
|
@ -389,10 +398,10 @@ bool AddressManager::handleRelativeViewpoint(const QString& lookupString, bool s
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const QString GET_USER_LOCATION = "/api/v1/users/%1/location";
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
const QString HIFI_URL_SCHEME = "hifi";
|
||||
const QString DEFAULT_HIFI_ADDRESS = "hifi://entry";
|
||||
const QString INDEX_PATH = "/";
|
||||
|
||||
typedef const glm::vec3& (*PositionGetter)();
|
||||
typedef glm::quat (*OrientationGetter)();
|
||||
|
@ -57,8 +58,10 @@ public:
|
|||
|
||||
public slots:
|
||||
void handleLookupString(const QString& lookupString);
|
||||
|
||||
void goToUser(const QString& username);
|
||||
void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply& reply);
|
||||
bool goToViewpoint(const QString& viewpointString) { return handleViewpoint(viewpointString); }
|
||||
|
||||
void storeCurrentAddress();
|
||||
|
||||
|
@ -74,6 +77,7 @@ signals:
|
|||
void locationChangeRequired(const glm::vec3& newPosition,
|
||||
bool hasOrientationChange, const glm::quat& newOrientation,
|
||||
bool shouldFaceLocation);
|
||||
void pathChangeRequired(const QString& newPath);
|
||||
void rootPlaceNameChanged(const QString& newRootPlaceName);
|
||||
protected:
|
||||
AddressManager();
|
||||
|
@ -88,7 +92,8 @@ private:
|
|||
bool handleUrl(const QUrl& lookupUrl);
|
||||
|
||||
bool handleNetworkAddress(const QString& lookupString);
|
||||
bool handleRelativeViewpoint(const QString& pathSubsection, bool shouldFace = false);
|
||||
void handlePath(const QString& path);
|
||||
bool handleViewpoint(const QString& viewpointString, bool shouldFace = false);
|
||||
bool handleUsername(const QString& lookupString);
|
||||
|
||||
QString _rootPlaceName;
|
||||
|
|
|
@ -46,7 +46,7 @@ void DomainHandler::clearConnectionInfo() {
|
|||
|
||||
if (requiresICE()) {
|
||||
// if we connected to this domain with ICE, re-set the socket so we reconnect through the ice-server
|
||||
_sockAddr.setAddress(QHostAddress::Null);
|
||||
_sockAddr.clear();
|
||||
}
|
||||
|
||||
setIsConnected(false);
|
||||
|
@ -70,7 +70,10 @@ void DomainHandler::hardReset() {
|
|||
_iceDomainID = QUuid();
|
||||
_iceServerSockAddr = HifiSockAddr();
|
||||
_hostname = QString();
|
||||
_sockAddr.setAddress(QHostAddress::Null);
|
||||
_sockAddr.clear();
|
||||
|
||||
// clear any pending path we may have wanted to ask the previous DS about
|
||||
_pendingPath.clear();
|
||||
}
|
||||
|
||||
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
|
||||
|
@ -142,19 +145,25 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname,
|
|||
void DomainHandler::activateICELocalSocket() {
|
||||
_sockAddr = _icePeer.getLocalSocket();
|
||||
_hostname = _sockAddr.getAddress().toString();
|
||||
emit completedSocketDiscovery();
|
||||
}
|
||||
|
||||
void DomainHandler::activateICEPublicSocket() {
|
||||
_sockAddr = _icePeer.getPublicSocket();
|
||||
_hostname = _sockAddr.getAddress().toString();
|
||||
emit completedSocketDiscovery();
|
||||
}
|
||||
|
||||
void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
|
||||
for (int i = 0; i < hostInfo.addresses().size(); i++) {
|
||||
if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
_sockAddr.setAddress(hostInfo.addresses()[i]);
|
||||
|
||||
qCDebug(networking, "DS at %s is at %s", _hostname.toLocal8Bit().constData(),
|
||||
_sockAddr.getAddress().toString().toLocal8Bit().constData());
|
||||
|
||||
emit completedSocketDiscovery();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,12 @@ public:
|
|||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||
void processICEResponsePacket(const QByteArray& icePacket);
|
||||
|
||||
void setPendingPath(const QString& pendingPath) { _pendingPath = pendingPath; }
|
||||
const QString& getPendingPath() { return _pendingPath; }
|
||||
void clearPendingPath() { _pendingPath.clear(); }
|
||||
|
||||
bool isSocketKnown() const { return !_sockAddr.getAddress().isNull(); }
|
||||
|
||||
void softReset();
|
||||
public slots:
|
||||
void setHostnameAndPort(const QString& hostname, quint16 port = DEFAULT_DOMAIN_SERVER_PORT);
|
||||
|
@ -82,8 +88,14 @@ private slots:
|
|||
void settingsRequestFinished();
|
||||
signals:
|
||||
void hostnameChanged(const QString& hostname);
|
||||
|
||||
// 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 connectedToDomain(const QString& hostname);
|
||||
void disconnectedFromDomain();
|
||||
|
||||
void requestICEConnectionAttempt();
|
||||
|
||||
void settingsReceived(const QJsonObject& domainSettingsObject);
|
||||
|
@ -103,6 +115,7 @@ private:
|
|||
bool _isConnected;
|
||||
QJsonObject _settingsObject;
|
||||
int _failedSettingsRequests;
|
||||
QString _pendingPath;
|
||||
};
|
||||
|
||||
#endif // hifi_DomainHandler_h
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
HifiSockAddr(const sockaddr* sockaddr);
|
||||
|
||||
bool isNull() const { return _address.isNull() && _port == 0; }
|
||||
void clear() { _address = QHostAddress::Null; _port = 0;}
|
||||
|
||||
HifiSockAddr& operator=(const HifiSockAddr& rhsSockAddr);
|
||||
void swap(HifiSockAddr& otherSockAddr);
|
||||
|
|
|
@ -54,6 +54,13 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
|
|||
connect(addressManager.data(), &AddressManager::possibleDomainChangeRequiredViaICEForID,
|
||||
&_domainHandler, &DomainHandler::setIceServerHostnameAndID);
|
||||
|
||||
// handle a request for a path change from the AddressManager
|
||||
connect(addressManager.data(), &AddressManager::pathChangeRequired, this, &NodeList::handleDSPathQuery);
|
||||
|
||||
// in case we don't know how to talk to DS when a path change is requested
|
||||
// fire off any pending DS path query when we get socket information
|
||||
connect(&_domainHandler, &DomainHandler::completedSocketDiscovery, this, &NodeList::sendPendingDSPathQuery);
|
||||
|
||||
// clear our NodeList when the domain changes
|
||||
connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, this, &NodeList::reset);
|
||||
|
||||
|
@ -226,6 +233,10 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
|
|||
processSTUNResponse(packet);
|
||||
break;
|
||||
}
|
||||
case PacketTypeDomainServerPathResponse: {
|
||||
handleDSPathQueryResponse(packet);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LimitedNodeList::processNodeData(senderSockAddr, packet);
|
||||
break;
|
||||
|
@ -395,6 +406,102 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
}
|
||||
}
|
||||
|
||||
void NodeList::handleDSPathQuery(const QString& newPath) {
|
||||
if (_domainHandler.isSocketKnown()) {
|
||||
// if we have a DS socket we assume it will get this packet and send if off right away
|
||||
sendDSPathQuery(newPath);
|
||||
} else {
|
||||
// otherwise we make it pending so that it can be sent once a connection is established
|
||||
_domainHandler.setPendingPath(newPath);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::sendPendingDSPathQuery() {
|
||||
|
||||
QString pendingPath = _domainHandler.getPendingPath();
|
||||
|
||||
if (!pendingPath.isEmpty()) {
|
||||
qCDebug(networking) << "Attemping to send pending query to DS for path" << pendingPath;
|
||||
|
||||
// this is a slot triggered if we just established a network link with a DS and want to send a path query
|
||||
sendDSPathQuery(_domainHandler.getPendingPath());
|
||||
|
||||
// clear whatever the pending path was
|
||||
_domainHandler.clearPendingPath();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::sendDSPathQuery(const QString& newPath) {
|
||||
// only send a path query if we know who our DS is or is going to be
|
||||
if (_domainHandler.isSocketKnown()) {
|
||||
// construct the path query packet
|
||||
QByteArray pathQueryPacket = byteArrayWithPopulatedHeader(PacketTypeDomainServerPathQuery);
|
||||
|
||||
// get the UTF8 representation of path query
|
||||
QByteArray pathQueryUTF8 = newPath.toUtf8();
|
||||
|
||||
// get the size of the UTF8 representation of the desired path
|
||||
quint16 numPathBytes = pathQueryUTF8.size();
|
||||
|
||||
if (pathQueryPacket.size() + numPathBytes + sizeof(numPathBytes) < MAX_PACKET_SIZE) {
|
||||
// append the size of the path to the query packet
|
||||
pathQueryPacket.append(reinterpret_cast<char*>(&numPathBytes), sizeof(numPathBytes));
|
||||
|
||||
// append the path itself to the query packet
|
||||
pathQueryPacket.append(pathQueryUTF8);
|
||||
|
||||
qCDebug(networking) << "Sending a path query packet for path" << newPath << "to domain-server at"
|
||||
<< _domainHandler.getSockAddr();
|
||||
|
||||
// send off the path query
|
||||
writeUnverifiedDatagram(pathQueryPacket, _domainHandler.getSockAddr());
|
||||
} else {
|
||||
qCDebug(networking) << "Path" << newPath << "would make PacketTypeDomainServerPathQuery packet > MAX_PACKET_SIZE." <<
|
||||
"Will not send query.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::handleDSPathQueryResponse(const QByteArray& packet) {
|
||||
// This is a response to a path query we theoretically made.
|
||||
// In the future we may want to check that this was actually from our DS and for a query we actually made.
|
||||
|
||||
int numHeaderBytes = numBytesForPacketHeaderGivenPacketType(PacketTypeDomainServerPathResponse);
|
||||
const char* startPosition = packet.data() + numHeaderBytes;
|
||||
const char* currentPosition = startPosition;
|
||||
|
||||
// figure out how many bytes the path query is
|
||||
qint16 numPathBytes;
|
||||
memcpy(&numPathBytes, currentPosition, sizeof(numPathBytes));
|
||||
currentPosition += sizeof(numPathBytes);
|
||||
|
||||
// make sure it is safe to pull the path
|
||||
if (numPathBytes <= packet.size() - numHeaderBytes - (currentPosition - startPosition)) {
|
||||
// pull the path from the packet
|
||||
QString pathQuery = QString::fromUtf8(currentPosition, numPathBytes);
|
||||
currentPosition += numPathBytes;
|
||||
|
||||
// figure out how many bytes the viewpoint is
|
||||
qint16 numViewpointBytes;
|
||||
memcpy(&numViewpointBytes, currentPosition, sizeof(numViewpointBytes));
|
||||
currentPosition += sizeof(numViewpointBytes);
|
||||
|
||||
// make sure it is safe to pull the viewpoint
|
||||
if (numViewpointBytes <= packet.size() - numHeaderBytes - (currentPosition - startPosition)) {
|
||||
// pull the viewpoint from the packet
|
||||
QString viewpoint = QString::fromUtf8(currentPosition, numViewpointBytes);
|
||||
|
||||
// Hand it off to the AddressManager so it can handle it as a relative viewpoint
|
||||
if (DependencyManager::get<AddressManager>()->goToViewpoint(viewpoint)) {
|
||||
qCDebug(networking) << "Going to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery;
|
||||
} else {
|
||||
qCDebug(networking) << "Could not go to viewpoint" << viewpoint
|
||||
<< "which was the lookup result for path" << pathQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::handleICEConnectionToDomainServer() {
|
||||
if (_domainHandler.getICEPeer().isNull()
|
||||
|| _domainHandler.getICEPeer().getConnectionAttempts() >= MAX_ICE_CONNECTION_ATTEMPTS) {
|
||||
|
|
|
@ -71,8 +71,11 @@ public slots:
|
|||
void reset();
|
||||
void sendDomainServerCheckIn();
|
||||
void pingInactiveNodes();
|
||||
void handleDSPathQuery(const QString& newPath);
|
||||
signals:
|
||||
void limitOfSilentDomainCheckInsReached();
|
||||
private slots:
|
||||
void sendPendingDSPathQuery();
|
||||
private:
|
||||
NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile
|
||||
NodeList(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0);
|
||||
|
@ -89,6 +92,10 @@ private:
|
|||
void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode);
|
||||
void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode);
|
||||
|
||||
void handleDSPathQueryResponse(const QByteArray& packet);
|
||||
|
||||
void sendDSPathQuery(const QString& newPath);
|
||||
|
||||
NodeType_t _ownerType;
|
||||
NodeSet _nodeTypesOfInterest;
|
||||
DomainHandler _domainHandler;
|
||||
|
|
|
@ -47,8 +47,8 @@ enum PacketType {
|
|||
PacketTypeMuteEnvironment,
|
||||
PacketTypeAudioStreamStats,
|
||||
PacketTypeDataServerConfirm, // 20
|
||||
UNUSED_1,
|
||||
UNUSED_2,
|
||||
PacketTypeDomainServerPathQuery,
|
||||
PacketTypeDomainServerPathResponse,
|
||||
UNUSED_3,
|
||||
UNUSED_4,
|
||||
UNUSED_5, // 25
|
||||
|
@ -96,7 +96,8 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
|
|||
<< PacketTypeNodeJsonStats << PacketTypeEntityQuery
|
||||
<< PacketTypeOctreeDataNack << PacketTypeEntityEditNack
|
||||
<< PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse
|
||||
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode;
|
||||
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode
|
||||
<< PacketTypeDomainServerPathQuery << PacketTypeDomainServerPathResponse;
|
||||
|
||||
const QSet<PacketType> SEQUENCE_NUMBERED_PACKETS = QSet<PacketType>()
|
||||
<< PacketTypeAvatarData;
|
||||
|
|
|
@ -159,7 +159,7 @@ void HifiConfigVariantMap::addMissingValuesToExistingMap(QVariantMap& existingMa
|
|||
}
|
||||
}
|
||||
|
||||
const QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath) {
|
||||
QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath) {
|
||||
int dotIndex = keyPath.indexOf('.');
|
||||
|
||||
QString firstKey = (dotIndex == -1) ? keyPath : keyPath.mid(0, dotIndex);
|
||||
|
|
|
@ -37,6 +37,6 @@ private:
|
|||
void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap);
|
||||
};
|
||||
|
||||
const QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath);
|
||||
QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath);
|
||||
|
||||
#endif // hifi_HifiConfigVariantMap_h
|
||||
|
|
Loading…
Reference in a new issue