don't unpack avatar identity that is old

This commit is contained in:
Stephen Birarda 2017-06-14 14:02:22 -07:00
parent 9be016fd3e
commit 50b56ec761
7 changed files with 98 additions and 85 deletions

View file

@ -510,12 +510,9 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
AvatarData& avatar = nodeData->getAvatar(); AvatarData& avatar = nodeData->getAvatar();
// parse the identity packet and update the change timestamp if appropriate // parse the identity packet and update the change timestamp if appropriate
AvatarData::Identity identity;
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
bool identityChanged = false; bool identityChanged = false;
bool displayNameChanged = false; bool displayNameChanged = false;
avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged); avatar.processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
if (identityChanged) { if (identityChanged) {
QMutexLocker nodeDataLocker(&nodeData->getMutex()); QMutexLocker nodeDataLocker(&nodeData->getMutex());
nodeData->flagIdentityChange(); nodeData->flagIdentityChange();

View file

@ -1473,27 +1473,6 @@ QStringList AvatarData::getJointNames() const {
return _jointNames; return _jointNames;
} }
void AvatarData::parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut) {
QDataStream packetStream(data);
packetStream >> identityOut.uuid
>> identityOut.skeletonModelURL
>> identityOut.attachmentData
>> identityOut.displayName
>> identityOut.sessionDisplayName
>> identityOut.avatarEntityData
>> identityOut.sequenceId;
#ifdef WANT_DEBUG
qCDebug(avatars) << __FUNCTION__
<< "identityOut.uuid:" << identityOut.uuid
<< "identityOut.skeletonModelURL:" << identityOut.skeletonModelURL
<< "identityOut.displayName:" << identityOut.displayName
<< "identityOut.sessionDisplayName:" << identityOut.sessionDisplayName;
#endif
}
glm::quat AvatarData::getOrientationOutbound() const { glm::quat AvatarData::getOrientationOutbound() const {
return (getLocalOrientation()); return (getLocalOrientation());
} }
@ -1504,46 +1483,80 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const {
return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL; return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL;
} }
void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged) { void AvatarData::processAvatarIdentity(const QByteArray& identityData, bool& identityChanged, bool& displayNameChanged) {
if (identity.sequenceId < _identitySequenceId) { QDataStream packetStream(identityData);
qCDebug(avatars) << "Ignoring older identity packet for avatar" << getSessionUUID()
<< "_identitySequenceId (" << _identitySequenceId << ") is greater than" << identity.sequenceId; QUuid avatarSessionID;
return;
// peek the sequence number, this will tell us if we should be processing this identity packet at all
udt::SequenceNumber::Type incomingSequenceNumberType;
packetStream >> avatarSessionID >> incomingSequenceNumberType;
udt::SequenceNumber incomingSequenceNumber(incomingSequenceNumberType);
if (!_hasProcessedFirstIdentity) {
_identitySequenceNumber = incomingSequenceNumber - 1;
_hasProcessedFirstIdentity = true;
qCDebug(avatars) << "Processing first identity packet for" << avatarSessionID << "-"
<< (udt::SequenceNumber::Type) incomingSequenceNumber;
} }
// otherwise, set the identitySequenceId to match the incoming identity
_identitySequenceId = identity.sequenceId;
if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) { if (incomingSequenceNumber > _identitySequenceNumber) {
setSkeletonModelURL(identity.skeletonModelURL); Identity identity;
identityChanged = true;
if (_firstSkeletonCheck) { packetStream >> identity.skeletonModelURL
>> identity.attachmentData
>> identity.displayName
>> identity.sessionDisplayName
>> identity.avatarEntityData;
// set the store identity sequence number to match the incoming identity
_identitySequenceNumber = incomingSequenceNumber;
if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) {
setSkeletonModelURL(identity.skeletonModelURL);
identityChanged = true;
if (_firstSkeletonCheck) {
displayNameChanged = true;
}
_firstSkeletonCheck = false;
}
if (identity.displayName != _displayName) {
_displayName = identity.displayName;
identityChanged = true;
displayNameChanged = true; displayNameChanged = true;
} }
_firstSkeletonCheck = false; maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
}
if (identity.displayName != _displayName) { if (identity.attachmentData != _attachmentData) {
_displayName = identity.displayName; setAttachmentData(identity.attachmentData);
identityChanged = true; identityChanged = true;
displayNameChanged = true; }
}
maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
if (identity.attachmentData != _attachmentData) { bool avatarEntityDataChanged = false;
setAttachmentData(identity.attachmentData); _avatarEntitiesLock.withReadLock([&] {
identityChanged = true; avatarEntityDataChanged = (identity.avatarEntityData != _avatarEntityData);
} });
bool avatarEntityDataChanged = false; if (avatarEntityDataChanged) {
_avatarEntitiesLock.withReadLock([&] { setAvatarEntityData(identity.avatarEntityData);
avatarEntityDataChanged = (identity.avatarEntityData != _avatarEntityData); identityChanged = true;
}); }
if (avatarEntityDataChanged) {
setAvatarEntityData(identity.avatarEntityData);
identityChanged = true;
}
#ifdef WANT_DEBUG
qCDebug(avatars) << __FUNCTION__
<< "identity.uuid:" << identity.uuid
<< "identity.skeletonModelURL:" << identity.skeletonModelURL
<< "identity.displayName:" << identity.displayName
<< "identity.sessionDisplayName:" << identity.sessionDisplayName;
#endif
} else {
qCDebug(avatars) << "Refusing to process identity for" << uuidStringWithoutCurlyBraces(avatarSessionID) << "since"
<< (udt::SequenceNumber::Type) _identitySequenceNumber
<< "is later than" << (udt::SequenceNumber::Type) incomingSequenceNumber;
}
} }
QByteArray AvatarData::identityByteArray() const { QByteArray AvatarData::identityByteArray() const {
@ -1553,12 +1566,12 @@ QByteArray AvatarData::identityByteArray() const {
_avatarEntitiesLock.withReadLock([&] { _avatarEntitiesLock.withReadLock([&] {
identityStream << getSessionUUID() identityStream << getSessionUUID()
<< urlToSend << (udt::SequenceNumber::Type) _identitySequenceNumber
<< _attachmentData << urlToSend
<< _displayName << _attachmentData
<< getSessionDisplayNameForTransport() // depends on _sessionDisplayName << _displayName
<< _avatarEntityData << getSessionDisplayNameForTransport() // depends on _sessionDisplayName
<< _identitySequenceId; << _avatarEntityData;
}); });
return identityData; return identityData;
@ -2340,6 +2353,8 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
_avatarEntityData = avatarEntityData; _avatarEntityData = avatarEntityData;
setAvatarEntityDataChanged(true); setAvatarEntityDataChanged(true);
qDebug() << "Current avatar entity data is" << _avatarEntityData.keys();
foreach (auto entityID, previousAvatarEntityIDs) { foreach (auto entityID, previousAvatarEntityIDs) {
if (!_avatarEntityData.contains(entityID)) { if (!_avatarEntityData.contains(entityID)) {
_avatarEntityDetached.insert(entityID); _avatarEntityDetached.insert(entityID);

View file

@ -52,15 +52,16 @@ typedef unsigned long long quint64;
#include <JointData.h> #include <JointData.h>
#include <NLPacket.h> #include <NLPacket.h>
#include <Node.h> #include <Node.h>
#include <RegisteredMetaTypes.h>
#include <SimpleMovingAverage.h>
#include <SpatiallyNestable.h>
#include <NumericalConstants.h> #include <NumericalConstants.h>
#include <Packed.h> #include <Packed.h>
#include <ThreadSafeValueCache.h> #include <RegisteredMetaTypes.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <shared/RateCounter.h> #include <SimpleMovingAverage.h>
#include <SpatiallyNestable.h>
#include <ThreadSafeValueCache.h>
#include <ViewFrustum.h> #include <ViewFrustum.h>
#include <shared/RateCounter.h>
#include <udt/SequenceNumber.h>
#include "AABox.h" #include "AABox.h"
#include "HeadData.h" #include "HeadData.h"
@ -525,20 +526,16 @@ public:
const HeadData* getHeadData() const { return _headData; } const HeadData* getHeadData() const { return _headData; }
struct Identity { struct Identity {
QUuid uuid;
QUrl skeletonModelURL; QUrl skeletonModelURL;
QVector<AttachmentData> attachmentData; QVector<AttachmentData> attachmentData;
QString displayName; QString displayName;
QString sessionDisplayName; QString sessionDisplayName;
AvatarEntityMap avatarEntityData; AvatarEntityMap avatarEntityData;
quint64 sequenceId;
}; };
static void parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut);
// identityChanged returns true if identity has changed, false otherwise. // identityChanged returns true if identity has changed, false otherwise.
// displayNameChanged returns true if displayName has changed, false otherwise. // displayNameChanged returns true if displayName has changed, false otherwise.
void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged); void processAvatarIdentity(const QByteArray& identityData, bool& identityChanged, bool& displayNameChanged);
QByteArray identityByteArray() const; QByteArray identityByteArray() const;
@ -626,7 +623,7 @@ public:
bool getIdentityDataChanged() const { return _identityDataChanged; } // has the identity data changed since the last time sendIdentityPacket() was called bool getIdentityDataChanged() const { return _identityDataChanged; } // has the identity data changed since the last time sendIdentityPacket() was called
void markIdentityDataChanged() { void markIdentityDataChanged() {
_identityDataChanged = true; _identityDataChanged = true;
_identitySequenceId++; ++_identitySequenceNumber;
} }
float getDensity() const { return _density; } float getDensity() const { return _density; }
@ -786,7 +783,8 @@ protected:
float _audioAverageLoudness { 0.0f }; float _audioAverageLoudness { 0.0f };
bool _identityDataChanged { false }; bool _identityDataChanged { false };
quint64 _identitySequenceId { 0 }; udt::SequenceNumber _identitySequenceNumber { 0 };
bool _hasProcessedFirstIdentity { false };
float _density; float _density;
private: private:

View file

@ -126,8 +126,9 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessag
} }
void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) { void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
AvatarData::Identity identity;
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity); // peek the avatar UUID from the incoming packet
QUuid identityUUID = message->peek(NUM_BYTES_RFC4122_UUID);
// make sure this isn't for an ignored avatar // make sure this isn't for an ignored avatar
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -136,20 +137,21 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
{ {
QReadLocker locker(&_hashLock); QReadLocker locker(&_hashLock);
auto me = _avatarHash.find(EMPTY); auto me = _avatarHash.find(EMPTY);
if ((me != _avatarHash.end()) && (identity.uuid == me.value()->getSessionUUID())) { if ((me != _avatarHash.end()) && (identityUUID == me.value()->getSessionUUID())) {
// We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an // We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an
// identity packet for ourself (such as when we are assigned a sessionDisplayName by the mixer upon joining), // identity packet for ourself (such as when we are assigned a sessionDisplayName by the mixer upon joining),
// we make things match here. // we make things match here.
identity.uuid = EMPTY; identityUUID = EMPTY;
} }
} }
if (!nodeList->isIgnoringNode(identity.uuid) || nodeList->getRequestsDomainListData()) {
if (!nodeList->isIgnoringNode(identityUUID) || nodeList->getRequestsDomainListData()) {
// mesh URL for a UUID, find avatar in our list // mesh URL for a UUID, find avatar in our list
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode); auto avatar = newOrExistingAvatar(identityUUID, sendingNode);
bool identityChanged = false; bool identityChanged = false;
bool displayNameChanged = false; bool displayNameChanged = false;
// In this case, the "sendingNode" is the Avatar Mixer. // In this case, the "sendingNode" is the Avatar Mixer.
avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged); avatar->processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
} }
} }

View file

@ -59,7 +59,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::AvatarData: case PacketType::AvatarData:
case PacketType::BulkAvatarData: case PacketType::BulkAvatarData:
case PacketType::KillAvatar: case PacketType::KillAvatar:
return static_cast<PacketVersion>(AvatarMixerPacketVersion::AvatarIdentitySequenceId); return static_cast<PacketVersion>(AvatarMixerPacketVersion::AvatarIdentitySequenceFront);
case PacketType::MessagesData: case PacketType::MessagesData:
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData); return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
case PacketType::ICEServerHeartbeat: case PacketType::ICEServerHeartbeat:

View file

@ -243,7 +243,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
AvatarAsChildFixes, AvatarAsChildFixes,
StickAndBallDefaultAvatar, StickAndBallDefaultAvatar,
IdentityPacketsIncludeUpdateTime, IdentityPacketsIncludeUpdateTime,
AvatarIdentitySequenceId AvatarIdentitySequenceId,
AvatarIdentitySequenceFront
}; };
enum class DomainConnectRequestVersion : PacketVersion { enum class DomainConnectRequestVersion : PacketVersion {

View file

@ -35,8 +35,8 @@ public:
explicit SequenceNumber(char* value) { _value = (*reinterpret_cast<int32_t*>(value)) & MAX; } explicit SequenceNumber(char* value) { _value = (*reinterpret_cast<int32_t*>(value)) & MAX; }
explicit SequenceNumber(Type value) { _value = (value <= MAX) ? ((value >= 0) ? value : 0) : MAX; } explicit SequenceNumber(Type value) { _value = (value <= MAX) ? ((value >= 0) ? value : 0) : MAX; }
explicit SequenceNumber(UType value) { _value = (value <= MAX) ? value : MAX; } explicit SequenceNumber(UType value) { _value = (value <= MAX) ? value : MAX; }
explicit operator Type() { return _value; } explicit operator Type() const { return _value; }
explicit operator UType() { return static_cast<UType>(_value); } explicit operator UType() const { return static_cast<UType>(_value); }
inline SequenceNumber& operator++() { inline SequenceNumber& operator++() {
_value = (_value + 1) % (MAX + 1); _value = (_value + 1) % (MAX + 1);