add clearing of known state if client resets ES connection

This commit is contained in:
Stephen Birarda 2017-11-15 14:50:01 -08:00
parent b5d4f6c65f
commit eedb77dae9
11 changed files with 70 additions and 24 deletions

View file

@ -23,6 +23,16 @@ EntityTreeSendThread::EntityTreeSendThread(OctreeServer* myServer, const SharedN
{ {
connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::editingEntityPointer, this, &EntityTreeSendThread::editingEntityPointer, Qt::QueuedConnection); connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::editingEntityPointer, this, &EntityTreeSendThread::editingEntityPointer, Qt::QueuedConnection);
connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::deletingEntityPointer, this, &EntityTreeSendThread::deletingEntityPointer, Qt::QueuedConnection); connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::deletingEntityPointer, this, &EntityTreeSendThread::deletingEntityPointer, Qt::QueuedConnection);
// connect to connection ID change on EntityNodeData so we can clear state for this receiver
auto nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
connect(nodeData, &EntityNodeData::incomingConnectionIDChanged, this, &EntityTreeSendThread::resetKnownState);
}
void EntityTreeSendThread::resetKnownState() {
qCDebug(entities) << "Clearing known EntityTreeSendThread state for" << _nodeUuid;
_knownState.clear();
} }
void EntityTreeSendThread::preDistributionProcessing() { void EntityTreeSendThread::preDistributionProcessing() {

View file

@ -33,6 +33,9 @@ protected:
void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
bool viewFrustumChanged, bool isFullScene) override; bool viewFrustumChanged, bool isFullScene) override;
private slots:
void resetKnownState(); // clears our known state forcing entities to appear unsent
private: private:
// the following two methods return booleans to indicate if any extra flagged entities were new additions to set // the following two methods return booleans to indicate if any extra flagged entities were new additions to set
bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);

View file

@ -59,7 +59,8 @@ protected:
OctreePacketData _packetData; OctreePacketData _packetData;
QWeakPointer<Node> _node; QWeakPointer<Node> _node;
OctreeServer* _myServer { nullptr }; OctreeServer* _myServer { nullptr };
QUuid _nodeUuid;
private: private:
/// Called before a packetDistributor pass to allow for pre-distribution processing /// Called before a packetDistributor pass to allow for pre-distribution processing
virtual void preDistributionProcessing() {}; virtual void preDistributionProcessing() {};
@ -71,8 +72,6 @@ private:
virtual void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene); virtual void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene);
virtual bool shouldTraverseAndSend(OctreeQueryNode* nodeData) { return hasSomethingToSend(nodeData); } virtual bool shouldTraverseAndSend(OctreeQueryNode* nodeData) { return hasSomethingToSend(nodeData); }
QUuid _nodeUuid;
int _truePacketsSent { 0 }; // available for debug stats int _truePacketsSent { 0 }; // available for debug stats
int _trueBytesSent { 0 }; // available for debug stats int _trueBytesSent { 0 }; // available for debug stats
int _packetsSentThisInterval { 0 }; // used for bandwidth throttle condition int _packetsSentThisInterval { 0 }; // used for bandwidth throttle condition

View file

@ -1392,7 +1392,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
updateHeartbeat(); updateHeartbeat();
QTimer* settingsTimer = new QTimer(); QTimer* settingsTimer = new QTimer();
moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{ moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{
connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{ connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{
@ -4482,8 +4481,11 @@ void Application::resetPhysicsReadyInformation() {
void Application::reloadResourceCaches() { void Application::reloadResourceCaches() {
resetPhysicsReadyInformation(); resetPhysicsReadyInformation();
// Query the octree to refresh everything in view // Query the octree to refresh everything in view
_lastQueriedTime = 0; _lastQueriedTime = 0;
_octreeQuery.incrementConnectionID();
queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions); queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
DependencyManager::get<AssetClient>()->clearCache(); DependencyManager::get<AssetClient>()->clearCache();
@ -5544,6 +5546,7 @@ void Application::nodeActivated(SharedNodePointer node) {
// so we will do a proper query during update // so we will do a proper query during update
if (node->getType() == NodeType::EntityServer) { if (node->getType() == NodeType::EntityServer) {
_lastQueriedTime = 0; _lastQueriedTime = 0;
_octreeQuery.incrementConnectionID();
} }
if (node->getType() == NodeType::AudioMixer) { if (node->getType() == NodeType::AudioMixer) {

View file

@ -543,7 +543,7 @@ private:
ViewFrustum _displayViewFrustum; ViewFrustum _displayViewFrustum;
quint64 _lastQueriedTime; quint64 _lastQueriedTime;
OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers OctreeQuery _octreeQuery { true }; // NodeData derived class for querying octee cells from octree servers
std::shared_ptr<controller::StateController> _applicationStateDevice; // Default ApplicationDevice reflecting the state of different properties of the session std::shared_ptr<controller::StateController> _applicationStateDevice; // Default ApplicationDevice reflecting the state of different properties of the session
std::shared_ptr<KeyboardMouseDevice> _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad std::shared_ptr<KeyboardMouseDevice> _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad

View file

@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
return static_cast<PacketVersion>(EntityVersion::HazeEffect); return static_cast<PacketVersion>(EntityVersion::HazeEffect);
case PacketType::EntityQuery: case PacketType::EntityQuery:
return static_cast<PacketVersion>(EntityQueryPacketVersion::JSONFilterWithFamilyTree); return static_cast<PacketVersion>(EntityQueryPacketVersion::ConnectionIdentifier);
case PacketType::AvatarIdentity: case PacketType::AvatarIdentity:
case PacketType::AvatarData: case PacketType::AvatarData:
case PacketType::BulkAvatarData: case PacketType::BulkAvatarData:

View file

@ -209,7 +209,8 @@ enum class EntityScriptCallMethodVersion : PacketVersion {
enum class EntityQueryPacketVersion: PacketVersion { enum class EntityQueryPacketVersion: PacketVersion {
JSONFilter = 18, JSONFilter = 18,
JSONFilterWithFamilyTree = 19 JSONFilterWithFamilyTree = 19,
ConnectionIdentifier = 20
}; };
enum class AssetServerPacketVersion: PacketVersion { enum class AssetServerPacketVersion: PacketVersion {

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <random>
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
#include <GLMHelpers.h> #include <GLMHelpers.h>
@ -22,7 +24,7 @@ const float DEFAULT_ASPECT_RATIO = 1.0f;
const float DEFAULT_NEAR_CLIP = 0.1f; const float DEFAULT_NEAR_CLIP = 0.1f;
const float DEFAULT_FAR_CLIP = 3.0f; const float DEFAULT_FAR_CLIP = 3.0f;
OctreeQuery::OctreeQuery() : OctreeQuery::OctreeQuery(bool randomizeConnectionID) :
_cameraFov(DEFAULT_FOV), _cameraFov(DEFAULT_FOV),
_cameraAspectRatio(DEFAULT_ASPECT_RATIO), _cameraAspectRatio(DEFAULT_ASPECT_RATIO),
_cameraNearClip(DEFAULT_NEAR_CLIP), _cameraNearClip(DEFAULT_NEAR_CLIP),
@ -30,10 +32,21 @@ OctreeQuery::OctreeQuery() :
_cameraCenterRadius(DEFAULT_FAR_CLIP) _cameraCenterRadius(DEFAULT_FAR_CLIP)
{ {
_maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS;
if (randomizeConnectionID) {
// randomize our initial octree query connection ID using random_device
// the connection ID is 16 bits so we take a generated 32 bit value from random device and chop off the top
std::random_device randomDevice;
_connectionID = randomDevice();
}
} }
int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
unsigned char* bufferStart = destinationBuffer; unsigned char* bufferStart = destinationBuffer;
// pack the connection ID so the server can detect when we start a new connection
memcpy(destinationBuffer, &_connectionID, sizeof(_connectionID));
destinationBuffer += sizeof(_connectionID);
// back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum // back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum
memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum)); memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum));
@ -98,7 +111,27 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(message.getRawMessage()); const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(message.getRawMessage());
const unsigned char* sourceBuffer = startPosition; const unsigned char* sourceBuffer = startPosition;
// unpack the connection ID
uint16_t newConnectionID;
memcpy(&newConnectionID, sourceBuffer, sizeof(newConnectionID));
sourceBuffer += sizeof(newConnectionID);
if (!_hasReceivedFirstQuery) {
// set our flag to indicate that we've parsed for this query at least once
_hasReceivedFirstQuery = true;
// set the incoming connection ID as the current
_connectionID = newConnectionID;
} else {
if (newConnectionID != _connectionID) {
// the connection ID has changed - emit our signal so the server
// knows that the client is starting a new session
_connectionID = newConnectionID;
emit incomingConnectionIDChanged();
}
}
// check if this query uses a view frustum // check if this query uses a view frustum
memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum)); memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum));
sourceBuffer += sizeof(_usesFrustum); sourceBuffer += sizeof(_usesFrustum);

View file

@ -27,11 +27,11 @@ class OctreeQuery : public NodeData {
Q_OBJECT Q_OBJECT
public: public:
OctreeQuery(); OctreeQuery(bool randomizeConnectionID = false);
virtual ~OctreeQuery() {} virtual ~OctreeQuery() {}
int getBroadcastData(unsigned char* destinationBuffer); int getBroadcastData(unsigned char* destinationBuffer);
virtual int parseData(ReceivedMessage& message) override; int parseData(ReceivedMessage& message) override;
// getters for camera details // getters for camera details
const glm::vec3& getCameraPosition() const { return _cameraPosition; } const glm::vec3& getCameraPosition() const { return _cameraPosition; }
@ -68,6 +68,13 @@ public:
bool getUsesFrustum() { return _usesFrustum; } bool getUsesFrustum() { return _usesFrustum; }
void setUsesFrustum(bool usesFrustum) { _usesFrustum = usesFrustum; } void setUsesFrustum(bool usesFrustum) { _usesFrustum = usesFrustum; }
void incrementConnectionID() { ++_connectionID; }
bool hasReceivedFirstQuery() const { return _hasReceivedFirstQuery; }
signals:
void incomingConnectionIDChanged();
public slots: public slots:
void setMaxQueryPacketsPerSecond(int maxQueryPPS) { _maxQueryPPS = maxQueryPPS; } void setMaxQueryPacketsPerSecond(int maxQueryPPS) { _maxQueryPPS = maxQueryPPS; }
void setOctreeSizeScale(float octreeSizeScale) { _octreeElementSizeScale = octreeSizeScale; } void setOctreeSizeScale(float octreeSizeScale) { _octreeElementSizeScale = octreeSizeScale; }
@ -90,9 +97,12 @@ protected:
int _boundaryLevelAdjust = 0; /// used for LOD calculations int _boundaryLevelAdjust = 0; /// used for LOD calculations
uint8_t _usesFrustum = true; uint8_t _usesFrustum = true;
uint16_t _connectionID; // query connection ID, randomized to start, increments with each new connection to server
QJsonObject _jsonParameters; QJsonObject _jsonParameters;
QReadWriteLock _jsonParametersLock; QReadWriteLock _jsonParametersLock;
bool _hasReceivedFirstQuery { false };
private: private:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called

View file

@ -18,13 +18,6 @@
#include <SharedUtil.h> #include <SharedUtil.h>
#include <UUID.h> #include <UUID.h>
int OctreeQueryNode::parseData(ReceivedMessage& message) {
// set our flag to indicate that we've parsed for this query at least once
_hasReceivedFirstQuery = true;
return OctreeQuery::parseData(message);
}
void OctreeQueryNode::nodeKilled() { void OctreeQueryNode::nodeKilled() {
_isShuttingDown = true; _isShuttingDown = true;
} }

View file

@ -35,8 +35,6 @@ public:
void init(); // called after creation to set up some virtual items void init(); // called after creation to set up some virtual items
virtual PacketType getMyPacketType() const = 0; virtual PacketType getMyPacketType() const = 0;
virtual int parseData(ReceivedMessage& message) override;
void resetOctreePacket(); // resets octree packet to after "V" header void resetOctreePacket(); // resets octree packet to after "V" header
void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet
@ -108,8 +106,6 @@ public:
bool shouldForceFullScene() const { return _shouldForceFullScene; } bool shouldForceFullScene() const { return _shouldForceFullScene; }
void setShouldForceFullScene(bool shouldForceFullScene) { _shouldForceFullScene = shouldForceFullScene; } void setShouldForceFullScene(bool shouldForceFullScene) { _shouldForceFullScene = shouldForceFullScene; }
bool hasReceivedFirstQuery() const { return _hasReceivedFirstQuery; }
private: private:
OctreeQueryNode(const OctreeQueryNode &); OctreeQueryNode(const OctreeQueryNode &);
OctreeQueryNode& operator= (const OctreeQueryNode&); OctreeQueryNode& operator= (const OctreeQueryNode&);
@ -157,8 +153,6 @@ private:
QJsonObject _lastCheckJSONParameters; QJsonObject _lastCheckJSONParameters;
bool _shouldForceFullScene { false }; bool _shouldForceFullScene { false };
bool _hasReceivedFirstQuery { false };
}; };
#endif // hifi_OctreeQueryNode_h #endif // hifi_OctreeQueryNode_h