From 8d19395b0a78aae5b448f62cdf20fc19f7f6ce8b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 14 Jun 2017 16:04:52 -0700 Subject: [PATCH 1/5] ignore remote update younger than recent bid --- libraries/entities/src/EntityItem.cpp | 32 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 530e356137..17de15e32b 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -386,7 +386,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef return 0; } - qint64 clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0; + int64_t clockSkew = 0; + uint64_t maxPingRoundTrip = 33333; // two frames periods at 60 fps + if (args.sourceNode) { + clockSkew = args.sourceNode->getClockSkewUsec(); + const float MSECS_PER_USEC = 1000; + maxPingRoundTrip += args.sourceNode->getPingMs() * MSECS_PER_USEC; + } BufferParser parser(data, bytesLeftToRead); @@ -653,7 +659,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef const QUuid& myNodeID = nodeList->getSessionUUID(); bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); - // pack SimulationOwner and terse update properties near each other // NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data // even when we would otherwise ignore the rest of the packet. @@ -678,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) { // entity-server is trying to clear our ownership (probably at our own request) // but we actually want to own it, therefore we ignore this clear event - // and pretend that we own it (we assume we'll recover it soon) + // and pretend that we own it (e.g. we assume we'll receive ownership soon) // However, for now, when the server uses a newer time than what we sent, listen to what we're told. if (overwriteLocalData) { @@ -690,16 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); } - } else if (newSimOwner.getID().isNull() && _simulationOwner.pendingTake(lastEditedFromBufferAdjusted)) { - // entity-server is trying to clear someone else's ownership - // but we want to own it, therefore we ignore this clear event - // and pretend that we own it (we assume we'll get it soon) + } else if (_simulationOwner.pendingTake(now - maxPingRoundTrip)) { + // we sent a bid before this packet could have been sent from the server + // so we ignore it and pretend we own the object's simulation weOwnSimulation = true; - if (!_simulationOwner.isNull()) { - // someone else really did own it - markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); - somethingChanged = true; - _simulationOwner.clearCurrentOwner(); + if (newSimOwner.getID().isNull()) { + // entity-server is trying to clear someone else's ownership + // but we want to own it, therefore we ignore this clear event + if (!_simulationOwner.isNull()) { + // someone else really did own it + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); + somethingChanged = true; + _simulationOwner.clearCurrentOwner(); + } } } else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) { // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, From b105ad83380e6a7f5485b71bb2898521f47b85cc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 16 Jun 2017 16:55:00 -0700 Subject: [PATCH 2/5] measure linear velocity of tractor position --- libraries/physics/src/ObjectActionTractor.cpp | 35 ++++++++++++------- libraries/physics/src/ObjectActionTractor.h | 1 + 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libraries/physics/src/ObjectActionTractor.cpp b/libraries/physics/src/ObjectActionTractor.cpp index 4bb5d850a9..1a1790b0e0 100644 --- a/libraries/physics/src/ObjectActionTractor.cpp +++ b/libraries/physics/src/ObjectActionTractor.cpp @@ -23,14 +23,16 @@ const uint16_t ObjectActionTractor::tractorVersion = 1; ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer ownerEntity) : ObjectAction(DYNAMIC_TYPE_TRACTOR, id, ownerEntity), - _positionalTarget(glm::vec3(0.0f)), - _desiredPositionalTarget(glm::vec3(0.0f)), + _positionalTarget(0.0f), + _desiredPositionalTarget(0.0f), _linearTimeScale(FLT_MAX), - _positionalTargetSet(true), - _rotationalTarget(glm::quat()), - _desiredRotationalTarget(glm::quat()), + _positionalTargetSet(false), + _rotationalTarget(), + _desiredRotationalTarget(), _angularTimeScale(FLT_MAX), - _rotationalTargetSet(true) { + _rotationalTargetSet(true), + _linearVelocityTarget(0.0f) +{ #if WANT_DEBUG qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor"; #endif @@ -77,7 +79,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) { glm::quat rotation; glm::vec3 position; - glm::vec3 linearVelocity; glm::vec3 angularVelocity; bool linearValid = false; @@ -117,7 +118,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) { linearValid = true; linearTractorCount++; position += positionForAction; - linearVelocity += linearVelocityForAction; } } } @@ -126,9 +126,18 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) { withWriteLock([&]{ if (linearValid && linearTractorCount > 0) { position /= linearTractorCount; - linearVelocity /= linearTractorCount; + if (_positionalTargetSet) { + _lastPositionTarget = _positionalTarget; + } else { + _lastPositionTarget = position; + } _positionalTarget = position; - _linearVelocityTarget = linearVelocity; + if (deltaTimeStep > EPSILON) { + // blend the new velocity with the old (low-pass filter) + glm::vec3 newVelocity = (1.0f / deltaTimeStep) * (position - _lastPositionTarget); + const float blend = 0.25f; + _linearVelocityTarget = (1.0f - blend) * _linearVelocityTarget + blend * newVelocity; + } _positionalTargetSet = true; _active = true; } @@ -169,19 +178,19 @@ void ObjectActionTractor::updateActionWorker(btScalar deltaTimeStep) { } if (_linearTimeScale < MAX_TRACTOR_TIMESCALE) { - btVector3 targetVelocity(0.0f, 0.0f, 0.0f); + btVector3 offsetVelocity(0.0f, 0.0f, 0.0f); btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget); float offsetLength = offset.length(); if (offsetLength > FLT_EPSILON) { float speed = glm::min(offsetLength / _linearTimeScale, TRACTOR_MAX_SPEED); - targetVelocity = (-speed / offsetLength) * offset; + offsetVelocity = (-speed / offsetLength) * offset; if (speed > rigidBody->getLinearSleepingThreshold()) { forceBodyNonStatic(); rigidBody->activate(); } } // this action is aggresively critically damped and defeats the current velocity - rigidBody->setLinearVelocity(targetVelocity); + rigidBody->setLinearVelocity(glmToBullet(_linearVelocityTarget) + offsetVelocity); } if (_angularTimeScale < MAX_TRACTOR_TIMESCALE) { diff --git a/libraries/physics/src/ObjectActionTractor.h b/libraries/physics/src/ObjectActionTractor.h index c629d84998..a17526f5f9 100644 --- a/libraries/physics/src/ObjectActionTractor.h +++ b/libraries/physics/src/ObjectActionTractor.h @@ -36,6 +36,7 @@ protected: glm::vec3 _positionalTarget; glm::vec3 _desiredPositionalTarget; + glm::vec3 _lastPositionTarget; float _linearTimeScale; bool _positionalTargetSet; From 36ff765d7f15a54a9ab19e5872ad38cd28bf7de2 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Sun, 18 Jun 2017 22:19:28 +0200 Subject: [PATCH 3/5] Make sure registered object have different name from iport alias --- interface/resources/qml/hifi/audio/Audio.qml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index a30aba2a6b..929752f925 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -18,7 +18,7 @@ import QtQuick.Layouts 1.3 import "../../styles-uit" import "../../controls-uit" as HifiControls import "../../windows" -import "./" as Audio +import "./" as AudioControls Rectangle { id: root; @@ -57,7 +57,7 @@ Rectangle { x: 16; // padding does not work spacing: 16; - Audio.CheckBox { + AudioControls.CheckBox { text: qsTr("Mute microphone"); checked: Audio.muted; onClicked: { @@ -65,7 +65,7 @@ Rectangle { checked = Qt.binding(function() { return Audio.muted; }); // restore binding } } - Audio.CheckBox { + AudioControls.CheckBox { text: qsTr("Enable noise reduction"); checked: Audio.noiseReduction; onClicked: { @@ -73,7 +73,7 @@ Rectangle { checked = Qt.binding(function() { return Audio.noiseReduction; }); // restore binding } } - Audio.CheckBox { + AudioControls.CheckBox { text: qsTr("Show audio level meter"); checked: AvatarInputs.showAudioTools; onClicked: { @@ -110,7 +110,7 @@ Rectangle { delegate: Item { width: parent.width; height: 36; - Audio.CheckBox { + AudioControls.CheckBox { text: display; checked: selected; onClicked: { @@ -148,7 +148,7 @@ Rectangle { delegate: Item { width: parent.width; height: 36; - Audio.CheckBox { + AudioControls.CheckBox { text: display; checked: selected; onClicked: { From 0c7f1cda0f7828b1952f5af40febdf3eb3e80aaa Mon Sep 17 00:00:00 2001 From: seefo Date: Mon, 19 Jun 2017 15:01:50 -0700 Subject: [PATCH 4/5] Added a restart button to domain server settings page --- domain-server/resources/web/header.html | 16 +++++++++- .../resources/web/js/domain-server.js | 31 +++++++++++++++++++ .../resources/web/settings/index.shtml | 13 -------- .../resources/web/settings/js/settings.js | 25 --------------- domain-server/src/DomainServer.cpp | 5 +++ 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/domain-server/resources/web/header.html b/domain-server/resources/web/header.html index 965f86b0a1..0dc08e6e31 100644 --- a/domain-server/resources/web/header.html +++ b/domain-server/resources/web/header.html @@ -10,7 +10,6 @@ - + + +
diff --git a/domain-server/resources/web/js/domain-server.js b/domain-server/resources/web/js/domain-server.js index 3f78d8f466..88ab7b1470 100644 --- a/domain-server/resources/web/js/domain-server.js +++ b/domain-server/resources/web/js/domain-server.js @@ -1,3 +1,28 @@ +function showRestartModal() { + $('#restart-modal').modal({ + backdrop: 'static', + keyboard: false + }); + + var secondsElapsed = 0; + var numberOfSecondsToWait = 3; + + var refreshSpan = $('span#refresh-time') + refreshSpan.html(numberOfSecondsToWait + " seconds"); + + // call ourselves every 1 second to countdown + var refreshCountdown = setInterval(function(){ + secondsElapsed++; + secondsLeft = numberOfSecondsToWait - secondsElapsed + refreshSpan.html(secondsLeft + (secondsLeft == 1 ? " second" : " seconds")) + + if (secondsElapsed == numberOfSecondsToWait) { + location.reload(true); + clearInterval(refreshCountdown); + } + }, 1000); +} + $(document).ready(function(){ var url = window.location; // Will only work if string in href matches with location @@ -7,4 +32,10 @@ $(document).ready(function(){ $('ul.nav a').filter(function() { return this.href == url; }).parent().addClass('active'); + + $('body').on('click', '#restart-server', function(e){ + $.get("/restart"); + showRestartModal(); + return false; + }); }); \ No newline at end of file diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 1812c52dad..92ba7cf988 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -81,19 +81,6 @@
- - diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index 39628ebb11..35573e4300 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -1656,31 +1656,6 @@ function updateDataChangedForSiblingRows(row, forceTrue) { }) } -function showRestartModal() { - $('#restart-modal').modal({ - backdrop: 'static', - keyboard: false - }); - - var secondsElapsed = 0; - var numberOfSecondsToWait = 3; - - var refreshSpan = $('span#refresh-time') - refreshSpan.html(numberOfSecondsToWait + " seconds"); - - // call ourselves every 1 second to countdown - var refreshCountdown = setInterval(function(){ - secondsElapsed++; - secondsLeft = numberOfSecondsToWait - secondsElapsed - refreshSpan.html(secondsLeft + (secondsLeft == 1 ? " second" : " seconds")) - - if (secondsElapsed == numberOfSecondsToWait) { - location.reload(true); - clearInterval(refreshCountdown); - } - }, 1000); -} - function cleanupFormValues(node) { if (node.type && node.type === 'checkbox') { return { name: node.name, value: node.checked ? true : false }; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index d637a20454..0c1ebbf189 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1650,6 +1650,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString URI_NODES = "/nodes"; const QString URI_SETTINGS = "/settings"; const QString URI_ENTITY_FILE_UPLOAD = "/content/upload"; + const QString URI_RESTART = "/restart"; const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; @@ -1804,6 +1805,10 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url // send the response connection->respond(HTTPConnection::StatusCode200, nodesDocument.toJson(), qPrintable(JSON_MIME_TYPE)); + return true; + } else if (url.path() == URI_RESTART) { + connection->respond(HTTPConnection::StatusCode200); + restart(); return true; } else { // check if this is for json stats for a node From cf9a97cf101bb6003f8f50579e595efc74e751ae Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 9 Jun 2017 11:56:52 -0700 Subject: [PATCH 5/5] use length sent by AssetServer to verify asset size --- libraries/networking/src/AssetClient.cpp | 18 ++++++++++++------ libraries/networking/src/AssetClient.h | 2 +- libraries/networking/src/AssetRequest.cpp | 7 +------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 054557e920..3faa9981dc 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -353,13 +353,20 @@ void AssetClient::handleAssetGetReply(QSharedPointer message, S connect(message.data(), &ReceivedMessage::progress, this, [this, weakNode, messageID, length](qint64 size) { handleProgressCallback(weakNode, messageID, size, length); }); - connect(message.data(), &ReceivedMessage::completed, this, [this, weakNode, messageID]() { - handleCompleteCallback(weakNode, messageID); + connect(message.data(), &ReceivedMessage::completed, this, [this, weakNode, messageID, length]() { + handleCompleteCallback(weakNode, messageID, length); }); if (message->isComplete()) { disconnect(message.data(), nullptr, this, nullptr); - callbacks.completeCallback(true, error, message->readAll()); + + if (length != message->getBytesLeftToRead()) { + callbacks.completeCallback(false, error, QByteArray()); + } else { + callbacks.completeCallback(true, error, message->readAll()); + } + + messageCallbackMap.erase(requestIt); } } @@ -391,7 +398,7 @@ void AssetClient::handleProgressCallback(const QWeakPointer& node, Message callbacks.progressCallback(size, length); } -void AssetClient::handleCompleteCallback(const QWeakPointer& node, MessageID messageID) { +void AssetClient::handleCompleteCallback(const QWeakPointer& node, MessageID messageID, DataOffset length) { auto senderNode = node.toStrongRef(); if (!senderNode) { @@ -424,8 +431,7 @@ void AssetClient::handleCompleteCallback(const QWeakPointer& node, Message return; } - - if (message->failed()) { + if (message->failed() || length != message->getBytesLeftToRead()) { callbacks.completeCallback(false, AssetServerError::NoError, QByteArray()); } else { callbacks.completeCallback(true, AssetServerError::NoError, message->readAll()); diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index 6f9cc3cd31..cab4a4f5b0 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -93,7 +93,7 @@ private: bool cancelUploadAssetRequest(MessageID id); void handleProgressCallback(const QWeakPointer& node, MessageID messageID, qint64 size, DataOffset length); - void handleCompleteCallback(const QWeakPointer& node, MessageID messageID); + void handleCompleteCallback(const QWeakPointer& node, MessageID messageID, DataOffset length); void forceFailureOfPendingRequests(SharedNodePointer node); diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 00fa3d9f2f..7fa563d4ad 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -104,12 +104,7 @@ void AssetRequest::start() { break; } } else { - if (_byteRange.isSet()) { - // we had a byte range, the size of the data does not match what we expect, so we return an error - if (data.size() != _byteRange.size()) { - _error = SizeVerificationFailed; - } - } else if (hashData(data).toHex() != _hash) { + if (!_byteRange.isSet() && hashData(data).toHex() != _hash) { // the hash of the received data does not match what we expect, so we return an error _error = HashVerificationFailed; }